Android

レイアウトxmlでカスタムビューに子ビューを入れる

要点

カスタムビューのaddViewをオーバーライドする

レイアウトxml

カスタムビューを使うほうのxml

カスタムビューWrapViewをこんな感じで使いたい。

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="nittyan.childview.MainActivity"
    >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        />

    <nittyan.childview.WrapView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        >
        <!-- カスタムビューに子ビュー入れる -->
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="aaa"
            />
    </nittyan.childview.WrapView>

</android.support.constraint.ConstraintLayout>

view_wrap.xml

色とかパディングの値は適当で特別意味はないです。
上記xmlのTextViewをrootの子要素として追加されるようにしたい。

<?xml version="1.0" encoding="utf-8"?>
<layout
    xmlns:android="http://schemas.android.com/apk/res/android"
    >

    <android.support.constraint.ConstraintLayout
        android:id="@+id/root"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:background="#00ff00"
        android:paddingTop="20dp"
        >

    </android.support.constraint.ConstraintLayout>

</layout>

WrapView.java

rootの子要素に追加されるようにするにはaddViewをオーバーライドしてbindingが初期化されてないときは親クラスのaddViewを使用して、bindingが初期化されていたらrootの子ビューとして追加するようにする。

package nittyan.childview;

import android.content.Context;
import android.databinding.DataBindingUtil;
import android.support.constraint.ConstraintLayout;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import nittyan.childview.databinding.ViewWrapBinding;


public class WrapView extends ConstraintLayout {

    private ViewWrapBinding binding;

    public WrapView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public WrapView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    private void init() {
        binding = DataBindingUtil.inflate(LayoutInflater.from(getContext()), R.layout.view_wrap, this, true);
    }

    @Override
    public void addView(View child, int index, ViewGroup.LayoutParams params) {
        if (binding == null) {
            super.addView(child, index, params);
        } else {
            binding.root.addView(child, index, params);
        }
    }

}