RecyclerView (3) 行をクリックしてイベントを発行する

2020年1月19日日曜日

Android Fragment RecyclerView

t f B! P L

概要

 RecyclerViewで行をクリックするとイベントが発行され、MainFragmentがそのイベントを受け取り、何らかの処理を行ふまでを実装する。前までに作成したアプリケーションの改造として行ふ。



 実現方式はいろいろあるやうだが、ここでは以下のやうにして listenerをAdapterに渡す方式とする。

  • Adapterは、コンストラクタで イベント発生時の実行関数を受け取る。
  • Adapterは、onBIndViewHolder実行時にその関数をクリックイベントとして登録する。
  • Adapterは、イベントリスナを interfaceとして定義する。
  • MainFragmentは、イベントリスナを実装し、Adapter生成時に引数としてそれを渡す。

全体像

 MainFragmentクラスと CustomAdapterクラスを変更することになる。クラス間の関係、クラス内の関数の実装の全体像は下図。

Adapter ファイルの編集 - CustomAdapter.kt

interface定義

 まず イベントリスナーとなる interfaceを CustomAdapterクラス内で定義する。以下。


    interface OnRowClickListener {
        fun onRowClicked (pos:Int) // posは行番号
    }

クラスのコンストラクタの定義

 引数で イベントリスナを受け取るやうにする。受けた listenerは、onBindViewHolderで登録する際に必要なので、覚へておく。


class CustomAdapter(listener:OnRowClickListener): RecyclerView.Adapter() {

    val listener = listener //listenerを覚へておく
    //中略
}

イベントリスナーの登録

イベントリスナーを登録する。 onBIndViewHolder ( )の中で登録する。

   override fun onBindViewHolder(holder: EachRowViewHolder, position: Int) {
        //中略
        holder.itemView.setOnClickListener {
            listener.onRowClicked(position)
        }
    }

 以上が Adapterの実装の変更。

MainFragmentの編集 - MainFragment.kt

インタフェースの継承の追加

MainFragmentのクラス定義で 、上記で定義したリスナー interfaceを継承する。以下。

class MainFragment : Fragment(), CustomAdapter.OnRowClickListener {
     //中略
}

イベントリスナーのinterfaceの実装

実装は以下。単に Toastを表示するだけ。

    override fun onRowClicked(pos: Int) {
        Toast.makeText(context,"Clicked " + pos.toString(), Toast.LENGTH_SHORT).show()
    }

Adapter生成時に イベントリスナーの実体を渡す

thisはこのクラス全体のオブジェクト。asで型変換して interfaceの実装の OnRowClickListenerとしてゐる。

val adapter = CustomAdapter(this as CustomAdapter.OnRowClickListener)

動作確認

 ビルドして動作確認する。 RecyclerViewで表示されたリストをクリックすると、Toastで行番号が表示されることを確認する。

コード全体

MainFragment.kt


class MainFragment : Fragment(), CustomAdapter.OnRowClickListener {

    companion object {
        fun newInstance() = MainFragment()
    }

    private lateinit var viewModel: MainViewModel

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        val view = inflater.inflate(R.layout.main_fragment, container, false)


        val adapter = CustomAdapter(this as CustomAdapter.OnRowClickListener)

        val recyclerView = view.findViewById(R.id.recyclerView)

        recyclerView.adapter = adapter
        recyclerView.layoutManager = LinearLayoutManager(context,LinearLayoutManager.VERTICAL, false)

        return view
    }

    override fun onRowClicked(pos: Int) {
        Toast.makeText(context,"Clicked " + pos.toString(), Toast.LENGTH_SHORT).show()
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        viewModel = ViewModelProviders.of(this).get(MainViewModel::class.java)
        // TODO: Use the ViewModel
    }

}

CustomAdapter.kt


class CustomAdapter(listener:OnRowClickListener): RecyclerView.Adapter() {

    val listener = listener

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): EachRowViewHolder {

        val layoutInflater = LayoutInflater.from(parent.context)
        val view = layoutInflater.inflate(R.layout.each_row, parent, false)

        val viewHolder =EachRowViewHolder(view)

        return viewHolder
    }

    override fun getItemCount(): Int {
        return 50
    }

    override fun onBindViewHolder(holder: EachRowViewHolder, position: Int) {
        holder.rowView1.text = "AAA" + position.toString()
        holder.rowView2.text = "BBB" + position.toString()

        holder.itemView.setOnClickListener {
            listener.onRowClicked(position)
        }
    }

    interface OnRowClickListener {
        fun onRowClicked (pos:Int)
    }
}

(了)

アーカイブ