StickyListHeaders風のライブラリを自作する-4
StickyListHeaders風のライブラリを自作する-3 - 日々是好日の続き。
override が必要なメソッドの整理。
ユーザ側でオーバーライドするメソッド
- PinningListView
- RecyclerView を拡張した View
setOnHeaderTouchListener
を搭載し、ヘッダー部分をタッチしたときのリスナーをセット可としている- オーバーライドは特に必要なし
- PinningListAdapter (abstract)
- PinningListView 用の抽象アダプタ
onCreateViewHolder
onBindViewHolder
getItemViewType
bindHeaderData
- 内部クラスとして
ViewHolder
を要実装
- PinningItemDecoration
- ヘッダー描画用の ItemDecoration クラス
- インスタンス化して PinningListView に突っ込めば OK(引数にアダプタを渡すこと)
- PinningListListener インターフェースをもつ
- PinningHeaderTouchListener
PinningListView#setOnHeaderTouchListener
でヘッダータッチイベントを定義するためのインターフェースonHeaderTouch
を実装する
つまるところ、PinningListAdapter を継承したアダプタ
のみ実装が必要となる。
ヘッダーにタッチイベントを付けたい場合は PinningHeaderTouchListener
を使って実装してやる。
使用例
こんな感じになる。ヘッダーの色変化はあえてやってるので、あまり気にせず…。
ヘッダーをタップし、ヘッダーの位置にスクロールしたいときの実装は以下のとおり。
adapterPosition
の取得がちょっとめんどくさい。
Kotlin では object 式で匿名クラスを実装してやる。
val decor = PinningItemDecoration(adapter) pinningListView.setOnHeaderTouchListener(object: PinningHeaderTouchListener { override fun onTouchHeader(rv: RecyclerView, e: MotionEvent): Boolean { val headerHeight = decor.getHeaderHeight() if (headerHeight != null && e.y <= headerHeight && rv.scrollState == RecyclerView.SCROLL_STATE_IDLE){ val listener = rv.adapter as PinningListDecoration.PinningListListener val topView = rv.getChildAt(0) val adapterPosition = rv.getChildAdapterPosition(topView) val headerPosition = listener.getCurrentHeaderPosition(adapterPosition) if (headerPosition != null) { rv.layoutManager?.scrollToPosition(headerPosition) return true } } return false } })