Edited at

Kotlin × Data BindingでonItemClickListener付きListViewアプリを作る

More than 1 year has passed since last update.

KotlinとData Bindingを使ってListViewのアプリを作ります。

サンプルプロジェクトは、以下repositoryに格納しています。

https://github.com/shanonim/Kotlin-DataBinding-ListView


KotlinでData Bindingを使うための設定

build.gradleに以下を追記します。


build.gradle

apply plugin: 'kotlin-kapt'

android {
dataBinding {
enabled = true
}
}

dependencies {
kapt 'com.android.databinding:compiler:2.2.3'
}


kapt 'com.android.databinding:compiler:のversionは以下サイトを参考にしました。

https://bintray.com/android/android-tools/com.android.databinding.compiler

2017.02.11現在、stableの最新は2.2.3だったので、そちらを採用しています。

スクリーンショット 2017-02-11 14.21.41.png


表示するデータ

APIから取得するデータではなく、enumで定義したサンプルデータを表示します。


KemonoData.kt

enum class KemonoData(val kemonoName: String, val kemonoWords: String) {

SERVAL("サーバル", "サーバルキャットのサーバルだよ!"),
FENNEC("フェネック", "君、やっぱイケてるねー"),
COMMON_RACCOON("アライグマ", "アライさんにお任せなのだー!"),
KABAN("かばん", "(・8・)")
}


KemonoModel.kt

data class KemonoModel(val kemonoName: String, val kemonoWords: String)



ソースコード


Activity


MainActivity.kt

class MainActivity : AppCompatActivity() {

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

val binding : ActivityMainBinding
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)

val listAdapter = KemonoAdapter(applicationContext)
val list = mutableListOf<KemonoModel>()
for (value in KemonoData.values()) {
list.add(KemonoModel(value.kemonoName, value.kemonoWords))
}
listAdapter.kemonoFriends = list
binding.listview.adapter = listAdapter

binding.setOnItemClick { adapterView, view, position, l ->
Toast.makeText(this, listAdapter.kemonoFriends[position].kemonoName, Toast.LENGTH_SHORT).show()
}
}
}


対応するxmlファイルはactivity_main.xmlです。

<variable>タグ内のtypeAdapterView.OnItemClickListenerをセットし、ListViewの子要素に対するonItemClickを設定しています。


activity_main.xml

<?xml version="1.0" encoding="utf-8"?>

<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:bind="http://schemas.android.com/apk/res-auto">

<data>

<variable
name="onItemClick"
type="android.widget.AdapterView.OnItemClickListener" />
</data>

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

<ListView
android:id="@+id/listview"
android:layout_width="match_parent"
android:layout_height="match_parent"
bind:onItemClickListener="@{onItemClick}" />

</LinearLayout>
</layout>



item_list_view

ListViewの子要素のxmlファイルです。


item_list_view.xml

<?xml version="1.0" encoding="utf-8"?>

<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<data>

<variable
name="kemonoFriends"
type="com.example.shanonim.kotlin_databinding_listview.model.KemonoModel" />
</data>

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingBottom="10dp"
android:paddingLeft="20dp"
android:paddingTop="10dp">

<TextView
android:id="@+id/text_view_kemono_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:width="500dp"
android:height="30dp"
android:gravity="center_vertical"
android:text="@{kemonoFriends.kemonoName}"
android:textColor="@android:color/black"
android:textSize="20dp"
tools:text="サーバル" />

<TextView
android:id="@+id/text_view_kemono_words"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/text_view_kemono_name"
android:width="500dp"
android:height="30dp"
android:gravity="center_vertical"
android:text="@{kemonoFriends.kemonoWords}"
android:textColor="@android:color/black"
tools:text="サーバルキャットのサーバルだよ!" />
</RelativeLayout>
</layout>



Adapter


KemonoAdapter.kt

class KemonoAdapter(private val context: Context) : BaseAdapter() {

var kemonoFriends: List<KemonoModel> = emptyList()

override fun getCount(): Int = kemonoFriends.size

override fun getItem(position: Int): Any? = kemonoFriends[position]

override fun getItemId(position: Int): Long = 0

override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
val binding: ItemListViewBinding
if (convertView == null) {
binding = ItemListViewBinding.inflate(LayoutInflater.from(context), parent, false)
binding.root.tag = binding
} else {
binding = convertView.tag as ItemListViewBinding
}
binding?.kemonoFriends = getItem(position) as KemonoModel

return binding.root
}
}



動作結果

ListViewの子要素をタップすると、それぞれのデータをToast表示します。


まとめ

ButterKnifeからData Bindingに乗り換える目的で今回のサンプルアプリを作りましたが、少ないコード量で求める機能を実現できたので、Data Bindingの有用性を確認することができました。

もっと良い方法やここはこうしたほうがいいなどありましたら、コメントやGitHubのPullRequestで教えて頂けると嬉しいです。


参考URL

参考にさせていただきました。ありがとうございます。:bow: