前言
開發 Android 的時候很常使用 Kotlin 方便的語法來取得 view 。 舉例來說我們常常會這樣寫
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val title = textView
title.text = "I'm a title"
}
}
最近(好像也不最近了) Google 推出了新的 View Binding 來取代舊有的 Kotlin synthetics 。
如果想要了解更多更詳細的 View Binding 請看這裡。
遇到的問題
有時候我們會組合 Android 提供的 View 製作成 Component 組合出一些實用的功能。 想了解更多 Custom View 請看這裡。
但因為我們使用了 View Binding 不能透過 Kotlin 直接的取得 Custom View 裡面的 View 。
解決方式
先來看看 Custom View Class 裡我們會怎麼做改寫 假設我們的 custom_view.xml 裡面就只有一個簡單的 titleTextView
class MyCustomView: ConstraintLayout {
constructor(context: Context) : super(context){ init(context, null) }
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) { init(context, attrs) }
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
context,
attrs,
defStyleAttr
){ init(context, attrs) }
private lateinit var binding: MyCustomViewBinding
val title get() = binding.titleTextView // 需要宣告變數,才能讓外部取得
private fun init(context: Context, attrs: AttributeSet?){
binding = MyCustomViewBinding.inflate(LayoutInflater.from(context), this)
}
}
接下來我們會在 activity_main 裡加入這個 custom view
// activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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:background="@color/white_five"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.example.ui.components.MyCustomView
android:id="@+id/customView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</androidx.constraintlayout.widget.ConstraintLayout>
比較舊方法跟新方式的差距
// 舊的方式
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val title = customView.titleTextView
title.text = "I'm a title"
}
}
// 新的方式
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
with(binding.customView){
title.text = "I'm a title"
// Custom View Class 需要宣告變數才能夠被存取
}
}
}
透過這樣的方式就可以取得 titleTextView 囉。