sazzy4o sazzy4o - 4 months ago 13
Android Question

How to fix layout_weight in Linear layout?

In my xml file I set each small circle (ImageView) to be the size of 25% of the screen with a Linear View and layout_weights.

Here is a screen shot from my phone(how it is supposed to look):

enter image description here

On my tablet it does not change the size to be 25% of the screen and this is how it looks:

enter image description here

My code consists of three LinearLayouts each containing ImageViews with weights of 0.25 out of 1.

Here is the code:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent"
xmlns:ads="http://schemas.android.com/apk/res-auto">
<ImageView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/imageView12"
android:src="@drawable/circle_big"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true" />

<LinearLayout
android:id="@+id/wrapper"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:weightSum="1.0"
android:layout_centerVertical="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
>

<FrameLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.03125">
</FrameLayout>
<ImageView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.25"
android:id="@+id/imageView12"
android:src="@drawable/circle_white"
android:onClick="changeToScreenSelectLayout"
android:scaleType="fitCenter"
android:adjustViewBounds="true"
/>
<FrameLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.09375">
</FrameLayout>
<ImageView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.25"
android:id="@+id/imageView12"
android:src="@drawable/circle_white"
android:onClick="changeToScreenSelectLayout"
android:scaleType="fitCenter"
android:adjustViewBounds="true"
/>
<FrameLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.09375">
</FrameLayout>
<ImageView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.25"
android:id="@+id/imageView12"
android:src="@drawable/circle_white"
android:onClick="changeToScreenSelectLayout"
android:scaleType="fitCenter"
android:adjustViewBounds="true"
/>

<FrameLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.03125">

</FrameLayout>


</LinearLayout>
<LinearLayout
android:id="@+id/wrapper"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:weightSum="1.0"
android:layout_centerVertical="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:rotation = "120"
>

<FrameLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.03125">
</FrameLayout>
<ImageView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.25"
android:id="@+id/imageView12"
android:src="@drawable/circle_white"
android:onClick="changeToScreenSelectLayout"
android:scaleType="fitCenter"
android:adjustViewBounds="true"
/>
<FrameLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.4375">
</FrameLayout>
<ImageView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.25"
android:id="@+id/imageView12"
android:src="@drawable/circle_white"
android:onClick="changeToScreenSelectLayout"
android:scaleType="fitCenter"
android:adjustViewBounds="true"
/>

<FrameLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.03125">

</FrameLayout>


</LinearLayout>
<LinearLayout
android:id="@+id/wrapper"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:weightSum="1.0"
android:layout_centerVertical="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:rotation = "60"
>

<FrameLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.03125">
</FrameLayout>
<ImageView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.25"
android:id="@+id/imageView12"
android:src="@drawable/circle_white"
android:onClick="changeToScreenSelectLayout"
android:scaleType="fitCenter"
android:adjustViewBounds="true"
/>
<FrameLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.4375">
</FrameLayout>
<ImageView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.25"
android:id="@+id/imageView12"
android:src="@drawable/circle_white"
android:onClick="changeToScreenSelectLayout"
android:scaleType="fitCenter"
android:adjustViewBounds="true"
/>

<FrameLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.03125">

</FrameLayout>


</LinearLayout>

</RelativeLayout>

Answer

You cannot use a png file as your circle_white. You could technically make this work if you choose the correct android:scaleType, but it would result in horribly aliased renderings.

I would first delete your existing pngs (From each resource bucket) since they cannot be used for this. Then make a new file in drawable named "circle_white.xml". Put this in it, this will draw a circle with no intrinsic size. I.E. it will just fill whatever you render it with.

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">
    <solid
        android:color="#fff"/>
</shape>

And then change from using ImageView's with a src of circle_white to a HeightMatchesWidthView with the background set to this new @drawable/circle_white. You would need to ensure the Views height matches the width which I did in a view extension below. To use this just make a new class somewhere and paste this in. In xml reference it by instead of having ImageView do com.whatever.HeightMatchesWidthView where the com.whatever is whatever package you put this in.

public class HeightMatchesWidthView extends View {
    public HeightMatchesWidthView(final Context context) {
        super(context);
    }

    public HeightMatchesWidthView(final Context context, final AttributeSet attrs) {
        super(context, attrs);
    }

    public HeightMatchesWidthView(final Context context, final AttributeSet attrs, final int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
        int width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
        setMeasuredDimension(width, width);
    }

    @Override
    protected void onSizeChanged(final int w, final int h, final int oldw, final int oldh) {
        super.onSizeChanged(w, w, oldw, oldh);
    }
}

Instead of the HeightMatchesWidthView you could also use a PercentRelativeLayout instead and use that to force them to be square, and the correct size without having to extend View to add support for forcing square.