Search code examples
javaandroidpositionsizepercentage

Setting ImageView's size AND position as percentages programmatically in ConstraintLayout (Android)


As stated in the title i'm trying to set multiple ImageViews size and position as percentages in a ConstraintLayout programmatically.

I succeeded to do the individually, either via ConstraintSet or ConstraintLayout.LayoutParams, but when i try to do them both at the same time nothing seems to work.

I also tried to use Guidelines for the position and ConstraintSet for the size but still no result.

Here is the for loop (position working, no idea how to do size) in which i want to achieve this

ConstraintLayout layout = findViewById(R.id.mapView);
for(Point p : getCoords()){
            ImageView iv = new ImageView(this);
            iv.setId(View.generateViewId());

            iv.setLayoutParams(getFeatureLayout(p.x/100f, p.y/100f));

            iv.setImageDrawable(getResources().getDrawable(R.drawable.area));

            layout.addView(iv);
        }

The getFeatureLayout method is as follows

private ConstraintLayout.LayoutParams getFeatureLayout(float percentFromLeft, float percentFromTop){
        assert percentFromTop>=0 && percentFromTop<=1 : "Inputs must be 0<=x<=1";
        assert percentFromLeft>=0 && percentFromLeft<=1 : "Inputs must be 0<=x<=1";

        ConstraintLayout.LayoutParams params = new ConstraintLayout.LayoutParams(
                ConstraintProperties.WRAP_CONTENT,
                ConstraintProperties.WRAP_CONTENT
        );

        params.bottomToBottom= ConstraintProperties.PARENT_ID;
        params.topToTop= ConstraintProperties.PARENT_ID;
        params.startToStart= ConstraintProperties.PARENT_ID;
        params.endToEnd= ConstraintProperties.PARENT_ID;

        params.verticalBias=percentFromTop;
        params.horizontalBias=percentFromLeft;

        return params;
    }

Solution

  • Ok i finally got it to work, posting the solution if anyone needs it

    // Define a constraint set that will be used to modify the constraint layout parameters of the child.
    ConstraintSet set = new ConstraintSet();
    // Start with a copy the original constraints.
    set.clone(mapView);
    // The background of the ConstraintLayout (i need it for width-height ratio)
    Drawable map = getResources().getDrawable(R.drawable.pvp_map);
    float heightPercentSize = .1f; // The area size will be this much of the map's height
    // Defining the width-height ratio so that 
    // width*heightPercentSize*ratioAdjuster == height*heightPercentSize
    float ratioAdjuster = (float)map.getIntrinsicHeight()/map.getIntrinsicWidth();
            
    for(Point p : getPvpCoords()){
            ImageView iv = new ImageView(this);
            Guideline gStart = getNewGuideline(this, ConstraintLayout.LayoutParams.VERTICAL);
            Guideline gTop = getNewGuideline(this, ConstraintLayout.LayoutParams.HORIZONTAL);
    
            iv.setId(View.generateViewId());
    
            gStart.setGuidelinePercent(p.x/100f-heightPercentSize/2);
            gTop.setGuidelinePercent(p.y/100f-heightPercentSize/2);
            set.connect(iv.getId(), ConstraintSet.START, gStart.getId(), ConstraintSet.END);
            set.connect(iv.getId(), ConstraintSet.TOP, gTop.getId(), ConstraintSet.BOTTOM);
    
            set.constrainPercentWidth(iv.getId(), heightPercentSize*ratioAdjuster);
            set.constrainPercentHeight(iv.getId(), heightPercentSize);
    
            iv.setImageDrawable(getResources().getDrawable(R.drawable.area));
            mapView.addView(gTop);
            mapView.addView(gStart);
            mapView.addView(iv);
    }
    // Apply the constraints for the child view to the parent layout.
    set.applyTo(mapView);