Android 自定义视图组委托addView

Android custom view group delegate addView

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

<?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>

我想将所有 child 视图重定向到 ID frame_layout_child_containerFrameLayout

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

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

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

我的想法是始终在此容器的顶部保留一些视图 frame_layout_top 并且添加到自定义组件中的所有 child 视图都应该转到 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

是否可以像我描述的那样委托将所有视图添加到 child ViewGroup 中。

我还有其他想法,比如每次添加视图时都使用 bringToFront() 方法以保持它们的正确 z-axis 顺序,或者例如添加视图时,将其保存到数组中,然后在膨胀自定义后查看向此添加所有视图 child FrameLayout

建议在这种情况下该怎么做,以便在每次添加新视图时都重新展开所有布局,如果可以通过其他方式实现,则不会影响性能。

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

在该方法中,检查添加的 child 是否是您的两个特殊 FrameLayout 之一。如果是,让 super class 处理添加。否则,将 child 添加到您的容器 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);
        }
    }
}