カスタムビュー(custom view)の実装

#カスタムビュー
子Viewを複数箇所で使用する場合や、
処理を独立させたい場合にカスタムビューを使用する。

更に子Viewを表示している間は後ろのViewにタッチを伝搬させないようにする。

#実装
ActivityにaddViewする先の親ViewであるFrameLayoutを保持する

## Activity
```activity_main.xml
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- 子Viewが表示中、このScrollViewがスクロールされなければOK -->
    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/gradation">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="1000dp"
            android:orientation="vertical">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="500dp"
                android:text="activity_main top"
                android:textSize="30sp" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="activity_main bottom"
                android:textSize="30sp" />
        </LinearLayout>

    </ScrollView>

    <!-- 親View -->
    <FrameLayout
        android:id="@+id/customViewContainer"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</FrameLayout>
```

```MainActivity.kt
class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // 親View
        val container = findViewById<FrameLayout>(R.id.customViewContainer)

        // 子View
        val firstCustomView = FirstCustomView(this, {
            container.removeAllViews()    // 親Viewに設定した子Viewを削除
        })

        // 親Viewに子viewを設定
        container.addView(firstCustomView)
    }
}
```

##カスタムビュー(子View)
```widget_custom_view.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#66000000">

    <FrameLayout
        android:layout_gravity="center"
        android:layout_width="300dp"
        android:layout_height="300dp"
        android:background="@android:color/black">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:text="custom view first"
            android:textColor="@android:color/white"
            android:textSize="30sp" />

        <Button
            android:id="@+id/customFirstButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|center"
            android:layout_marginBottom="30dp"
            android:text="close"
            android:textColor="@android:color/black" />
    </FrameLayout>

</FrameLayout>
```

```FirstCustomView.kt
class FirstCustomView(context: Context): FrameLayout(context) {

    var onClick: (()->Unit)? = null

    constructor(context: Context, onClick: ()->Unit): this(context){
        this.onClick = onClick
    }

    init{
        // Viewを設定
        inflate(context, R.layout.widget_custom_first, this)

        findViewById<Button>(R.id.customFirstButton)?.setOnClickListener {
            onClick?.invoke()
        }

        // 背後のViewへタッチを伝搬させない
        // これがないと後ろのスクロールViewがスクロールできてしまう
        setOnTouchListener { _, _ -> true }
    }
}
```

#結果
スクリーンショット

## 子view表示時 - スクロール不可
![screen.png](https://qiita-image-store.s3.amazonaws.com/0/199764/b313009e-b999-e512-4b1b-1e951dec3ad5.png)

## CLOSEタップして子View削除後
![screen.png](https://qiita-image-store.s3.amazonaws.com/0/199764/a1001c60-8859-b857-b204-3540c09d77da.png)

## スクロール可能に
![screen.png](https://qiita-image-store.s3.amazonaws.com/0/199764/c35a36a6-d5bd-9a41-e276-bf3d3bbbc947.png)

## 説明
親ViewのContainerにFrameLayoutを継承した子ViewのFirstCustomViewを
addView()にて設定

```
        // 親Viewに子viewを設定
        container.addView(firstCustomView)
```

子Viewの"CLOSE"Buttonをタップした際にActivityへタップされたことを通知
親ViewにてremoveAllView()にて子Viewを削除。

```
        // 子View
        val firstCustomView = FirstCustomView(this, {
            container.removeAllViews()    // 親Viewに設定した子Viewを削除
        })
```

使い勝手が非常に良いので、中規模以上のアプリでは使用すると良い感じです。