あんまりRecyclerView使う機会が無かったんですけど仕事で触る機会があったのでめも。
AdapterのgetItemViewTypeをオーバーライドしてデータに応じたViewTypeを返してあげるとレイアウトを使い分けることが出来ます。enum使うと綺麗に書ける感じですね。
下の例はItemEntityを継承した3種類のクラスに応じたレイアウトを表示するサンプルです。なお仕事では今のとこKotlinで書いてるのでサンプルもKotlinです。
CustomAdapter.kt
class CustomAdapter(context: Context,
val itemList: MutableList<ItemEntity>) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
enum class ViewType(val id: Int) {
HOGE(0) {
override fun createViewHolder(inflater: LayoutInflater, viewGroup: ViewGroup?): RecyclerView.ViewHolder {
// タイプに応じたViewHolderを返す
return HogeViewHolder (inflater.inflate(R.layout.adapter_row_hoge, viewGroup, false))
}
override fun bindViewHolder(holder: RecyclerView.ViewHolder, itemEntity: ItemEntity) {
holder as HogeViewHolder
// Viewにそれぞれのデータを表示(以下略)
}
},
FUGA(1) {
override fun createViewHolder(inflater: LayoutInflater, viewGroup: ViewGroup?): RecyclerView.ViewHolder {
return FugaViewHolder (inflater.inflate(R.layout.adapter_row_fuga, viewGroup, false))
}
override fun bindViewHolder(holder: RecyclerView.ViewHolder, itemEntity: ItemEntity) {
holder as FugaViewHolder
// Viewにそれぞれのデータを表示(以下略)
}
},
PIYO(2) {
override fun createViewHolder(inflater: LayoutInflater, viewGroup: ViewGroup?): RecyclerView.ViewHolder {
return PiyoViewHolder (inflater.inflate(R.layout.adapter_row_piyo, viewGroup, false))
}
override fun bindViewHolder(holder: RecyclerView.ViewHolder, itemEntity: ItemEntity) {
holder as PiyoViewHolder
// Viewにそれぞれのデータを表示(以下略)
}
};
companion object {
fun forId(id: Int): ViewType {
for (viewType: ViewType in values()) {
if (viewType.id == id) {
return viewType
}
}
throw AssertionError("no enum found for the id. you forgot to implement?")
}
}
abstract fun createViewHolder(inflater: LayoutInflater, viewGroup: ViewGroup?): RecyclerView.ViewHolder
abstract fun bindViewHolder(holder: RecyclerView.ViewHolder, itemEntity: ItemEntity)
}
companion object {
// レイアウトに応じたViewHolderを作る。KotterKnifeを使うとBindが楽
private class HogeViewHolder(itemView: View?) : RecyclerView.ViewHolder(itemView) {
val imageHoge: ImageView by bindView(R.id.adapter_row_hoge_image)
val textHoge: TextView by bindView(R.id.adapter_row_hoge_text)
}
private class FugaViewHolder(itemView: View?) : RecyclerView.ViewHolder(itemView) {
val imageFuga: ImageView by bindView(R.id.adapter_row_fuga_image)
val textFuga: TextView by bindView(R.id.adapter_row_fuga_text)
}
private class PiyoViewHolder(itemView: View?) : RecyclerView.ViewHolder(itemView) {
val imagePiyo: ImageView by bindView(R.id.adapter_row_piyo_image)
val textPiyo: TextView by bindView(R.id.adapter_row_piyo_text)
}
}
private val inflater = LayoutInflater.from(context)
// Viewを作る時に呼ばれる
override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): RecyclerView.ViewHolder? {
return ViewType.forId(viewType).createViewHolder(inflater, parent)
}
// ViewにデータをBindする時に呼ばれる
override fun onBindViewHolder(holder: RecyclerView.ViewHolder?, position: Int) {
holder ?: return
val item = itemList[position]
ViewType.forId(holder.itemViewType).bindViewHolder(holder, item)
}
override fun getItemCount(): Int {
return itemList.size
}
// 型に応じたViewTypeを返す
override fun getItemViewType(position: Int): Int {
val item = itemList[position]
return when (item) {
is HogeItemEntity -> {
ViewType.HOGE.id
}
is FugaItemEntity -> {
ViewType.FUGA.id
}
is PiyoItemEntity -> {
ViewType.PIYO.id
}
else -> {
throw AssertionError("no enum found for the id. you forgot to implement?")
}
}
}
}