Freewind
Freewind

Reputation: 198238

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

Upvotes: 9

Views: 8792

Answers (3)

user
user

Reputation: 87064

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.

Upvotes: 10

Jens Zalzala
Jens Zalzala

Reputation: 2576

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.

Upvotes: 20

Dmitriy Tarasov
Dmitriy Tarasov

Reputation: 1969

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(....);
    }

Upvotes: 2

Related Questions