Custom view hierarchy child not added

北慕城南 提交于 2019-12-12 02:52:32

问题


I have a hierarchy of custom views that looks like this:

Activity(RelativeLayout) -> ParentLayout(FrameLayout) -> ChildLayout(LinearLayout)

The activity and parent layout are added and displayed just fine, but the child is not. I have looked at the hierarchy viewer in the device monitor to confirm it is not being added to the view hierarchy.

Really all I'm trying to do here is create a view hierarchy so I can play around with handling touch events at various places in the view.

Here is everything:

main_activity.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity">

    <net.openeye.touchevents.ParentLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#558833" />

</RelativeLayout>

parent_layout.xml:

<?xml version="1.0" encoding="utf-8"?>
<net.openeye.touchevents.ParentLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <net.openeye.touchevents.ChildLayout
        android:id="@+id/child_view"
        android:layout_width="300dp"
        android:layout_height="300dp" />

</net.openeye.touchevents.ParentLayout>

ParentLayout.java:

public class ParentLayout extends FrameLayout implements View.OnTouchListener {
    public ParentLayout(Context context) {
        super(context);
    }

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

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

child_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<net.openeye.touchevents.ChildLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="300dp"
    android:layout_height="300dp"
    android:background="#0066dd"
    android:orientation="vertical">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="Hi"/>

</net.openeye.touchevents.ChildLayout>

ChildLayout.java:

public class ChildLayout extends LinearLayout {
    public ChildLayout(Context context) {
        super(context);
    }

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

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

What am I missing? I have another project that is basically set up the same way, except the child views are dynamically inflated and added, instead of being directly added in the xml layout files. This seems like it should work and I don't understand why it doesn't.


回答1:


So it looks like when you have a custom view class, you don't want to have the view of the layout file be the same type as the custom class. i.e., if I have ParentLayout.java, I don't want parent_layout.xml's root to be <net.openeye.TouchEvents.ParentLayout>. It seems that when you want both a custom layout file and custom view class, you need to have the view class inflate the layout. If the layout has an element (the root, on this case) that is the same as the class, it will cause infinite recursion as the view inflates the layout, which instantiates the class, which inflates the layout... and so on.

I got this to work finally by making the following changes:

parent_layout.xml:
Change the root element from net.openeye.TouchEvents.ParentLayout to the class it extends, FrameLayout. It now looks like this:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <!-- ... -->
</FrameLayout>

child_layout.xml:
Change the root element from net.openeye.TouchEvents.ChildLayout to the class it extends, LinearLayout. It now looks like this:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="300dp"
    android:layout_height="300dp"
    android:orientation="vertical">
    <!-- ... -->
</LinearLayout>

ParentLayout.java: Inflate it's layout during instantiation. It now looks like this:

public ParentLayout(Context context) {
    super(context);
    init(context);
}

public ParentLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
    init(context);
}

public ParentLayout(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    init(context);
}

private void init(Context context) {
    inflate(context, R.layout.parent_layout, this);
}

ChildLayout.java: Same thing as ParentLayout.java, but inflate child_layout.

After getting this working and thinking about why this is happening, it makes sense that this is how it works.



来源:https://stackoverflow.com/questions/31997792/custom-view-hierarchy-child-not-added

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!