Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extending FrameLayout, child views won't show anymore

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

like image 573
Freewind Avatar asked Sep 11 '12 08:09

Freewind


2 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.

like image 77
Jens Zalzala Avatar answered Sep 19 '22 17:09

Jens Zalzala


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.

like image 23
user Avatar answered Sep 22 '22 17:09

user