Create empty view for RecyclerViewFragment

This commit is contained in:
Phillip Hsu
2016-09-05 23:31:01 -07:00
parent 34930fa2b3
commit edf33240e6
7 changed files with 107 additions and 20 deletions
@@ -1,7 +1,10 @@
package com.philliphsu.clock2;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.annotation.DrawableRes;
import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader;
import android.support.v7.widget.LinearLayoutManager;
@@ -9,8 +12,10 @@ import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.philliphsu.clock2.alarms.ScrollHandler;
import com.philliphsu.clock2.aospdatetimepicker.Utils;
import com.philliphsu.clock2.model.BaseItemCursor;
import com.philliphsu.clock2.model.ObjectWithId;
@@ -34,7 +39,12 @@ public abstract class RecyclerViewFragment<
// TODO: Rename id to recyclerView?
// TODO: Rename variable to mRecyclerView?
@Bind(R.id.list) RecyclerView mList;
@Bind(R.id.list)
RecyclerView mList;
@Nullable // Subclasses are not required to use the default content layout, so this may not be present.
@Bind(R.id.empty_view)
TextView mEmptyView;
public abstract void onFabClick();
@@ -51,6 +61,33 @@ public abstract class RecyclerViewFragment<
*/
protected abstract A onCreateAdapter();
/**
* @return a resource to a String that will be displayed when the list is empty
*/
@StringRes
protected int emptyMessage() {
// The reason this isn't abstract is so we don't require subclasses that
// don't have an empty view to implement this.
return 0;
}
/**
* @return a resource to a Drawable that will be displayed when the list is empty
*/
@DrawableRes
protected int emptyMessageIcon() {
// TODO: If this is the same for all RecyclerViewFragments, then why not just specify
// the compound drawable in XML?
return R.drawable.ic_empty_list_96dp;
}
/**
* @return whether the list should show an empty view when its adapter has an item count of zero
*/
protected boolean hasEmptyView() {
return true;
}
/**
* @return the adapter instance created from {@link #onCreateAdapter()}
*/
@@ -73,6 +110,13 @@ public abstract class RecyclerViewFragment<
View view = super.onCreateView(inflater, container, savedInstanceState);
mList.setLayoutManager(getLayoutManager());
mList.setAdapter(mAdapter = onCreateAdapter());
if (hasEmptyView() && mEmptyView != null) {
// Configure the empty view, even if there currently are items.
mEmptyView.setText(emptyMessage());
int iconColor = Utils.getTextColorFromThemeAttr(getActivity(), R.attr.themedIconTint);
Drawable emptyMessageIcon = Utils.getTintedDrawable(getActivity(), emptyMessageIcon(), iconColor);
mEmptyView.setCompoundDrawablesRelativeWithIntrinsicBounds(null, emptyMessageIcon, null, null);
}
return view;
}
@@ -87,6 +131,12 @@ public abstract class RecyclerViewFragment<
@Override
public void onLoadFinished(Loader<C> loader, C data) {
mAdapter.swapCursor(data);
if (hasEmptyView() && mEmptyView != null) {
// TODO: Last I checked after a fresh install, this worked fine.
// However, previous attempts (without fresh installs) didn't hide the empty view
// upon an item being added. Verify this is no longer the case.
mEmptyView.setVisibility(mAdapter.getItemCount() == 0 ? View.VISIBLE : View.GONE);
}
// This may have been a requery due to content change. If the change
// was an insertion, scroll to the last modified alarm.
performScrollToStableId();
@@ -146,6 +146,11 @@ public class AlarmsFragment extends RecyclerViewFragment<
return new AlarmsCursorAdapter(this, mAlarmController);
}
@Override
protected int emptyMessage() {
return R.string.empty_alarms_container;
}
// TODO: We're not using EditAlarmActivity anymore, so move this logic somewhere else.
// We also don't need to delay the change to get animations working.
@Override
@@ -160,6 +160,11 @@ public class StopwatchFragment extends RecyclerViewFragment<
+ ", mPauseTime = " + mPauseTime);
}
@Override
protected boolean hasEmptyView() {
return false;
}
@Override
public Loader<LapCursor> onCreateLoader(int id, Bundle args) {
return new LapsCursorLoader(getActivity());
@@ -102,6 +102,11 @@ public class TimersFragment extends RecyclerViewFragment<
}
}
@Override
protected int emptyMessage() {
return R.string.empty_timers_container;
}
@Override
public Loader<TimerCursor> onCreateLoader(int id, Bundle args) {
return new TimersListCursorLoader(getActivity());