Simplify empty view handling on recycler views

This commit is contained in:
ByteHamster 2019-05-03 11:06:04 +02:00
parent 7a921e0024
commit 06c15fd9e6
9 changed files with 131 additions and 59 deletions

View File

@ -51,6 +51,7 @@ import de.danoeh.antennapod.core.util.FeedItemUtil;
import de.danoeh.antennapod.core.util.LongList;
import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
import de.danoeh.antennapod.menuhandler.MenuItemUtils;
import de.danoeh.antennapod.view.EmptyViewHandler;
import de.greenrobot.event.EventBus;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
@ -76,7 +77,7 @@ public class AllEpisodesFragment extends Fragment {
RecyclerView recyclerView;
AllEpisodesRecycleAdapter listAdapter;
private ProgressBar progLoading;
private View emptyView;
EmptyViewHandler emptyView;
List<FeedItem> episodes;
private List<Downloader> downloaderList;
@ -334,10 +335,10 @@ public class AllEpisodesFragment extends Fragment {
onFragmentLoaded();
}
emptyView = root.findViewById(R.id.emptyView);
emptyView.setVisibility(View.GONE);
((TextView)emptyView.findViewById(R.id.emptyViewTitle)).setText(R.string.no_all_episodes_head_label);
((TextView)emptyView.findViewById(R.id.emptyViewMessage)).setText(R.string.no_all_episodes_label);
emptyView = new EmptyViewHandler(getContext());
emptyView.attachToRecyclerView(recyclerView);
emptyView.setTitle(R.string.no_all_episodes_head_label);
emptyView.setMessage(R.string.no_all_episodes_label);
return root;
}
@ -350,14 +351,14 @@ public class AllEpisodesFragment extends Fragment {
new DefaultActionButtonCallback(mainActivity), showOnlyNewEpisodes());
listAdapter.setHasStableIds(true);
recyclerView.setAdapter(listAdapter);
emptyView.updateAdapter(listAdapter);
}
emptyView.setVisibility(View.GONE);
recyclerView.setVisibility(View.VISIBLE);
listAdapter.notifyDataSetChanged();
} else {
listAdapter = null;
recyclerView.setVisibility(View.GONE);
emptyView.setVisibility(View.VISIBLE);
emptyView.updateAdapter(listAdapter);
}
restoreScrollPosition();
@ -497,7 +498,7 @@ public class AllEpisodesFragment extends Fragment {
}
if (viewsCreated && !itemsLoaded) {
recyclerView.setVisibility(View.GONE);
emptyView.setVisibility(View.GONE);
emptyView.hide();
progLoading.setVisibility(View.VISIBLE);
}
disposable = Observable.fromCallable(this::loadData)

View File

@ -51,8 +51,8 @@ public class FavoriteEpisodesFragment extends AllEpisodesFragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View root = super.onCreateViewHelper(inflater, container, savedInstanceState,
R.layout.all_episodes_fragment);
((TextView)root.findViewById(R.id.emptyViewTitle)).setText(R.string.no_fav_episodes_head_label);
((TextView)root.findViewById(R.id.emptyViewMessage)).setText(R.string.no_fav_episodes_label);
emptyView.setTitle(R.string.no_fav_episodes_head_label);
emptyView.setMessage(R.string.no_fav_episodes_label);
ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
@Override

View File

@ -46,8 +46,8 @@ public class NewEpisodesFragment extends AllEpisodesFragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View root = super.onCreateViewHelper(inflater, container, savedInstanceState,
R.layout.all_episodes_fragment);
((TextView)root.findViewById(R.id.emptyViewTitle)).setText(R.string.no_new_episodes_head_label);
((TextView)root.findViewById(R.id.emptyViewMessage)).setText(R.string.no_new_episodes_label);
emptyView.setTitle(R.string.no_new_episodes_head_label);
emptyView.setMessage(R.string.no_new_episodes_label);
ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
@Override

View File

@ -52,6 +52,7 @@ import de.danoeh.antennapod.core.util.LongList;
import de.danoeh.antennapod.core.util.QueueSorter;
import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
import de.danoeh.antennapod.menuhandler.MenuItemUtils;
import de.danoeh.antennapod.view.EmptyViewHandler;
import de.greenrobot.event.EventBus;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
@ -72,7 +73,7 @@ public class QueueFragment extends Fragment {
private TextView infoBar;
private RecyclerView recyclerView;
private QueueRecyclerAdapter recyclerAdapter;
private View emptyView;
private EmptyViewHandler emptyView;
private ProgressBar progLoading;
private List<FeedItem> queue;
@ -502,11 +503,11 @@ public class QueueFragment extends Fragment {
}
);
itemTouchHelper.attachToRecyclerView(recyclerView);
//empty view
emptyView = root.findViewById(R.id.emptyView);
emptyView.setVisibility(View.GONE);
((TextView)emptyView.findViewById(R.id.emptyViewTitle)).setText(R.string.no_items_header_label);
((TextView)emptyView.findViewById(R.id.emptyViewMessage)).setText(R.string.no_items_label);
emptyView = new EmptyViewHandler(getContext());
emptyView.attachToRecyclerView(recyclerView);
emptyView.setTitle(R.string.no_items_header_label);
emptyView.setMessage(R.string.no_items_label);
progLoading = root.findViewById(R.id.progLoading);
progLoading.setVisibility(View.VISIBLE);
@ -522,13 +523,13 @@ public class QueueFragment extends Fragment {
new DefaultActionButtonCallback(activity), itemTouchHelper);
recyclerAdapter.setHasStableIds(true);
recyclerView.setAdapter(recyclerAdapter);
emptyView.updateAdapter(recyclerAdapter);
}
emptyView.setVisibility(View.GONE);
recyclerView.setVisibility(View.VISIBLE);
} else {
recyclerAdapter = null;
recyclerView.setVisibility(View.GONE);
emptyView.setVisibility(View.VISIBLE);
emptyView.updateAdapter(recyclerAdapter);
}
if (restoreScrollPosition) {
@ -641,7 +642,7 @@ public class QueueFragment extends Fragment {
}
if (queue == null) {
recyclerView.setVisibility(View.GONE);
emptyView.setVisibility(View.GONE);
emptyView.hide();
progLoading.setVisibility(View.VISIBLE);
}
disposable = Observable.fromCallable(DBReader::getQueue)

View File

@ -1,59 +1,95 @@
package de.danoeh.antennapod.view;
import android.app.Activity;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import de.danoeh.antennapod.R;
public class EmptyViewHandler extends View {
private Activity activity;
private int title;
private int message;
public class EmptyViewHandler {
private boolean layoutAdded = false;
private RecyclerView recyclerView;
private RecyclerView.Adapter adapter;
private final View emptyView;
private final TextView tvTitle;
private final TextView tvMessage;
public EmptyViewHandler(Context context) {
super(context);
this.setActivity((Activity) context);
}
public int getTitle() {
return title;
emptyView = View.inflate(context, R.layout.empty_view_layout, null);
tvTitle = emptyView.findViewById(R.id.emptyViewTitle);
tvMessage = emptyView.findViewById(R.id.emptyViewMessage);
}
public void setTitle(int title) {
this.title = title;
}
public int getMessage() {
return message;
tvTitle.setText(title);
}
public void setMessage(int message) {
this.message = message;
tvMessage.setText(message);
}
public void hide() {
emptyView.setVisibility(View.GONE);
}
public void attachToListView(ListView listView) {
View emptyView = getActivity().getLayoutInflater().inflate(R.layout.empty_view_layout, null);
if (layoutAdded) {
throw new IllegalStateException("Can not attach to ListView multiple times");
}
layoutAdded = true;
((ViewGroup) listView.getParent()).addView(emptyView);
listView.setEmptyView(emptyView);
TextView tvTitle = (TextView) emptyView.findViewById(R.id.emptyViewTitle);
tvTitle.setText(title);
TextView tvMessage = (TextView) emptyView.findViewById(R.id.emptyViewMessage);
tvMessage.setText(message);
}
public Activity getActivity() {
return activity;
public void attachToRecyclerView(RecyclerView recyclerView) {
if (layoutAdded) {
throw new IllegalStateException("Can not attach to ListView multiple times");
}
layoutAdded = true;
this.recyclerView = recyclerView;
ViewGroup parent = ((ViewGroup) recyclerView.getParent());
parent.addView(emptyView);
updateAdapter(recyclerView.getAdapter());
if (parent instanceof RelativeLayout) {
RelativeLayout.LayoutParams layoutParams =
(RelativeLayout.LayoutParams)emptyView.getLayoutParams();
layoutParams.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE);
emptyView.setLayoutParams(layoutParams);
}
}
public void setActivity(Activity activity) {
this.activity = activity;
public void updateAdapter(RecyclerView.Adapter adapter) {
if (this.adapter != null) {
this.adapter.unregisterAdapterDataObserver(adapterObserver);
}
this.adapter = adapter;
if (adapter != null) {
adapter.registerAdapterDataObserver(adapterObserver);
}
updateVisibility();
}
private final SimpleAdapterDataObserver adapterObserver = new SimpleAdapterDataObserver() {
@Override
public void anythingChanged() {
updateVisibility();
}
};
private void updateVisibility() {
boolean empty;
if (adapter == null) {
empty = true;
} else {
empty = adapter.getItemCount() == 0;
}
recyclerView.setVisibility(empty ? View.GONE : View.VISIBLE);
emptyView.setVisibility(empty ? View.VISIBLE : View.GONE);
}
}

View File

@ -0,0 +1,41 @@
package de.danoeh.antennapod.view;
import android.support.annotation.Nullable;
import android.support.v7.widget.RecyclerView;
/**
* AdapterDataObserver that relays all events to the method anythingChanged().
*/
public abstract class SimpleAdapterDataObserver extends RecyclerView.AdapterDataObserver {
public abstract void anythingChanged();
@Override
public void onChanged() {
anythingChanged();
}
@Override
public void onItemRangeChanged(int positionStart, int itemCount) {
anythingChanged();
}
@Override
public void onItemRangeChanged(int positionStart, int itemCount, @Nullable Object payload) {
anythingChanged();
}
@Override
public void onItemRangeInserted(int positionStart, int itemCount) {
anythingChanged();
}
@Override
public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {
anythingChanged();
}
@Override
public void onItemRangeRemoved(int positionStart, int itemCount) {
anythingChanged();
}
}

View File

@ -17,10 +17,6 @@
tools:itemCount="13"
tools:listitem="@layout/new_episodes_listitem" />
<include
android:id="@+id/emptyView"
layout="@layout/empty_view_layout"/>
<ProgressBar
android:id="@+id/progLoading"
android:layout_width="wrap_content"

View File

@ -4,6 +4,7 @@
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
android:layout_centerInParent="true"
xmlns:tools="http://schemas.android.com/tools">
<TextView

View File

@ -27,10 +27,6 @@
android:layout_below="@id/divider"
android:scrollbars="vertical"/>
<include
android:id="@+id/emptyView"
layout="@layout/empty_view_layout"/>
<ProgressBar
android:id="@+id/progLoading"
android:layout_width="wrap_content"