Home » Android » android – Extending FrameLayout, child views won't show anymore

android – Extending FrameLayout, child views won't show anymore

Posted by: admin June 15, 2020 Leave a comment

Questions:

This is my code with FrameLayout:

<FrameLayout
        android:layout_width="fill_parent" android:layout_height="wrap_content">
    <ImageView
            android:id="@+id/frameView"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:src="@drawable/image1"
            />
</FrameLayout>

The ImageView show well.

Now I have a custom layout extends from FrameLayout, e.g. MyFrameLayout.

In MyFrameLayout, I want the height of the layout is always half of the width, so my code is:

public class MyFrameLayout extends FrameLayout {

     // 3 constructors just call super

     @Override
     protected void onMeasure(int widthMeasureSpec,
                         int heightMeasureSpec) {
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = (int) (width * 0.5);
        setMeasuredDimension(width, height);
    }
}

Then use it in xml:

<com.test.MyFrameLayout
        android:layout_width="fill_parent" android:layout_height="wrap_content">
    <ImageView
            android:id="@+id/frameView"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:src="@drawable/image1"
            />
</com.test.MyFrameLayout>

But now the inner ImageView disappeared.

I think I don’t implement onMeasure or onLayout correctly. I guess I need to resize the children views as well. But I don’t know what to do now.


UPDATE

Per TheDimasig‘s comment, I just checked my code and update my question. Thanks

How to&Answers:

The simplest way is to change the measurespec in onMeasure, but still call super:

 @Override
 protected void onMeasure(int widthMeasureSpec,
                     int heightMeasureSpec) {
    int width = MeasureSpec.getSize(widthMeasureSpec);
    int height = (int) (width * 0.5);
    heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

This way you get the dimensions you want but don’t have to manually measure the children.

Answer:

You don’t see any child views because you don’t override the method onMeasure correctly. You could let the super class implement the logic(so the child views will be shown) and then reset the calculated width and height for MyFrameLayout:

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    // let the super class handle calculations
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    // set again the dimensions, this time calculated as we want
    setMeasuredDimension(getMeasuredWidth(), getMeasuredHeight() / 2);
    // this is required because the children keep the super class calculated dimensions (which will not work with the new MyFrameLayout sizes) 
    final int count = getChildCount();
    for (int i = 0; i < count; i++) {
        final View v = getChildAt(i);
        // this works because you set the dimensions of the ImageView to FILL_PARENT          
        v.measure(MeasureSpec.makeMeasureSpec(getMeasuredWidth(),
                MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(
                getMeasuredHeight(), MeasureSpec.EXACTLY));
    }
}

If that layout you posted isn’t your full layout then my code might not work.

Answer:

I suppose in your onMeasure method you forget to call onMeasure on all child views, including your ImageView. You must go thru all your child views and call onMeasure on them something like this:

    for (int i = 0; i < getChildCount(); i++) {
        getChildAt(i).measure(....);
    }