【问题标题】:Android custom view group delegate addViewAndroid 自定义视图组委托 addView
【发布时间】:2016-08-25 01:51:30
【问题描述】:

在我的情况下,我想实现自定义ViewGroup,从FrameLayout 派生,但我希望所有从xml 添加的子视图不直接添加到此视图中,而是添加到此自定义ViewGroup 中包含的FrameLayout 中。 让我举例说明一下。

<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:orientation="vertical">
    <FrameLayout
        android:id="@+id/frame_layout_child_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
    <FrameLayout
        android:id="@+id/frame_layout_top"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</merge>

我想将所有子视图重定向到FrameLayout,ID 为frame_layout_child_container

所以我当然会像这样覆盖addView() 方法

  @Override
    public void addView(View child) {
        this.mFrameLayoutChildViewsContainer.addView(child);
    }

但这肯定不行,因为这次mFrameLayoutChildViewsContainer 没有添加到根自定义视图中。

我的想法是始终在此容器的顶部保留一些视图 frame_layout_top 并且添加到自定义组件中的所有子视图都应该转到 frame_layout_child_container

使用自定义视图的示例

   <CustomFrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello World!"/>
    </CustomFrameLayout>

所以在这种情况下TextView 应该添加到frame_layout_child_container

是否可以像我描述的那样将所有视图委托给子 ViewGroup

我还有其他想法,例如每次添加视图时使用 bringToFront() 方法以使它们保持正确的 z 轴顺序,或者例如在添加视图时,将其保存到数组中,然后在扩展自定义视图后将所有视图添加到此孩子FrameLayout

建议在这种情况下该怎么做,以免在每次添加新视图时重新膨胀所有布局而影响性能,如果可以以其他方式实现的话。

【问题讨论】:

  • 您确定要扩展FrameLayout吗? orientation 属性仅适用于 LinearLayout
  • 我根本不需要方向属性 :) 所以我的答案是肯定的

标签: android performance android-layout android-view android-custom-view


【解决方案1】:

Views 从布局膨胀 - 就像您的示例 TextView - 不会使用 addView(View child) 添加到它们的父级 ViewGroup,这就是为什么仅覆盖该方法对您不起作用的原因。您想要覆盖 addView(View child, int index, ViewGroup.LayoutParams params),而所有其他 addView() 重载最终都会调用它。

在该方法中,检查要添加的孩子是否是您的两个特殊FrameLayouts 之一。如果是,让super 类处理添加。否则,将孩子添加到您的容器 FrameLayout

public class CustomFrameLayout extends FrameLayout {

    private final FrameLayout topLayout;
    private final FrameLayout containerLayout;

    ...

    public CustomFrameLayout(Context context, AttributeSet attrs) {
        super(context, attrs);

        LayoutInflater.from(context).inflate(R.layout.custom, this, true);
        topLayout = (FrameLayout) findViewById(R.id.frame_layout_top);
        containerLayout = (FrameLayout) findViewById(R.id.frame_layout_child_container);
    }

    @Override
    public void addView(View child, int index, ViewGroup.LayoutParams params) {
        final int id = child.getId();
        if (id == R.id.frame_layout_top || id == R.id.frame_layout_child_container) {
            super.addView(child, index, params);
        }
        else {
            containerLayout.addView(child, index, params);
        }
    }
}

【讨论】:

  • 这对我很有用。不过,我想添加一件事,最初添加到我的子 LinearLayout 容器的视图是不可见的。当我在 Android 设备监视器中使用层次结构检查器时,我注意到容器 LinearLayout 本身不在视图 DOM 中。长话短说,这是因为和 op 一样,我使用了合并标签而不是额外的 LinearLayout。当你这样做时,你的 android:orientation 属性需要被添加到它被合并到的 ViewGroup 中,而不是合并标签本身。一旦我将它添加到我的另一个父视图的布局文件中,我的视图就会出现。
  • 也可以通过检查getChildCount() == 0来实现。
猜你喜欢
  • 2023-03-11
  • 2012-06-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-15
  • 2012-06-22
相关资源
最近更新 更多