【问题标题】:Extending FrameLayout, child views won't show anymore扩展 FrameLayout,子视图不再显示
【发布时间】:2012-09-11 08:06:16
【问题描述】:

这是我的代码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>

ImageView 显示良好。

现在我有一个从 FrameLayout 扩展的自定义布局,例如我的框架布局。

在MyFrameLayout中,我希望布局的高度总是宽度的一半,所以我的代码是:

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

然后在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>

但是现在内部的 ImageView 消失了。

我认为我没有正确实现onMeasureonLayout。我想我也需要调整子视图的大小。但我现在不知道该怎么办。


更新

根据 TheDimasig 的评论,我刚刚检查了我的代码并更新了我的问题。谢谢

【问题讨论】:

  • 两个建议:1. 检查MyFrameLayout 类中的onMeasureonLayout 方法。 2.尝试使用hierarhyviewer工具进行调试。另外,是否可以显示自定义布局的所有代码
  • @TheDimasig,我刚刚更新了我的问题,请查看:)

标签: android android-layout


【解决方案1】:

您看不到任何子视图,因为您没有正确覆盖方法onMeasure。您可以让超类实现逻辑(因此将显示子视图),然后重置 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));
    }
}

如果您发布的布局不是您的完整布局,那么我的代码可能无法正常工作。

【讨论】:

    【解决方案2】:

    最简单的方法是在onMeasure中改变measurespec,但还是调用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);
    }
    

    这样您可以获得所需的尺寸,但不必手动测量子级。

    【讨论】:

    • 我可以确认它有效。如果不调用 super.onMeasure(),子视图是不可见的!
    • 非常感谢,我已经阅读了很多讨论,这是使孩子使用父布局调整大小的唯一有效答案!
    【解决方案3】:

    我想在您的 onMeasure 方法中,您忘记对所有子视图调用 onMeasure,包括您的 ImageView。您必须遍历所有子视图并对其调用 onMeasure,如下所示:

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

    【讨论】:

    • 我刚看了FrameLayout的源码,onMeasureonLayout看起来挺复杂的,有没有简单的方法呢?
    • 而不是覆盖所有方法主体和 setDimension() 尝试使用您的参数调用 super.onMeasure(widthMeasureSpec * 0.5, heightMeasureSpec)。此解决方案可能也需要以这种方式覆盖 onLayout
    • 我试过widthMeasureSpec*0.5,但最终大小看起来不像预期的那样。没看懂,有时间可以给我举个例子吗?
    • 很遗憾没有。如果 super.onMeasure 调用的技巧不起作用,我担心你需要实现自己的 onMeasure 和 onLayout 并且不要忘记孩子,祝你好运 =)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-08-26
    • 2016-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-03
    相关资源
    最近更新 更多