Simple way to do dynamic but square layout
I'm using a GridView
to display a bunch of views which are essentially LinearLayouts
. I want the LinearLayouts
to all be square, but I also want them to be dynamically sized--that is, there are two columns and I want the LinearLayouts
to stretch depending on the size of the screen but remain square. Is there a way to do this through the xml
layout or do I have to set the heights and widths programmatically?
A neat solution for square GridView
items is to extend RelativeLayout
or LinearLayout
and override onMeasure
like so:
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
}
With the new ConstraintLayout introduced in Android Studio 2.3, it is now quite easy to build responsive layouts.
In a parent ConstraintLayout, to make any of its children view/layout dynamically square, add this attribute
app:layout_constraintDimensionRatio="w,1:1"
w is to specify width-wise constraints and 1:1 ratio ensures square layout.
I've done this way:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int size;
if(widthMode == MeasureSpec.EXACTLY && widthSize > 0){
size = widthSize;
}
else if(heightMode == MeasureSpec.EXACTLY && heightSize > 0){
size = heightSize;
}
else{
size = widthSize < heightSize ? widthSize : heightSize;
}
int finalMeasureSpec = MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY);
super.onMeasure(finalMeasureSpec, finalMeasureSpec);
}
With this implementation, your layout will be square, assuming the lower size between width and height. And it can even be set with dynamic values, like using weight inside a LinearLayout.