Question

I have an Android layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/dice_container"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:gravity="center"
    android:orientation="vertical" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:gravity="top" >

    <FrameLayout
        android:id="@+id/die_frame_1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal|top" >

        <ImageView
            android:id="@+id/die1"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:contentDescription="@string/dice"
            android:src="@drawable/d6" />

        <ImageView 
            android:id="@+id/die_overlay_1"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:alpha="0.4"
            android:visibility="invisible"
            android:src="@drawable/gray_shape" 
            android:contentDescription="@string/gray_overlay" />

    </FrameLayout>

    </LinearLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <FrameLayout
            android:id="@+id/die_frame_2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" >

            <ImageView
                android:id="@+id/die2"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:contentDescription="@string/dice"
                android:src="@drawable/d2" />

            <ImageView 
                android:id="@+id/die_overlay_2"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:alpha="0.4"
                android:visibility="invisible"
                android:src="@drawable/gray_shape" 
                android:contentDescription="@string/gray_overlay" />

        </FrameLayout>

        <FrameLayout
            android:id="@+id/die_frame_3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" >

            <ImageView
                android:id="@+id/die3"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:contentDescription="@string/dice"
                android:src="@drawable/d1" />

            <ImageView 
                android:id="@+id/die_overlay_3"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:alpha="0.4"
                android:visibility="invisible"
                android:src="@drawable/gray_shape"
                android:contentDescription="@string/gray_overlay" />

        </FrameLayout>

    </LinearLayout>

</LinearLayout>

And I am trying to programmatically take care of the positions of the images. The problem is that the result is not what I want it to be, which would be three images centered in the form of a pyramid. Die number 1 is the top, and 2 and 3 bottom left and right respectively.

FrameLayout[] frames = new FrameLayout[] {(FrameLayout) findViewById(R.id.die_frame_1),
            (FrameLayout) findViewById(R.id.die_frame_2),
            (FrameLayout) findViewById(R.id.die_frame_3)};
Point size = getSize();
int width = size.x;
int height = size.y;
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) frames[0].getLayoutParams();
// Width will be restricted either by height or width. Dice should take max 50% of screen
int frameWidth = (int) Math.min(width * 0.44, height * 0.5 * 0.44); // Each dice 40%
params.width = frameWidth;
params.height = frameWidth; // Square, so width equals height
// Ensure that the space between each dice is equal
int frameHeightMargin = (int) (height * 0.5 - frameWidth * 2) / 3; // Divide the remainder evenly
int frameWidthMarginOuter = (int) (width - 2 * frameWidth - frameHeightMargin) / 2; // Calculate outer
int frameWidthMarginCenter = (int) frameHeightMargin / 2; // Same spacing between dice
int frameWidthMarginUpper = (int) (width - frameWidth) / 2; // Upper only
for (int i = 0; i < frames.length; i++) {
    if (i == 0) {
        params.setMargins(frameWidthMarginUpper, frameHeightMargin, frameWidthMarginUpper, frameWidthMarginCenter); // Gravity is centered
    } else if (i == 1) { // Left dice
        params.setMargins(frameWidthMarginOuter, frameWidthMarginCenter, frameWidthMarginCenter, frameHeightMargin);
    } else if (i == 2) {// Right dice
        params.setMargins(frameWidthMarginCenter, frameWidthMarginCenter, frameWidthMarginOuter, frameHeightMargin);
    }
    frames[i].setLayoutParams(params);
}

Current result: Dice

The code is in the onCreate method by the way. I have both tried with and without requestLayout() for the FrameLayouts and the parents.

Was it helpful?

Solution

Unless you know exactly what you are doing do not use the same LayoutParams for more than one ViewGroup. The solution is very simple. Create a new LayoutParams for each die.

FrameLayout[] frames = new FrameLayout[] {(FrameLayout) findViewById(R.id.die_frame_1),
        (FrameLayout) findViewById(R.id.die_frame_2),
        (FrameLayout) findViewById(R.id.die_frame_3)};
Point size = getSize();
int width = size.x;
int height = size.y;
// Width will be restricted either by height or width. Dice should take max 50% of screen
int frameWidth = (int) Math.min(width * 0.44, height * 0.5 * 0.44); // Each dice 40%
// Ensure that the space between each dice is equal
int frameHeightMargin = (int) (height * 0.5 - frameWidth * 2) / 3; // Divide the remainder evenly
int frameWidthMarginOuter = (int) (width - 2 * frameWidth - frameHeightMargin) / 2; // Calculate outer
int frameWidthMarginCenter = (int) frameHeightMargin / 2; // Same spacing between dice
int frameWidthMarginUpper = (int) (width - frameWidth) / 2; // Upper only
for (int i = 0; i < frames.length; i++) {
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
    params.width = frameWidth;
    params.height = frameWidth; // Square, so width equals height
    if (i == 0) {
        params.setMargins(frameWidthMarginUpper, frameHeightMargin, frameWidthMarginUpper, frameWidthMarginCenter); // Gravity is centered
    } else if (i == 1) { // Left dice
        params.setMargins(frameWidthMarginOuter, frameWidthMarginCenter, frameWidthMarginCenter, frameHeightMargin);
    } else if (i == 2) {// Right dice
        params.setMargins(frameWidthMarginCenter, frameWidthMarginCenter, frameWidthMarginOuter, frameHeightMargin);
    }
    frames[i].setLayoutParams(params);
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top