1. ホーム
  2. android

KotlinのRecyclerView itemClickListener [終了しました]。

2023-09-07 01:18:03

質問

私は3年間のAndroidの経験の後、Kotlinで最初のアプリを書いています。 ただ、KotlinでRecyclerViewでitemClickListenerを利用する方法について混乱しています。

私はtrait (edit: now interface) アプローチを試しましたが、非常にJavaのようでした。

public class MainActivity : ActionBarActivity() {

  protected override fun onCreate(savedInstanceState: Bundle?) {

    // set content view etc go above this line

    class itemClickListener : ItemClickListener {
      override fun onItemClick(view: View, position: Int) {
        Toast.makeText(this@MainActivity, "TEST: " + position, Toast.LENGTH_SHORT).show()
      }
    }

    val adapter = DrawerAdapter(itemClickListener())
    mRecyclerView.setAdapter(adapter)
 }

  trait ItemClickListener {
    fun onItemClick(view: View, position: Int)
  }
}

これは非常に冗長なように思えたので、インナークラスのアプローチを試してみました。

inner class ItemClickListener {
    fun onItemClick(view: View, position: Int) {
        startActivityFromFragmentForResult<SelectExerciseActivity>(SELECT_EXERCISES)
    }
}

そして、このようにアダプターのクリックリスナーを設定するだけです。

val adapter = WorkoutsAdapter(ItemClickListener())

しかし、私はまだこれに満足していません。なぜなら、もっと良い、すっきりした方法があるのではないかと思うからです。私は本質的に次のようなことを実現しようとしています。 RecyclerView onClick

何か提案はありますか?

結局、承認された答えのバリエーションで行くことになりました。

アクティビティで関数を定義しました。

val itemOnClick: (View, Int, Int) -> Unit = { view, position, type ->
    Log.d(TAG, "test")
}

このように関数そのものをアダプタに渡します。

class ExercisesAdapter(val itemClickListener: (View, Int, Int) -> Unit) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
      // other stuff up here
      val vhExercise = ExerciseVH(view) // view holder
      // on to the view holder through the extension function
      vhExercise.onClick(itemClickListener)
    }
}

下記の承認済み回答でLoopによる拡張機能。

fun <T : RecyclerView.ViewHolder> T.onClick(event: (view: View, position: Int, type: Int) -> Unit): T {
    itemView.setOnClickListener {
        event.invoke(it, getAdapterPosition(), getItemViewType())
    }
    return this
}

どのように解決するのですか?

少し変わった方法があります。ViewHolderの拡張機能を作成することができます。

fun <T : RecyclerView.ViewHolder> T.listen(event: (position: Int, type: Int) -> Unit): T {
    itemView.setOnClickListener {
        event.invoke(getAdapterPosition(), getItemViewType())
    }
    return this
}

そして、これをアダプタで次のように使います。

class MyAdapter : RecyclerView.Adapter<MyAdapter.MyViewHolder>() {

    val items: MutableList<String> = arrayListOf()

    override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): MyViewHolder? {
        val inflater = LayoutInflater.from(parent!!.getContext())
        val view = inflater.inflate(R.layout.item_view, parent, false)
        return MyViewHolder(view).listen { pos, type ->
            val item = items.get(pos)
            //TODO do other stuff here
        }
    }

    override fun onBindViewHolder(holder: MyViewHolder?, position: Int) {

    }

    override fun getItemCount(): Int {
        return items.size()
    }


    class MyViewHolder(view: View) : RecyclerView.ViewHolder(view) {

    }
}

私は同僚と一緒に ライブラリ を提供しています。