LoginSignup
4
6

More than 5 years have passed since last update.

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

Posted at

カスタムビュー

子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

CLOSEタップして子View削除後

screen.png

スクロール可能に

screen.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を削除
        })

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

4
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
6