search
LoginSignup
15

More than 3 years have passed since last update.

posted at

updated at

Groupie をつかってみる

はじめに

VALU Advent Calendar 2018 の17日目です。
Advent Calendar なるものに初めて参加したのですが…ちょっとドキドキです!

今回は今更感が満載ですが RecyclerView のあるある実装が簡単になる Groupie を使ってヘッダーのあるリストを作成したいと思います。

手順

Groupie のサンプルプロジェクト groupie/example-databinding を参考にして実装していきます。

  1. レイアウトを作成
  2. ViewHolder を作成
  3. RecyclerView に add

Step1

RecyclerView に表示するレイアウトを作成します。

ヘッダー

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

  <data>  
    <variable  name="viewModel"
      type="me.aluceps.practicerecyclerview.ItemViewModel"  
      />  
  </data>  

  <androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"  
    android:layout_height="wrap_content"  
    >  

    <TextView  android:id="@+id/item_text"  
      android:layout_width="0dp"  
      android:layout_height="wrap_content"  
      android:padding="16dp"  
      android:text="@{viewModel.text}"  
      app:layout_constraintBottom_toBottomOf="parent"  
      app:layout_constraintEnd_toEndOf="parent"  
      app:layout_constraintStart_toStartOf="parent"  
      app:layout_constraintTop_toTopOf="parent"  
      tools:text="ヘッダー1"  
      />  
  </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

アイテム

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

  <data>  
    <variable  name="viewModel"  
      type="me.aluceps.practicerecyclerview.ItemViewModel"  
      />  
  </data>  

  <androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"  
    android:layout_height="wrap_content"  
    android:orientation="vertical"  
    >  

  <TextView  android:id="@+id/item_text"  
    android:layout_width="0dp"  
    android:layout_height="wrap_content"  
    android:background="@android:color/white"  
    android:padding="16dp"  
    android:text="@{viewModel.text}"  
    app:layout_constraintBottom_toBottomOf="parent"  
    app:layout_constraintEnd_toEndOf="parent"  
    app:layout_constraintStart_toStartOf="parent"  
    app:layout_constraintTop_toTopOf="parent"  
    tools:text="アイテム1"  
    />  
  </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

Binding させる ViewModel は ObservableField を1つ持つだけのクラスです。

class ItemViewModel : BaseObservable() {  
    val text: ObservableField<String> = ObservableField()  
}

Step2

ヘッダーとアイテムの ViewHolder を作成します。

ヘッダー

class ItemHeaderViewHolder(id: Long) : BindableItem<ItemHeaderBinding>(id) {  

  private val viewModel = ItemViewModel()  

  override fun getLayout(): Int = R.layout.item_header  

  override fun bind(viewBinding: ItemHeaderBinding, position: Int) {  
    viewBinding.viewModel = viewModel  
  }  

  fun setText(value: String) {  
    viewModel.text.set(value)  
    viewModel.notifyChange()  
  }  
}

アイテム

class ItemNormalViewHolder(id: Long) : BindableItem<ItemNormalBinding>(id) {  

  private val viewModel = ItemViewModel()  

  override fun getLayout(): Int = R.layout.item_normal  

  override fun bind(viewBinding: ItemNormalBinding, position: Int) {  
    viewBinding.viewModel = viewModel  
  }  

  fun setText(value: String) {  
    viewModel.text.set(value)  
    viewModel.notifyChange()  
  }  
}

Step3

これまで作成したヘッダーとアイテムを使って RecyclerView に追加する処理を書きます。

private var groupAdapter: GroupAdapter<ViewHolder>? = null  

override fun onCreate(savedInstanceState: Bundle?) {  
  super.onCreate(savedInstanceState)  
  groupAdapter = GroupAdapter()  
  initializeRecyclerView()  
  for (i in 1..5) addItems(i)  
}  

private fun initializeRecyclerView() {  
  binding.recyclerView.run {  
    adapter = groupAdapter  
    layoutManager = LinearLayoutManager(this@MainActivity)  
    addItemDecoration(DividerItemDecoration(context, LinearLayoutManager.VERTICAL))  
  }  
}  

private fun addItems(index: Int) {  
  val section = Section()  
  section.setHeader(ItemHeaderViewHolder(index.toLong()).apply { setText("Section No.$index") })  
  for (i in 1..20) section.add(ItemNormalViewHolder(i.toLong()).apply { setText("Section No:$index Row:$i") })  
  groupAdapter?.add(section)  
}

Groupie は Section という単位でヘッダーとアイテムを追加していきます。Section.setHeader() でヘッダーを追加し Section.add() でアイテムを追加しています。そして GroupAdapter に追加することでヘッダーとアイテムの組み合わせを RecyclerView で表現できるようです。とても簡単ですね。

イメージ

まとめ

Groupie を使うことでわずか3ステップでヘッダーとリストのある RecyclerView ができました。Groupie を使わずに手作りした場合は Adapter の作成が必要になる上に ViewType に応じた処理を書く必要があります。難しいわけではないのですが ViewType を追加するたびに書くのは結構面倒なんですよね…!

そういった手間を省くことができるので Groupie はとてもオススメです!

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
15