Search code examples
androidandroid-viewbinding

Android ViewBinding with CustomView


I'd like to use try out the ViewBinding with custom view, for example:

MainActivity <=> layout_main.xml
MyCustomView <=> layout_my_custom_view.xml

layout_main.xml

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

        <com.example.myapplication.MyCustomView
            android:id="@+id/custom_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
</FrameLayout>

layout_my_custom_view.xml

<LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <TextView
            android:id="@+id/line1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Line1" />

        <View
            android:id="@+id/divider"
            android:layout_width="match_parent"
            android:layout_height="2dp"
            android:background="#2389bb" />

        <TextView
            android:id="@+id/line2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Line2" />
</LinearLayout>

MainActivity

class MainActivity : AppCompatActivity() {

    private lateinit var binding: LayoutMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = LayoutMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        binding.customView.line1.text = "Hello"
        binding.customView.line2.text = "World"
    }
}

In my MainActivity, I can use the binding to find MyCustomView but I can't further find @id/line1 and @id/line2 in MyCustomView. In this case, is it possible to use ViewBinding only or do I have to use findViewById or Kotlin synthetic ??

Thanks in advance.


Solution

  • ViewDataBinding.inflate doesn't generate of child view accessor inside custom view.

    thus, you can't touch line1(TextView) via only use ViewDataBinding.

    If you don't want using findViewById or kotlin synthetic, MyCustomView also needs to apply ViewDataBinding. try as below.

    CustomView

    class MyCustomView @JvmOverloads constructor(
        context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
    ) : LinearLayout(context, attrs, defStyleAttr) {
        private val binding =
            CustomLayoutBinding.inflate(LayoutInflater.from(context), this, true)
    
        val line1
            get() = binding.line1
    
        val line2
            get() = binding.line2
    }
    

    MainActivity

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    
        val binding = ActivityMainBinding.inflate(LayoutInflater.from(this))
        setContentView(binding.root)
    
        with(binding.customView) {
            line1.text = "Hello"
            line2.text = "World"
        }
    }