【问题标题】:Android Compound View: cannot make child view match parentAndroid 复合视图:无法使子视图匹配父视图
【发布时间】:2015-10-30 05:35:12
【问题描述】:

我创建了一个继承自 FrameLayout 的自定义视图(复合视图),其中包含多个子视图:

MediaComponentView.java:

final public class MediaComponentView extends FrameLayout {
    private int ratio = 1;

    private ImageView imageView;
    private CircularProgressView progressView;
    private View downloadButton;
    private View cancelButton;
    private View playButton;

    public MediaComponentView(Context context) {
        super(context);
        initializeViews();
    }

    public MediaComponentView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initializeViews();
    }

    public MediaComponentView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initializeViews();
    }

    private void initializeViews() {
        inflate(getContext(), R.layout.view_media_component, this);
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();

        imageView = (ImageView) this.findViewById(R.id.image_view);
        progressView = (CircularProgressView) this.findViewById(R.id.progress_view);
        downloadButton = this.findViewById(R.id.download_button);
        cancelButton = this.findViewById(R.id.cancel_button);
        playButton = this.findViewById(R.id.play_button);
    }

    public void setRatio(int ratio) {
        this.ratio = ratio;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        setMeasuredDimension(getMeasuredWidth(), getMeasuredWidth() / ratio);
    }

}

view_media_component.xml:

<merge
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    >

    <com.makeramen.roundedimageview.RoundedImageView
        android:id="@+id/image_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="centerCrop"
        app:riv_border_color="#eee"
        app:riv_border_width="1px"
        app:riv_corner_radius="3dp"
        />

    <com.github.rahatarmanahmed.cpv.CircularProgressView
        android:id="@+id/progress_view"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:layout_gravity="center"
        android:visibility="gone"
        />

    <ImageView
        android:id="@+id/download_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:src="@drawable/icon_chat_media_download"
        android:visibility="gone"
        />

    <ImageView
        android:id="@+id/cancel_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:src="@android:drawable/ic_menu_close_clear_cancel"
        android:visibility="gone"
        />

    <ImageView
        android:id="@+id/play_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:src="@drawable/icon_chat_media_play"
        android:visibility="gone"
        />
</merge>

复合视图的用法:

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal"
    android:layout_marginTop="4dp"
    android:layout_marginLeft="2dp"
    android:layout_marginRight="2dp"
    >

    <some.hidden.package.MediaComponentView
        android:id="@+id/media_0"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:layout_marginLeft="2dp"
        android:layout_marginRight="2dp"
        android:background="#00ff00"
        />

    <some.hidden.package.MediaComponentView
        android:id="@+id/media_1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:layout_marginLeft="2dp"
        android:layout_marginRight="2dp"
        android:background="#ff0000"
        />
</LinearLayout>

问题是“image_view”的布局不正确。它与父级不匹配。

我通过设置背景来检查 MediaComponentView 本身的大小是否正确。它的大小正确。

但是子视图的大小不正确。我猜这是因为 MediaComponentView 中重写了 onMeasure() 方法。

任何帮助或解释将不胜感激。

【问题讨论】:

  • 尝试将android:layout_width="fill_parent" android:layout_height="fill_parent 添加到您的&lt;merge&gt; 标签中。
  • 同理。它没有帮助。

标签: android android-custom-view layout-inflater android-viewgroup


【解决方案1】:

您需要在 onMeasure() 覆盖结束时调用 measureChildren(int widthMeasureSpec, int heightMeasureSpec) 。子视图不知道您更改了高度。

【讨论】:

  • 不幸的是,这并不能解决问题。子视图已经改变了它们的放置方式,但它们的大小仍然不正确。
  • 它会工作的。你用什么高度测量规格?应该是 MeasureSpec.makeMeasureSpec(MeasureSpec.AT_MOST, getMeasuredWidth() / ratio)。
  • 以下代码解决了这个问题: measureChildren(MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(getMeasuredWidth() / ratio, MeasureSpec.EXACTLY));
  • 非常感谢!最后一个问题 - 上面代码的性能如何?它不会让布局图变慢吗?
  • 很高兴你最终到达了那里。两次测量所有子视图会对性能造成小幅影响。如果您想避免这种情况,那么不要第二次调用 measureChildren(),而只需修改您传递给 super.onMeasure() 的高度 measurespec,即使其完全成为宽度的比率测量规格。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-01-11
  • 1970-01-01
  • 2016-01-15
  • 1970-01-01
  • 2020-11-16
  • 1970-01-01
  • 2015-10-11
相关资源
最近更新 更多