I want to make a layout similar to this one:
www.ImageBanana.net - layout.png http://www.imagebanana.com/img/9kmlhy66/thumb/layout.png
Four square buttons on
import android.content.Context;
import android.util.AttributeSet;
import android.widget.LinearLayout;
public class SquareLayout extends LinearLayout {
// Desired width-to-height ratio - 1.0 for square
private final double mScale = 1.0;
public SquareLayout(Context context) {
super(context);
}
public SquareLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
if (width > (int)((mScale * height) + 0.5)) {
width = (int)((mScale * height) + 0.5);
} else {
height = (int)((width / mScale) + 0.5);
}
super.onMeasure(
MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)
);
}
}
I'm usually doing things like that:
View v; // the view i want to layout squared
v.measure(1,1);
int size = v.getMeasuredHeight(); // or v.getMeasuredWidth()...
LayoutParams params = ... // either your own, or returned from View
params.width = size;
params.height = size;
v.setLayoutParams(params);
This is certainly not the most sophisticated code, as it leaves most capabilities that can be exploited in MeasureSpec, but it gets the job done, as 'v.measure(1,1)' just says "Measure my view as it is!".
The absolute plus in my approach is that you don't have to subclass anything and you don't have to add some OnGlobalLayoutListener
to your ViewTreeObserver
. This works all at the spot where you build or inflate your layout in code.
My solution is similar to the first one, however, I do the resizing in the onLayout method. Don't know which one is better.
For convenience I've wrapped my solution in a nice Android Library, see https://github.com/ronaldsteen/Android-SquareLayout-Library
You can achieve this using ConstraintLayout. You should just add vertical guideline with the position of 50% screen width, align your buttons to the left and right side of the guideline and size them in 1:1 aspect ratio. Everything can be done in layout XML file, no additional source code required.
Once you’ve completed all of these steps, you’ll end up with something like this:
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/button1"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="@android:color/holo_orange_light"
android:text="1"
app:layout_constraintDimensionRatio="H,1:1"
app:layout_constraintEnd_toStartOf="@+id/guideline"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button2"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="@android:color/holo_blue_light"
android:text="2"
app:layout_constraintDimensionRatio="W,1:1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/guideline"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button3"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="@android:color/holo_green_dark"
android:text="3"
app:layout_constraintDimensionRatio="W,1:1"
app:layout_constraintEnd_toStartOf="@+id/guideline"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button1" />
<Button
android:id="@+id/button4"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="@android:color/holo_purple"
android:text="4"
app:layout_constraintDimensionRatio="W,1:1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/guideline"
app:layout_constraintTop_toBottomOf="@+id/button2" />
<android.support.constraint.Guideline
android:id="@+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.5" />
</android.support.constraint.ConstraintLayout>
Here's how this layout looks on smallest vs largest screens:
ok, here's a revised example:
<?xml version="1.0" encoding="utf-8"?>
<ViewFlipper xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="fill_parent" android:layout_width="fill_parent">
<RelativeLayout android:id="@+id/magaLoginLayout"
android:layout_height="fill_parent" android:layout_width="fill_parent">
<Button android:text="@+id/Button01" android:id="@+id/Button01"
android:layout_width="160dip" android:layout_height="160dip" android:layout_marginTop="20dip"></Button>
<Button android:text="@+id/Button03" android:layout_below="@+id/Button01" android:id="@+id/Button03"
android:layout_alignLeft="@+id/Button01" android:layout_height="160dip" android:layout_width="160dip"></Button>
<Button android:text="@+id/Button04" android:layout_below="@+id/Button01" android:id="@+id/Button04"
android:layout_toRightOf="@+id/Button03" android:layout_height="160dip" android:layout_width="160dip"></Button>
<Button android:text="@+id/Button02" android:id="@+id/Button02" android:layout_width="wrap_content"
android:layout_toRightOf="@+id/Button01" android:layout_alignTop="@+id/Button01" android:layout_alignParentRight="true" android:layout_height="160dip"></Button>
</RelativeLayout>
</ViewFlipper>
I recommend the following way, it's straightforward and works
public class SquareLayout extends RelativeLayout {
public SquareLayout(Context context) {
super(context);
}
public SquareLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
}
}