RecyclerViewにはListViewなどと異なりsetEmptyViewが用意されていないため、自分で実装する必要がある。
使うたびにActivityなどでgetItemCountを取得して切り替えてもいいんだけど
めんどくさいじゃん!何回も使うようならどこかで絶対忘れるじゃん!
という理由でCustomViewを作ることにしました。
紆余曲折の軌跡をここに記す・・・
最終的に書いたコード
RecyclerViewを継承したCustomViewの作成
class SupportEmptyRecyclerView : RecyclerView {
@JvmOverloads public constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0)
: super(context, attrs, defStyleAttr) {
}
var emptyView: View? = null
private val emptyObserver = object : RecyclerView.AdapterDataObserver() {
override fun onChanged() {
if (adapter != null && emptyView != null) {
val isEmpty = adapter.itemCount == 0
emptyView!!.visibility = if (isEmpty) View.VISIBLE else View.GONE
visibility = if (isEmpty) View.GONE else View.VISIBLE
}
}
}
override fun setAdapter(adapter: RecyclerView.Adapter<*>?) {
super.setAdapter(adapter)
adapter?.registerAdapterDataObserver(emptyObserver)
emptyObserver.onChanged()
}
}
RecyclerViewの状態が変わった時に描画を変更するよう、Observerを登録。
このへんのstackoverflow参考にした。
RecyclerViewの要素数に応じて表示を切り替える。
visibilityかよ〜と思ったけどListViewに生えてるsetEmptyViewの内部実装もそうらしい。
setAdapterをoverrideしているので、ActivityやFragmentでsetAdapterをするだけで設定される。
emptyView用のXMLの作成
<layout xmlns:android="http://schemas.android.com/apk/res/android"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
>
<ImageView
android:id="@+id/empty_image"
android:layout_width="@dimen/empty_image_size"
android:layout_height="@dimen/empty_image_size"
android:layout_gravity="center"
android:layout_margin="@dimen/spacing"
android:src="@drawable/no_item"
/>
<TextView
android:id="@+id/empty_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="表示する内容がありません"
android:textColor="@color/black_alpha_54"
android:textSize="@dimen/text_large"
/>
</LinearLayout>
</layout>
RecyclerViewを乗せたいレイアウトファイルに追加する
〜略〜
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<me.rm_rf.view.widget.SupportEmptyRecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="@dimen/spacing_xsmall"
/>
<include
layout="@layout/view_empty"
android:id="@+id/included_empty_view"
/>
</RelativeLayout>
ここでポイントなのはEmptyViewをRecyclerViewと同じファイルに書くこと。
RecylerViewとEmptyViewをRelativeLayoutで括ること。
同じ階層に置いていないと、RecyclerViewの範囲内でEmptyViewを
android:gravity="center"
したいのに効かなかったり、なんかうまいこと表示されなかったりする。
setAdaptersするだけでitem=0のときにEmptyViewが表示されるの便利だな〜