Simplify empty view handling on recycler views
This commit is contained in:
parent
7a921e0024
commit
06c15fd9e6
|
@ -51,6 +51,7 @@ import de.danoeh.antennapod.core.util.FeedItemUtil;
|
||||||
import de.danoeh.antennapod.core.util.LongList;
|
import de.danoeh.antennapod.core.util.LongList;
|
||||||
import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
|
import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
|
||||||
import de.danoeh.antennapod.menuhandler.MenuItemUtils;
|
import de.danoeh.antennapod.menuhandler.MenuItemUtils;
|
||||||
|
import de.danoeh.antennapod.view.EmptyViewHandler;
|
||||||
import de.greenrobot.event.EventBus;
|
import de.greenrobot.event.EventBus;
|
||||||
import io.reactivex.Observable;
|
import io.reactivex.Observable;
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||||
|
@ -76,7 +77,7 @@ public class AllEpisodesFragment extends Fragment {
|
||||||
RecyclerView recyclerView;
|
RecyclerView recyclerView;
|
||||||
AllEpisodesRecycleAdapter listAdapter;
|
AllEpisodesRecycleAdapter listAdapter;
|
||||||
private ProgressBar progLoading;
|
private ProgressBar progLoading;
|
||||||
private View emptyView;
|
EmptyViewHandler emptyView;
|
||||||
|
|
||||||
List<FeedItem> episodes;
|
List<FeedItem> episodes;
|
||||||
private List<Downloader> downloaderList;
|
private List<Downloader> downloaderList;
|
||||||
|
@ -334,10 +335,10 @@ public class AllEpisodesFragment extends Fragment {
|
||||||
onFragmentLoaded();
|
onFragmentLoaded();
|
||||||
}
|
}
|
||||||
|
|
||||||
emptyView = root.findViewById(R.id.emptyView);
|
emptyView = new EmptyViewHandler(getContext());
|
||||||
emptyView.setVisibility(View.GONE);
|
emptyView.attachToRecyclerView(recyclerView);
|
||||||
((TextView)emptyView.findViewById(R.id.emptyViewTitle)).setText(R.string.no_all_episodes_head_label);
|
emptyView.setTitle(R.string.no_all_episodes_head_label);
|
||||||
((TextView)emptyView.findViewById(R.id.emptyViewMessage)).setText(R.string.no_all_episodes_label);
|
emptyView.setMessage(R.string.no_all_episodes_label);
|
||||||
|
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
@ -350,14 +351,14 @@ public class AllEpisodesFragment extends Fragment {
|
||||||
new DefaultActionButtonCallback(mainActivity), showOnlyNewEpisodes());
|
new DefaultActionButtonCallback(mainActivity), showOnlyNewEpisodes());
|
||||||
listAdapter.setHasStableIds(true);
|
listAdapter.setHasStableIds(true);
|
||||||
recyclerView.setAdapter(listAdapter);
|
recyclerView.setAdapter(listAdapter);
|
||||||
|
emptyView.updateAdapter(listAdapter);
|
||||||
}
|
}
|
||||||
emptyView.setVisibility(View.GONE);
|
|
||||||
recyclerView.setVisibility(View.VISIBLE);
|
recyclerView.setVisibility(View.VISIBLE);
|
||||||
listAdapter.notifyDataSetChanged();
|
listAdapter.notifyDataSetChanged();
|
||||||
} else {
|
} else {
|
||||||
listAdapter = null;
|
listAdapter = null;
|
||||||
recyclerView.setVisibility(View.GONE);
|
recyclerView.setVisibility(View.GONE);
|
||||||
emptyView.setVisibility(View.VISIBLE);
|
emptyView.updateAdapter(listAdapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
restoreScrollPosition();
|
restoreScrollPosition();
|
||||||
|
@ -497,7 +498,7 @@ public class AllEpisodesFragment extends Fragment {
|
||||||
}
|
}
|
||||||
if (viewsCreated && !itemsLoaded) {
|
if (viewsCreated && !itemsLoaded) {
|
||||||
recyclerView.setVisibility(View.GONE);
|
recyclerView.setVisibility(View.GONE);
|
||||||
emptyView.setVisibility(View.GONE);
|
emptyView.hide();
|
||||||
progLoading.setVisibility(View.VISIBLE);
|
progLoading.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
disposable = Observable.fromCallable(this::loadData)
|
disposable = Observable.fromCallable(this::loadData)
|
||||||
|
|
|
@ -51,8 +51,8 @@ public class FavoriteEpisodesFragment extends AllEpisodesFragment {
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
View root = super.onCreateViewHelper(inflater, container, savedInstanceState,
|
View root = super.onCreateViewHelper(inflater, container, savedInstanceState,
|
||||||
R.layout.all_episodes_fragment);
|
R.layout.all_episodes_fragment);
|
||||||
((TextView)root.findViewById(R.id.emptyViewTitle)).setText(R.string.no_fav_episodes_head_label);
|
emptyView.setTitle(R.string.no_fav_episodes_head_label);
|
||||||
((TextView)root.findViewById(R.id.emptyViewMessage)).setText(R.string.no_fav_episodes_label);
|
emptyView.setMessage(R.string.no_fav_episodes_label);
|
||||||
|
|
||||||
ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
|
ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -46,8 +46,8 @@ public class NewEpisodesFragment extends AllEpisodesFragment {
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
View root = super.onCreateViewHelper(inflater, container, savedInstanceState,
|
View root = super.onCreateViewHelper(inflater, container, savedInstanceState,
|
||||||
R.layout.all_episodes_fragment);
|
R.layout.all_episodes_fragment);
|
||||||
((TextView)root.findViewById(R.id.emptyViewTitle)).setText(R.string.no_new_episodes_head_label);
|
emptyView.setTitle(R.string.no_new_episodes_head_label);
|
||||||
((TextView)root.findViewById(R.id.emptyViewMessage)).setText(R.string.no_new_episodes_label);
|
emptyView.setMessage(R.string.no_new_episodes_label);
|
||||||
|
|
||||||
ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
|
ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -52,6 +52,7 @@ import de.danoeh.antennapod.core.util.LongList;
|
||||||
import de.danoeh.antennapod.core.util.QueueSorter;
|
import de.danoeh.antennapod.core.util.QueueSorter;
|
||||||
import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
|
import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
|
||||||
import de.danoeh.antennapod.menuhandler.MenuItemUtils;
|
import de.danoeh.antennapod.menuhandler.MenuItemUtils;
|
||||||
|
import de.danoeh.antennapod.view.EmptyViewHandler;
|
||||||
import de.greenrobot.event.EventBus;
|
import de.greenrobot.event.EventBus;
|
||||||
import io.reactivex.Observable;
|
import io.reactivex.Observable;
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||||
|
@ -72,7 +73,7 @@ public class QueueFragment extends Fragment {
|
||||||
private TextView infoBar;
|
private TextView infoBar;
|
||||||
private RecyclerView recyclerView;
|
private RecyclerView recyclerView;
|
||||||
private QueueRecyclerAdapter recyclerAdapter;
|
private QueueRecyclerAdapter recyclerAdapter;
|
||||||
private View emptyView;
|
private EmptyViewHandler emptyView;
|
||||||
private ProgressBar progLoading;
|
private ProgressBar progLoading;
|
||||||
|
|
||||||
private List<FeedItem> queue;
|
private List<FeedItem> queue;
|
||||||
|
@ -502,11 +503,11 @@ public class QueueFragment extends Fragment {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
itemTouchHelper.attachToRecyclerView(recyclerView);
|
itemTouchHelper.attachToRecyclerView(recyclerView);
|
||||||
//empty view
|
|
||||||
emptyView = root.findViewById(R.id.emptyView);
|
emptyView = new EmptyViewHandler(getContext());
|
||||||
emptyView.setVisibility(View.GONE);
|
emptyView.attachToRecyclerView(recyclerView);
|
||||||
((TextView)emptyView.findViewById(R.id.emptyViewTitle)).setText(R.string.no_items_header_label);
|
emptyView.setTitle(R.string.no_items_header_label);
|
||||||
((TextView)emptyView.findViewById(R.id.emptyViewMessage)).setText(R.string.no_items_label);
|
emptyView.setMessage(R.string.no_items_label);
|
||||||
|
|
||||||
progLoading = root.findViewById(R.id.progLoading);
|
progLoading = root.findViewById(R.id.progLoading);
|
||||||
progLoading.setVisibility(View.VISIBLE);
|
progLoading.setVisibility(View.VISIBLE);
|
||||||
|
@ -522,13 +523,13 @@ public class QueueFragment extends Fragment {
|
||||||
new DefaultActionButtonCallback(activity), itemTouchHelper);
|
new DefaultActionButtonCallback(activity), itemTouchHelper);
|
||||||
recyclerAdapter.setHasStableIds(true);
|
recyclerAdapter.setHasStableIds(true);
|
||||||
recyclerView.setAdapter(recyclerAdapter);
|
recyclerView.setAdapter(recyclerAdapter);
|
||||||
|
emptyView.updateAdapter(recyclerAdapter);
|
||||||
}
|
}
|
||||||
emptyView.setVisibility(View.GONE);
|
|
||||||
recyclerView.setVisibility(View.VISIBLE);
|
recyclerView.setVisibility(View.VISIBLE);
|
||||||
} else {
|
} else {
|
||||||
recyclerAdapter = null;
|
recyclerAdapter = null;
|
||||||
recyclerView.setVisibility(View.GONE);
|
recyclerView.setVisibility(View.GONE);
|
||||||
emptyView.setVisibility(View.VISIBLE);
|
emptyView.updateAdapter(recyclerAdapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (restoreScrollPosition) {
|
if (restoreScrollPosition) {
|
||||||
|
@ -641,7 +642,7 @@ public class QueueFragment extends Fragment {
|
||||||
}
|
}
|
||||||
if (queue == null) {
|
if (queue == null) {
|
||||||
recyclerView.setVisibility(View.GONE);
|
recyclerView.setVisibility(View.GONE);
|
||||||
emptyView.setVisibility(View.GONE);
|
emptyView.hide();
|
||||||
progLoading.setVisibility(View.VISIBLE);
|
progLoading.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
disposable = Observable.fromCallable(DBReader::getQueue)
|
disposable = Observable.fromCallable(DBReader::getQueue)
|
||||||
|
|
|
@ -1,59 +1,95 @@
|
||||||
package de.danoeh.antennapod.view;
|
package de.danoeh.antennapod.view;
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.support.v7.widget.RecyclerView;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ListView;
|
import android.widget.ListView;
|
||||||
|
import android.widget.RelativeLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import de.danoeh.antennapod.R;
|
import de.danoeh.antennapod.R;
|
||||||
|
|
||||||
public class EmptyViewHandler extends View {
|
public class EmptyViewHandler {
|
||||||
private Activity activity;
|
private boolean layoutAdded = false;
|
||||||
private int title;
|
private RecyclerView recyclerView;
|
||||||
private int message;
|
private RecyclerView.Adapter adapter;
|
||||||
|
|
||||||
|
private final View emptyView;
|
||||||
|
private final TextView tvTitle;
|
||||||
|
private final TextView tvMessage;
|
||||||
|
|
||||||
public EmptyViewHandler(Context context) {
|
public EmptyViewHandler(Context context) {
|
||||||
super(context);
|
emptyView = View.inflate(context, R.layout.empty_view_layout, null);
|
||||||
this.setActivity((Activity) context);
|
tvTitle = emptyView.findViewById(R.id.emptyViewTitle);
|
||||||
}
|
tvMessage = emptyView.findViewById(R.id.emptyViewMessage);
|
||||||
|
|
||||||
public int getTitle() {
|
|
||||||
return title;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTitle(int title) {
|
public void setTitle(int title) {
|
||||||
this.title = title;
|
tvTitle.setText(title);
|
||||||
}
|
|
||||||
|
|
||||||
public int getMessage() {
|
|
||||||
return message;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMessage(int message) {
|
public void setMessage(int message) {
|
||||||
this.message = message;
|
tvMessage.setText(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void attachToListView(ListView listView){
|
public void hide() {
|
||||||
|
emptyView.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
View emptyView = getActivity().getLayoutInflater().inflate(R.layout.empty_view_layout, null);
|
public void attachToListView(ListView listView) {
|
||||||
|
if (layoutAdded) {
|
||||||
|
throw new IllegalStateException("Can not attach to ListView multiple times");
|
||||||
|
}
|
||||||
|
layoutAdded = true;
|
||||||
((ViewGroup) listView.getParent()).addView(emptyView);
|
((ViewGroup) listView.getParent()).addView(emptyView);
|
||||||
listView.setEmptyView(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() {
|
public void attachToRecyclerView(RecyclerView recyclerView) {
|
||||||
return activity;
|
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) {
|
public void updateAdapter(RecyclerView.Adapter adapter) {
|
||||||
this.activity = activity;
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,10 +17,6 @@
|
||||||
tools:itemCount="13"
|
tools:itemCount="13"
|
||||||
tools:listitem="@layout/new_episodes_listitem" />
|
tools:listitem="@layout/new_episodes_listitem" />
|
||||||
|
|
||||||
<include
|
|
||||||
android:id="@+id/emptyView"
|
|
||||||
layout="@layout/empty_view_layout"/>
|
|
||||||
|
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
android:id="@+id/progLoading"
|
android:id="@+id/progLoading"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
|
android:layout_centerInParent="true"
|
||||||
xmlns:tools="http://schemas.android.com/tools">
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
|
|
@ -27,10 +27,6 @@
|
||||||
android:layout_below="@id/divider"
|
android:layout_below="@id/divider"
|
||||||
android:scrollbars="vertical"/>
|
android:scrollbars="vertical"/>
|
||||||
|
|
||||||
<include
|
|
||||||
android:id="@+id/emptyView"
|
|
||||||
layout="@layout/empty_view_layout"/>
|
|
||||||
|
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
android:id="@+id/progLoading"
|
android:id="@+id/progLoading"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|
Loading…
Reference in New Issue