Data binding ライブラリ サンプル
作ったサンプル
画面
Set up
Gradle
アプリ側のbuild.gradle
に以下を記述
android { buildFeatures { dataBinding true } }
Layoutファイル
layout
タグをルートに変更する
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <data> <variable name="resultHandler" type="io.github.yossan.databindingsample.MainActivity.ResultListener" /> </data> <androidx.constraintlayout.widget.ConstraintLayout ....
ソースファイル側
layoutファイルに、Data bindingする必要がある。
MainActivity.kt
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // activity_main.xmlレイアウトファイルの場合 DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main) }
- 生成されるDataBindingクラスは、レイアウトファイル名に基づく
サンプル
View Reference
viewのidを通して直接アクセスすることができる
activity_main.xml
<!-- 参照元 --> <EditText android:id="@+id/nameEditText" <!-- 参照 --> <TextView android:text="@{nameEditText.text}"
_
はCamel Caseに変換されるname_edit_text
→nameEditText
Event Handling
activity_main.xml
<data> <variable name="resultHandler" type="io.github.yossan.databindingsample.MainActivity.ResultListener" /> </data>
- resultHandler: 生成されるDataBindingクラスの属性となる
2つの方式でかける
- Method Reference
- Listener bindings
Method Reference
<Button android:onClick="@{resultHandler::onClick}"/>
Listener bindings
ラムダ式が使える
<Button android:onClick="@{(view) -> resultHandler.onClick(view)}"/>
MainActivity.kt
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val binding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main) // resultHandlerにリスナーをつなげる binding.resultHandler = ResultListener(binding) } class ResultListener(val binding: ActivityMainBinding) : View.OnClickListener { override fun onClick(v: View) { binding.resultTextView.text = when(binding.ageEditText.text.toString().toInt()) { in 0..20 -> "NG" in 21..130 ->"OK" else -> "It's not human." } } } }
プログラム側からViewに反映させる
lifecycleOwner
を設定する必要がある。
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) viewModel = ViewModelProvider(this, object : ViewModelProvider.NewInstanceFactory() { override fun <T : ViewModel?> create(modelClass: Class<T>): T { return MainViewModel() as T } }).get(MainViewModel::class.java) val binding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main) // これがないとプログラミング側での変更がlayoutに反映されない binding.lifecycleOwner = this binding.viewModel = viewModel }
layout file
<?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" > <data> <import type="androidx.lifecycle.MutableLiveData" /> <import type="io.github.yossan.drawsample.MainViewModel" /> <import type="io.github.yossan.drawsample.DrawView" /> <variable name="viewModel" type="MainViewModel" /> </data> <androidx.constraintlayout.widget.ConstraintLayout xmlns:tools="http://schemas.android.com/tools" xmlns:custom="http://schemas.android.com/apk/res/io.github.yossan.drawsample" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <io.github.yossan.drawsample.DrawView android:id="@+id/draw_view" android:layout_width="0dp" android:layout_height="0dp" custom:mode="@{viewModel.mode}" app:layout_constraintBottom_toTopOf="@+id/toolbar" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.0" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="1.0" /> <androidx.appcompat.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="?attr/colorPrimary" android:minHeight="?attr/actionBarSize" android:theme="?attr/actionBarTheme" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent"> <Button android:id="@+id/pen" android:layout_width="wrap_content" android:layout_height="wrap_content" android:enabled="@{viewModel.mode == DrawView.Mode.pen ? false : true}" android:onClick="@{_ -> viewModel.toggleMode()}" android:text="@string/pen" /> <Button android:id="@+id/eraser" android:layout_width="wrap_content" android:layout_height="wrap_content" android:enabled="@{viewModel.mode == DrawView.Mode.eraser ? false : true}" android:onClick="@{_ -> viewModel.toggleMode()}" android:text="@string/eraser" /> </androidx.appcompat.widget.Toolbar> </androidx.constraintlayout.widget.ConstraintLayout> </layout>