summaryrefslogtreecommitdiff
path: root/app/src/main/java/de/danoeh/antennapod
diff options
context:
space:
mode:
authorTom Hennen <TomHennen@users.noreply.github.com>2015-11-05 06:52:24 -0500
committerTom Hennen <TomHennen@users.noreply.github.com>2015-11-05 06:52:24 -0500
commit3b003c60abb7ccf461ea5f4eae35e69cdda2ecd2 (patch)
treebea911f0dab76ae175b879bb324315b9f172ab70 /app/src/main/java/de/danoeh/antennapod
parent58d1ba69f00df2519102d5c4a7f0f9f258ff3f33 (diff)
parente03ef16558a3d604860f7f14a895c1b7f022f425 (diff)
downloadAntennaPod-3b003c60abb7ccf461ea5f4eae35e69cdda2ecd2.zip
Merge pull request #1336 from TomHennen/recycler_view
Recycler view for Episodes Fragment
Diffstat (limited to 'app/src/main/java/de/danoeh/antennapod')
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java73
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesRecycleAdapter.java (renamed from app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesListAdapter.java)196
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java198
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java77
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java6
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java92
-rw-r--r--app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java4
-rw-r--r--app/src/main/java/de/danoeh/antennapod/view/DividerItemDecoration.java124
8 files changed, 399 insertions, 371 deletions
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java
index e92599561..a92eefc00 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java
@@ -153,7 +153,6 @@ public class MainActivity extends ActionBarActivity implements NavDrawerActivity
navList.setAdapter(navAdapter);
navList.setOnItemClickListener(navListClickListener);
navList.setOnItemLongClickListener(newListLongClickListener);
- registerForContextMenu(navList);
navAdapter.registerDataSetObserver(new DataSetObserver() {
@Override
@@ -522,78 +521,6 @@ public class MainActivity extends ActionBarActivity implements NavDrawerActivity
}
}
- @Override
- public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
- super.onCreateContextMenu(menu, v, menuInfo);
- if(v.getId() != R.id.nav_list) {
- return;
- }
- AdapterView.AdapterContextMenuInfo adapterInfo = (AdapterView.AdapterContextMenuInfo) menuInfo;
- int position = adapterInfo.position;
- if(position < navAdapter.getSubscriptionOffset()) {
- return;
- }
- MenuInflater inflater = getMenuInflater();
- inflater.inflate(R.menu.nav_feed_context, menu);
- Feed feed = navDrawerData.feeds.get(position - navAdapter.getSubscriptionOffset());
- menu.setHeaderTitle(feed.getTitle());
- // episodes are not loaded, so we cannot check if the podcast has new or unplayed ones!
-
- // we may need to reference this elsewhere...
- lastMenuInfo = (AdapterView.AdapterContextMenuInfo) menuInfo;
- }
-
- @Override
- public boolean onContextItemSelected(MenuItem item) {
- AdapterView.AdapterContextMenuInfo menuInfo = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
-
- if(menuInfo == null) {
- menuInfo = lastMenuInfo;
- }
-
- if(menuInfo == null
- || menuInfo.targetView == null
- || menuInfo.targetView.getParent() == null
- || menuInfo.targetView.getParent() instanceof ListView == false
- || ((ListView)menuInfo.targetView.getParent()).getId() != R.id.nav_list) {
- return false;
- }
- final int position = menuInfo.position;
- Feed feed = navDrawerData.feeds.get(position - navAdapter.getSubscriptionOffset());
- switch(item.getItemId()) {
- case R.id.mark_all_seen_item:
- DBWriter.markFeedSeen(feed.getId());
- return true;
- case R.id.mark_all_read_item:
- DBWriter.markFeedRead(feed.getId());
- return true;
- case R.id.remove_item:
- final FeedRemover remover = new FeedRemover(this, feed) {
- @Override
- protected void onPostExecute(Void result) {
- super.onPostExecute(result);
- if(getSelectedNavListIndex() == position) {
- loadFragment(EpisodesFragment.TAG, null);
- }
- }
- };
- ConfirmationDialog conDialog = new ConfirmationDialog(this,
- R.string.remove_feed_label,
- R.string.feed_delete_confirmation_msg) {
- @Override
- public void onConfirmButtonPressed(
- DialogInterface dialog) {
- dialog.dismiss();
- remover.executeAsync();
- }
- };
- conDialog.createNewDialog().show();
- return true;
- default:
- return super.onContextItemSelected(item);
- }
- }
-
private DBReader.NavDrawerData navDrawerData;
private AsyncTask<Void, Void, DBReader.NavDrawerData> loadTask;
private int selectedNavListIndex = 0;
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesListAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesRecycleAdapter.java
index b1b85da9f..c72c95feb 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesListAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesRecycleAdapter.java
@@ -3,12 +3,15 @@ package de.danoeh.antennapod.adapter;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.net.Uri;
+import android.support.v7.widget.PopupMenu;
+import android.support.v7.widget.RecyclerView;
import android.text.format.DateUtils;
import android.util.Log;
import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.BaseAdapter;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ProgressBar;
@@ -23,29 +26,38 @@ import com.joanzapata.iconify.Iconify;
import java.lang.ref.WeakReference;
import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.glide.ApGlideSettings;
+import de.danoeh.antennapod.core.storage.DownloadRequestException;
import de.danoeh.antennapod.core.storage.DownloadRequester;
import de.danoeh.antennapod.core.util.Converter;
import de.danoeh.antennapod.core.util.NetworkUtils;
+import de.danoeh.antennapod.fragment.ItemFragment;
+import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
/**
* List adapter for the list of new episodes
*/
-public class AllEpisodesListAdapter extends BaseAdapter {
+public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesRecycleAdapter.Holder> {
- private static final String TAG = AllEpisodesListAdapter.class.getSimpleName();
+ private static final String TAG = AllEpisodesRecycleAdapter.class.getSimpleName();
private final Context context;
private final ItemAccess itemAccess;
private final ActionButtonCallback actionButtonCallback;
private final ActionButtonUtils actionButtonUtils;
private final boolean showOnlyNewEpisodes;
+ private final WeakReference<MainActivity> mainActivityRef;
- public AllEpisodesListAdapter(Context context, ItemAccess itemAccess, ActionButtonCallback actionButtonCallback,
- boolean showOnlyNewEpisodes) {
+ public AllEpisodesRecycleAdapter(Context context,
+ MainActivity mainActivity,
+ ItemAccess itemAccess,
+ ActionButtonCallback actionButtonCallback,
+ boolean showOnlyNewEpisodes) {
super();
+ this.mainActivityRef = new WeakReference<>(mainActivity);
this.context = context;
this.itemAccess = itemAccess;
this.actionButtonUtils = new ActionButtonUtils(context);
@@ -54,55 +66,38 @@ public class AllEpisodesListAdapter extends BaseAdapter {
}
@Override
- public int getCount() {
- return itemAccess.getCount();
- }
-
- @Override
- public Object getItem(int position) {
- return itemAccess.getItem(position);
- }
-
- @Override
- public long getItemId(int position) {
- return position;
+ public Holder onCreateViewHolder(ViewGroup parent, int viewType) {
+ View view = LayoutInflater.from(parent.getContext())
+ .inflate(R.layout.new_episodes_listitem, parent, false);
+ Holder holder = new Holder(view);
+ holder.placeholder = (TextView) view.findViewById(R.id.txtvPlaceholder);
+ holder.title = (TextView) view.findViewById(R.id.txtvTitle);
+ holder.pubDate = (TextView) view
+ .findViewById(R.id.txtvPublished);
+ holder.statusUnread = view.findViewById(R.id.statusUnread);
+ holder.butSecondary = (ImageButton) view
+ .findViewById(R.id.butSecondaryAction);
+ holder.queueStatus = (ImageView) view
+ .findViewById(R.id.imgvInPlaylist);
+ holder.progress = (ProgressBar) view
+ .findViewById(R.id.pbar_progress);
+ holder.cover = (ImageView) view.findViewById(R.id.imgvCover);
+ holder.txtvDuration = (TextView) view.findViewById(R.id.txtvDuration);
+ holder.item = null;
+ holder.mainActivityRef = mainActivityRef;
+ holder.position = -1;
+ // so we can grab this later
+ view.setTag(holder);
+
+ return holder;
}
@Override
- public int getViewTypeCount() {
- return 1;
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- Holder holder;
- final FeedItem item = (FeedItem) getItem(position);
- if (item == null) return null;
-
- if (convertView == null) {
- holder = new Holder();
- LayoutInflater inflater = (LayoutInflater) context
- .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- convertView = inflater.inflate(R.layout.new_episodes_listitem,
- parent, false);
- holder.placeholder = (TextView) convertView.findViewById(R.id.txtvPlaceholder);
- holder.title = (TextView) convertView.findViewById(R.id.txtvTitle);
- holder.pubDate = (TextView) convertView
- .findViewById(R.id.txtvPublished);
- holder.statusUnread = convertView.findViewById(R.id.statusUnread);
- holder.butSecondary = (ImageButton) convertView
- .findViewById(R.id.butSecondaryAction);
- holder.queueStatus = (ImageView) convertView
- .findViewById(R.id.imgvInPlaylist);
- holder.progress = (ProgressBar) convertView
- .findViewById(R.id.pbar_progress);
- holder.cover = (ImageView) convertView.findViewById(R.id.imgvCover);
- holder.txtvDuration = (TextView) convertView.findViewById(R.id.txtvDuration);
- convertView.setTag(holder);
- } else {
- holder = (Holder) convertView.getTag();
- }
-
+ public void onBindViewHolder(final Holder holder, int position) {
+ final FeedItem item = itemAccess.getItem(position);
+ if (item == null) return;
+ holder.item = item;
+ holder.position = position;
holder.placeholder.setVisibility(View.VISIBLE);
holder.placeholder.setText(item.getFeed().getTitle());
holder.title.setText(item.getTitle());
@@ -146,7 +141,7 @@ public class AllEpisodesListAdapter extends BaseAdapter {
// item is being downloaded
holder.progress.setProgress(itemAccess.getItemDownloadProgressPercent(item));
} else if (state == FeedItem.State.PLAYING
- || state == FeedItem.State.IN_PROGRESS) {
+ || state == FeedItem.State.IN_PROGRESS) {
if (media.getDuration() > 0) {
int progress = (int) (100.0 * media.getPosition() / media.getDuration());
holder.progress.setProgress(progress);
@@ -178,8 +173,20 @@ public class AllEpisodesListAdapter extends BaseAdapter {
.fitCenter()
.dontAnimate()
.into(new CoverTarget(item.getFeed().getImageUri(), holder.placeholder, holder.cover));
+ }
- return convertView;
+ @Override
+ public long getItemId(int position) {
+ return position;
+ }
+
+ @Override
+ public int getItemCount() {
+ return itemAccess.getCount();
+ }
+
+ public FeedItem getItem(int position) {
+ return itemAccess.getItem(position);
}
private class CoverTarget extends GlideDrawableImageViewTarget {
@@ -228,8 +235,63 @@ public class AllEpisodesListAdapter extends BaseAdapter {
}
};
+ private Menu popupMenu;
+ private final FeedItemMenuHandler.MenuInterface contextMenuInterface = new FeedItemMenuHandler.MenuInterface() {
+ @Override
+ public void setItemVisibility(int id, boolean visible) {
+ if(popupMenu == null) {
+ return;
+ }
+ MenuItem item = popupMenu.findItem(id);
+ if (item != null) {
+ item.setVisible(visible);
+ }
+ }
+ };
+
+ private final boolean showContextMenu(View view) {
+ // Create a PopupMenu, giving it the clicked view for an anchor
+ MainActivity mainActivity = this.mainActivityRef.get();
+ if (mainActivity == null) {
+ Log.d(TAG, "mainActivity is null");
+ return false;
+ }
+ PopupMenu popup = new PopupMenu(mainActivity, view);
+ Menu menu = popup.getMenu();
- static class Holder {
+ // Inflate our menu resource into the PopupMenu's Menu
+ popup.getMenuInflater().inflate(R.menu.allepisodes_context, popup.getMenu());
+
+ Holder holder = (Holder) view.getTag();
+ FeedItem item = holder.item;
+ if (item == null) {
+ return false;
+ }
+
+ popupMenu = menu;
+ FeedItemMenuHandler.onPrepareMenu(context, contextMenuInterface, item, true, null);
+
+ // Set a listener so we are notified if a menu item is clicked
+ popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
+ @Override
+ public boolean onMenuItemClick(MenuItem menuItem) {
+ try {
+ FeedItemMenuHandler.onMenuItemClicked(context, menuItem.getItemId(), item);
+ return true;
+ } catch (DownloadRequestException e) {
+ e.printStackTrace();
+ }
+ return false;
+ }
+ });
+
+ popup.show();
+ return true;
+ }
+
+
+ public class Holder extends RecyclerView.ViewHolder
+ implements View.OnClickListener, View.OnLongClickListener{
TextView placeholder;
TextView title;
TextView pubDate;
@@ -239,6 +301,32 @@ public class AllEpisodesListAdapter extends BaseAdapter {
ProgressBar progress;
TextView txtvDuration;
ImageButton butSecondary;
+ FeedItem item;
+ WeakReference<MainActivity> mainActivityRef;
+ int position;
+
+ public Holder(View itemView) {
+ super(itemView);
+ itemView.setOnClickListener(this);
+ itemView.setOnLongClickListener(this);
+ }
+
+ @Override
+ public void onClick(View v) {
+ MainActivity mainActivity = mainActivityRef.get();
+ if (mainActivity != null) {
+ mainActivity.loadChildFragment(ItemFragment.newInstance(item.getId()));
+ }
+ }
+
+ public FeedItem getFeedItem() { return item; }
+
+ public int getItemPosition() { return position; }
+
+ @Override
+ public boolean onLongClick(View view) {
+ return showContextMenu(view);
+ }
}
public interface ItemAccess {
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java
index 31b24773f..c3249771f 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java
@@ -7,30 +7,26 @@ import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.Fragment;
-import android.support.v4.util.Pair;
import android.support.v4.view.MenuItemCompat;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.SearchView;
import android.util.Log;
-import android.view.ContextMenu;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.AdapterView;
import android.widget.ProgressBar;
-import android.widget.TextView;
import android.widget.Toast;
-import com.mobeta.android.dslv.DragSortListView;
-
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
-import de.danoeh.antennapod.adapter.AllEpisodesListAdapter;
+import de.danoeh.antennapod.adapter.AllEpisodesRecycleAdapter;
import de.danoeh.antennapod.adapter.DefaultActionButtonCallback;
import de.danoeh.antennapod.core.asynctask.DownloadObserver;
import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
@@ -43,11 +39,9 @@ import de.danoeh.antennapod.core.service.download.Downloader;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBTasks;
import de.danoeh.antennapod.core.storage.DBWriter;
-import de.danoeh.antennapod.core.storage.DownloadRequestException;
import de.danoeh.antennapod.core.storage.DownloadRequester;
-import de.danoeh.antennapod.core.util.LongList;
-import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
import de.danoeh.antennapod.menuhandler.MenuItemUtils;
+import de.danoeh.antennapod.view.DividerItemDecoration;
import rx.Observable;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
@@ -68,24 +62,18 @@ public class AllEpisodesFragment extends Fragment {
private static final int RECENT_EPISODES_LIMIT = 150;
private static final String DEFAULT_PREF_NAME = "PrefAllEpisodesFragment";
- private static final String PREF_KEY_LIST_TOP = "list_top";
- private static final String PREF_KEY_LIST_SELECTION = "list_selection";
+ private static final String PREF_SCROLL_POSITION = "scroll_position";
+ private static final String PREF_SCROLL_OFFSET = "scroll_offset";
- private String prefName;
- protected DragSortListView listView;
- private AllEpisodesListAdapter listAdapter;
- private TextView txtvEmpty;
+ protected RecyclerView recyclerView;
+ private AllEpisodesRecycleAdapter listAdapter;
private ProgressBar progLoading;
- private ContextMenu contextMenu;
- private AdapterView.AdapterContextMenuInfo lastMenuInfo = null;
private List<FeedItem> episodes;
- private LongList queuedItemsIds;
private List<Downloader> downloaderList;
private boolean itemsLoaded = false;
private boolean viewsCreated = false;
- private final boolean showOnlyNewEpisodes;
private AtomicReference<MainActivity> activity = new AtomicReference<MainActivity>();
@@ -94,20 +82,10 @@ public class AllEpisodesFragment extends Fragment {
private boolean isUpdatingFeeds;
protected Subscription subscription;
+ private LinearLayoutManager layoutManager;
- public AllEpisodesFragment() {
- // by default we show all the episodes
- this(false, DEFAULT_PREF_NAME);
- }
-
- // this is only going to be called by our sub-class.
- // The Android docs say to avoid non-default constructors
- // but I think this will be OK since it will only be invoked
- // from a fragment via a default constructor
- protected AllEpisodesFragment(boolean showOnlyNewEpisodes, String prefName) {
- this.showOnlyNewEpisodes = showOnlyNewEpisodes;
- this.prefName = prefName;
- }
+ protected boolean showOnlyNewEpisodes() { return false; }
+ protected String getPrefName() { return DEFAULT_PREF_NAME; }
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -163,25 +141,32 @@ public class AllEpisodesFragment extends Fragment {
}
private void saveScrollPosition() {
- SharedPreferences prefs = getActivity().getSharedPreferences(prefName, Context.MODE_PRIVATE);
+ int firstItem = layoutManager.findFirstVisibleItemPosition();
+ View firstItemView = layoutManager.findViewByPosition(firstItem);
+ float topOffset;
+ if(firstItemView == null) {
+ topOffset = 0;
+ } else {
+ topOffset = firstItemView.getTop();
+ }
+
+ SharedPreferences prefs = getActivity().getSharedPreferences(getPrefName(), Context.MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
- View v = listView.getChildAt(0);
- int top = (v == null) ? 0 : (v.getTop() - listView.getPaddingTop());
- editor.putInt(PREF_KEY_LIST_SELECTION, listView.getFirstVisiblePosition());
- editor.putInt(PREF_KEY_LIST_TOP, top);
+ editor.putInt(PREF_SCROLL_POSITION, firstItem);
+ editor.putFloat(PREF_SCROLL_OFFSET, topOffset);
editor.commit();
}
private void restoreScrollPosition() {
- SharedPreferences prefs = getActivity().getSharedPreferences(prefName, Context.MODE_PRIVATE);
- int listSelection = prefs.getInt(PREF_KEY_LIST_SELECTION, 0);
- int top = prefs.getInt(PREF_KEY_LIST_TOP, 0);
- if (listSelection > 0 || top > 0) {
- listView.setSelectionFromTop(listSelection, top);
+ SharedPreferences prefs = getActivity().getSharedPreferences(getPrefName(), Context.MODE_PRIVATE);
+ int position = prefs.getInt(PREF_SCROLL_POSITION, 0);
+ float offset = prefs.getFloat(PREF_SCROLL_OFFSET, 0.0f);
+ if (position > 0 || offset > 0) {
+ layoutManager.scrollToPositionWithOffset(position, (int) offset);
// restore once, then forget
SharedPreferences.Editor editor = prefs.edit();
- editor.putInt(PREF_KEY_LIST_SELECTION, 0);
- editor.putInt(PREF_KEY_LIST_TOP, 0);
+ editor.putInt(PREF_SCROLL_POSITION, 0);
+ editor.putFloat(PREF_SCROLL_OFFSET, 0.0f);
editor.commit();
}
}
@@ -289,26 +274,17 @@ public class AllEpisodesFragment extends Fragment {
View root = inflater.inflate(fragmentResource, container, false);
- listView = (DragSortListView) root.findViewById(android.R.id.list);
- txtvEmpty = (TextView) root.findViewById(android.R.id.empty);
- progLoading = (ProgressBar) root.findViewById(R.id.progLoading);
-
- listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- FeedItem item = (FeedItem) listAdapter.getItem(position - listView.getHeaderViewsCount());
- if (item != null) {
- ((MainActivity) getActivity()).loadChildFragment(ItemFragment.newInstance(item.getId()));
- }
-
- }
- });
+ recyclerView = (RecyclerView) root.findViewById(android.R.id.list);
+ layoutManager = new LinearLayoutManager(getActivity());
+ recyclerView.setLayoutManager(layoutManager);
+ recyclerView.setHasFixedSize(true);
+ RecyclerView.ItemDecoration itemDecoration = new DividerItemDecoration(getActivity(), null);
+ recyclerView.addItemDecoration(itemDecoration);
- registerForContextMenu(listView);
+ progLoading = (ProgressBar) root.findViewById(R.id.progLoading);
if (!itemsLoaded) {
progLoading.setVisibility(View.VISIBLE);
- txtvEmpty.setVisibility(View.GONE);
}
viewsCreated = true;
@@ -320,80 +296,11 @@ public class AllEpisodesFragment extends Fragment {
return root;
}
- private final FeedItemMenuHandler.MenuInterface contextMenuInterface = new FeedItemMenuHandler.MenuInterface() {
- @Override
- public void setItemVisibility(int id, boolean visible) {
- if(contextMenu == null) {
- return;
- }
- MenuItem item = contextMenu.findItem(id);
- if (item != null) {
- item.setVisible(visible);
- }
- }
- };
-
- @Override
- public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
- super.onCreateContextMenu(menu, v, menuInfo);
- AdapterView.AdapterContextMenuInfo adapterInfo = (AdapterView.AdapterContextMenuInfo) menuInfo;
- FeedItem item = itemAccess.getItem(adapterInfo.position);
- MenuInflater inflater = getActivity().getMenuInflater();
- inflater.inflate(R.menu.allepisodes_context, menu);
-
- if (item != null) {
- menu.setHeaderTitle(item.getTitle());
- }
-
- contextMenu = menu;
- lastMenuInfo = (AdapterView.AdapterContextMenuInfo) menuInfo;
- FeedItemMenuHandler.onPrepareMenu(getActivity(), contextMenuInterface, item, true, queuedItemsIds);
- }
-
- @Override
- public boolean onContextItemSelected(MenuItem item) {
- if (!getUserVisibleHint()) {
- // we're not visible, don't do anything.
- return false;
- }
- AdapterView.AdapterContextMenuInfo menuInfo = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
- if (menuInfo == null) {
- menuInfo = lastMenuInfo;
- }
- if (menuInfo == null) {
- Log.e(TAG, "menuInfo is null, not doing anything");
- return false;
- }
-
- FeedItem selectedItem = null;
-
- // make sure the item still makes sense
- if (menuInfo.position >= 0 && menuInfo.position < itemAccess.getCount()) {
- selectedItem = itemAccess.getItem(menuInfo.position);
- } else {
- Log.d(TAG, "Selected item at position " + menuInfo.position + " does not exist, only " + itemAccess.getCount() + " items available");
- }
-
- if (selectedItem == null) {
- Log.i(TAG, "Selected item at position " + menuInfo.position + " was null, ignoring selection");
- return super.onContextItemSelected(item);
- }
-
- try {
- return FeedItemMenuHandler.onMenuItemClicked(getActivity(), item.getItemId(), selectedItem);
- } catch (DownloadRequestException e) {
- e.printStackTrace();
- Toast.makeText(getActivity(), e.getMessage(), Toast.LENGTH_LONG).show();
- return true;
- }
- }
-
private void onFragmentLoaded() {
if (listAdapter == null) {
- listAdapter = new AllEpisodesListAdapter(activity.get(), itemAccess,
- new DefaultActionButtonCallback(activity.get()), showOnlyNewEpisodes);
- listView.setAdapter(listAdapter);
- listView.setEmptyView(txtvEmpty);
+ listAdapter = new AllEpisodesRecycleAdapter(activity.get(), activity.get(), itemAccess,
+ new DefaultActionButtonCallback(activity.get()), showOnlyNewEpisodes());
+ recyclerView.setAdapter(listAdapter);
downloadObserver = new DownloadObserver(activity.get(), new Handler(), downloadObserverCallback);
downloadObserver.onResume();
}
@@ -413,7 +320,7 @@ public class AllEpisodesFragment extends Fragment {
}
};
- private AllEpisodesListAdapter.ItemAccess itemAccess = new AllEpisodesListAdapter.ItemAccess() {
+ protected AllEpisodesRecycleAdapter.ItemAccess itemAccess = new AllEpisodesRecycleAdapter.ItemAccess() {
@Override
public int getCount() {
@@ -446,11 +353,10 @@ public class AllEpisodesFragment extends Fragment {
@Override
public boolean isInQueue(FeedItem item) {
- if (itemsLoaded) {
- return queuedItemsIds.contains(item.getId());
- } else {
- return false;
+ if (item != null) {
+ return item.isTagged(FeedItem.TAG_QUEUE);
}
+ return false;
}
};
@@ -467,7 +373,6 @@ public class AllEpisodesFragment extends Fragment {
};
private void updateShowOnlyEpisodesListViewState() {
- listView.setEmptyView(txtvEmpty);
}
protected void loadItems() {
@@ -475,19 +380,17 @@ public class AllEpisodesFragment extends Fragment {
subscription.unsubscribe();
}
if (viewsCreated && !itemsLoaded) {
- listView.setVisibility(View.GONE);
- txtvEmpty.setVisibility(View.GONE);
+ recyclerView.setVisibility(View.GONE);
progLoading.setVisibility(View.VISIBLE);
}
subscription = Observable.defer(() -> Observable.just(loadData()))
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(data -> {
- listView.setVisibility(View.VISIBLE);
+ recyclerView.setVisibility(View.VISIBLE);
progLoading.setVisibility(View.GONE);
if (data != null) {
- episodes = data.first;
- queuedItemsIds = data.second;
+ episodes = data;
itemsLoaded = true;
if (viewsCreated && activity.get() != null) {
onFragmentLoaded();
@@ -498,11 +401,8 @@ public class AllEpisodesFragment extends Fragment {
});
}
- protected Pair<List<FeedItem>,LongList> loadData() {
- List<FeedItem> items;
- items = DBReader.getRecentlyPublishedEpisodes(RECENT_EPISODES_LIMIT);
- LongList queuedIds = DBReader.getQueueIDList();
- return Pair.create(items, queuedIds);
+ protected List<FeedItem> loadData() {
+ return DBReader.getRecentlyPublishedEpisodes(RECENT_EPISODES_LIMIT);
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java
index 95f7cfcc1..532516dda 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java
@@ -1,8 +1,9 @@
package de.danoeh.antennapod.fragment;
-import android.content.Context;
import android.os.Bundle;
-import android.support.v4.util.Pair;
+import android.support.design.widget.Snackbar;
+import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.helper.ItemTouchHelper;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
@@ -11,13 +12,11 @@ import android.view.ViewGroup;
import java.util.List;
import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.adapter.AllEpisodesRecycleAdapter;
import de.danoeh.antennapod.core.event.FavoritesEvent;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBWriter;
-import de.danoeh.antennapod.core.util.LongList;
-import de.danoeh.antennapod.core.util.gui.FeedItemUndoToken;
-import de.danoeh.antennapod.core.util.gui.UndoBarController;
import de.greenrobot.event.EventBus;
@@ -32,11 +31,11 @@ public class FavoriteEpisodesFragment extends AllEpisodesFragment {
private static final String PREF_NAME = "PrefFavoriteEpisodesFragment";
- private UndoBarController undoBarController;
+ @Override
+ protected boolean showOnlyNewEpisodes() { return true; }
- public FavoriteEpisodesFragment() {
- super(false, PREF_NAME);
- }
+ @Override
+ protected String getPrefName() { return PREF_NAME; }
public void onEvent(FavoritesEvent event) {
Log.d(TAG, "onEvent(" + event + ")");
@@ -58,54 +57,48 @@ public class FavoriteEpisodesFragment extends AllEpisodesFragment {
@Override
protected void resetViewState() {
super.resetViewState();
- undoBarController = null;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View root = super.onCreateViewHelper(inflater, container, savedInstanceState,
- R.layout.episodes_fragment_with_undo);
+ R.layout.all_episodes_fragment);
- listView.setRemoveListener(which -> {
- Log.d(TAG, "remove(" + which + ")");
- if (subscription != null) {
- subscription.unsubscribe();
+ ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
+ @Override
+ public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
+ return false;
}
- FeedItem item = (FeedItem) listView.getAdapter().getItem(which);
-
- DBWriter.removeFavoriteItem(item);
-
- undoBarController.showUndoBar(false,
- getString(R.string.removed_item), new FeedItemUndoToken(item,
- which)
- );
- });
-
- undoBarController = new UndoBarController<FeedItemUndoToken>(root.findViewById(R.id.undobar), new UndoBarController.UndoListener<FeedItemUndoToken>() {
-
- private final Context context = getActivity();
@Override
- public void onUndo(FeedItemUndoToken token) {
- if (token != null) {
- long itemId = token.getFeedItemId();
- DBWriter.addFavoriteItemById(itemId);
+ public void onSwiped(RecyclerView.ViewHolder viewHolder, int swipeDir) {
+ AllEpisodesRecycleAdapter.Holder holder = (AllEpisodesRecycleAdapter.Holder)viewHolder;
+ Log.d(TAG, "remove(" + holder.getItemId() + ")");
+
+ if (subscription != null) {
+ subscription.unsubscribe();
+ }
+ FeedItem item = holder.getFeedItem();
+ if (item != null) {
+ DBWriter.removeFavoriteItem(item);
+
+ Snackbar snackbar = Snackbar.make(root, getString(R.string.removed_item),
+ Snackbar.LENGTH_LONG);
+ snackbar.setAction(getString(R.string.undo), v -> {
+ DBWriter.addFavoriteItem(item);
+ });
+ snackbar.show();
}
}
+ };
- @Override
- public void onHide(FeedItemUndoToken token) {
- // nothing to do
- }
- });
+ ItemTouchHelper itemTouchHelper = new ItemTouchHelper(simpleItemTouchCallback);
+ itemTouchHelper.attachToRecyclerView(recyclerView);
return root;
}
@Override
- protected Pair<List<FeedItem>,LongList> loadData() {
- List<FeedItem> items;
- items = DBReader.getFavoriteItemsList();
- LongList queuedIds = DBReader.getQueueIDList();
- return Pair.create(items, queuedIds);
+ protected List<FeedItem> loadData() {
+ return DBReader.getFavoriteItemsList();
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java
index d17788dde..8505cf143 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java
@@ -463,7 +463,7 @@ public class ItemlistFragment extends ListFragment {
private void refreshHeaderView() {
if (getListView() == null || feed == null) {
- Log.e(TAG, "Unable to setup listview: listView = null or feed = null");
+ Log.e(TAG, "Unable to setup listview: recyclerView = null or feed = null");
return;
}
if(feed.hasLastUpdateFailed()) {
@@ -503,7 +503,7 @@ public class ItemlistFragment extends ListFragment {
private void setupHeaderView() {
if (getListView() == null || feed == null) {
- Log.e(TAG, "Unable to setup listview: listView = null or feed = null");
+ Log.e(TAG, "Unable to setup listview: recyclerView = null or feed = null");
return;
}
ListView lv = getListView();
@@ -561,7 +561,7 @@ public class ItemlistFragment extends ListFragment {
private void setupFooterView() {
if (getListView() == null || feed == null) {
- Log.e(TAG, "Unable to setup listview: listView = null or feed = null");
+ Log.e(TAG, "Unable to setup listview: recyclerView = null or feed = null");
return;
}
if (feed.isPaged() && feed.getNextPageLink() != null) {
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java
index 60d0161b2..bbe9b20f3 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java
@@ -1,26 +1,25 @@
package de.danoeh.antennapod.fragment;
-import android.content.Context;
import android.os.Bundle;
-import android.support.v4.util.Pair;
+import android.os.Handler;
+import android.support.design.widget.Snackbar;
+import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.helper.ItemTouchHelper;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import com.mobeta.android.dslv.DragSortListView;
-
import java.util.List;
import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.adapter.AllEpisodesRecycleAdapter;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.event.QueueEvent;
+import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBWriter;
-import de.danoeh.antennapod.core.util.LongList;
-import de.danoeh.antennapod.core.util.gui.FeedItemUndoToken;
-import de.danoeh.antennapod.core.util.gui.UndoBarController;
import de.greenrobot.event.EventBus;
@@ -35,11 +34,11 @@ public class NewEpisodesFragment extends AllEpisodesFragment {
private static final String PREF_NAME = "PrefNewEpisodesFragment";
- private UndoBarController undoBarController;
+ @Override
+ protected boolean showOnlyNewEpisodes() { return true; }
- public NewEpisodesFragment() {
- super(true, PREF_NAME);
- }
+ @Override
+ protected String getPrefName() { return PREF_NAME; }
public void onEvent(QueueEvent event) {
Log.d(TAG, "onEvent(" + event + ")");
@@ -61,64 +60,61 @@ public class NewEpisodesFragment extends AllEpisodesFragment {
@Override
protected void resetViewState() {
super.resetViewState();
- undoBarController = null;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View root = super.onCreateViewHelper(inflater, container, savedInstanceState,
- R.layout.episodes_fragment_with_undo);
+ R.layout.all_episodes_fragment);
- listView.setRemoveListener(new DragSortListView.RemoveListener() {
+ ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
@Override
- public void remove(int which) {
- Log.d(TAG, "remove(" + which + ")");
+ public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
+ return false;
+ }
+
+ @Override
+ public void onSwiped(RecyclerView.ViewHolder viewHolder, int swipeDir) {
+ AllEpisodesRecycleAdapter.Holder holder = (AllEpisodesRecycleAdapter.Holder)viewHolder;
+
+ Log.d(TAG, "remove(" + holder.getItemId() + ")");
if (subscription != null) {
subscription.unsubscribe();
}
- FeedItem item = (FeedItem) listView.getAdapter().getItem(which);
+ FeedItem item = holder.getFeedItem();
// we're marking it as unplayed since the user didn't actually play it
// but they don't want it considered 'NEW' anymore
DBWriter.markItemPlayed(FeedItem.UNPLAYED, item.getId());
- undoBarController.showUndoBar(false,
- getString(R.string.marked_as_read_label), new FeedItemUndoToken(item,
- which)
- );
- }
- });
- undoBarController = new UndoBarController<FeedItemUndoToken>(root.findViewById(R.id.undobar), new UndoBarController.UndoListener<FeedItemUndoToken>() {
-
- private final Context context = getActivity();
-
- @Override
- public void onUndo(FeedItemUndoToken token) {
- if (token != null) {
- long itemId = token.getFeedItemId();
- DBWriter.markItemPlayed(FeedItem.NEW, itemId);
- }
- }
- @Override
- public void onHide(FeedItemUndoToken token) {
- if (token != null && context != null) {
- long itemId = token.getFeedItemId();
- FeedItem item = DBReader.getFeedItem(itemId);
+ final Handler h = new Handler(getActivity().getMainLooper());
+ final Runnable r = () -> {
FeedMedia media = item.getMedia();
- if(media != null && media.hasAlmostEnded() && item.getFeed().getPreferences().getCurrentAutoDelete()) {
- DBWriter.deleteFeedMediaOfItem(context, media.getId());
+ if (media != null && media.hasAlmostEnded() && UserPreferences.isAutoDelete()) {
+ DBWriter.deleteFeedMediaOfItem(getActivity(), media.getId());
}
- }
+ };
+
+ Snackbar snackbar = Snackbar.make(root, getString(R.string.marked_as_read_label),
+ Snackbar.LENGTH_LONG);
+ snackbar.setAction(getString(R.string.undo), v -> {
+ DBWriter.markItemPlayed(FeedItem.NEW, item.getId());
+ // don't forget to cancel the thing that's going to remove the media
+ h.removeCallbacks(r);
+ });
+ snackbar.show();
+ h.postDelayed(r, (int)Math.ceil(snackbar.getDuration() * 1.05f));
}
- });
+ };
+
+ ItemTouchHelper itemTouchHelper = new ItemTouchHelper(simpleItemTouchCallback);
+ itemTouchHelper.attachToRecyclerView(recyclerView);
+
return root;
}
@Override
- protected Pair<List<FeedItem>,LongList> loadData() {
- List<FeedItem> items;
- items = DBReader.getNewItemsList();
- LongList queuedIds = DBReader.getQueueIDList();
- return Pair.create(items, queuedIds);
+ protected List<FeedItem> loadData() {
+ return DBReader.getNewItemsList();
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java b/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java
index b24779934..3fa1048c0 100644
--- a/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java
+++ b/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java
@@ -73,10 +73,10 @@ public class FeedItemMenuHandler {
}
boolean isInQueue = selectedItem.isTagged(FeedItem.TAG_QUEUE);
- if(queueAccess.size() == 0 || queueAccess.get(0) == selectedItem.getId()) {
+ if(queueAccess == null || queueAccess.size() == 0 || queueAccess.get(0) == selectedItem.getId()) {
mi.setItemVisibility(R.id.move_to_top_item, false);
}
- if(queueAccess.size() == 0 || queueAccess.get(queueAccess.size()-1) == selectedItem.getId()) {
+ if(queueAccess == null || queueAccess.size() == 0 || queueAccess.get(queueAccess.size()-1) == selectedItem.getId()) {
mi.setItemVisibility(R.id.move_to_bottom_item, false);
}
if (!isInQueue || isPlaying) {
diff --git a/app/src/main/java/de/danoeh/antennapod/view/DividerItemDecoration.java b/app/src/main/java/de/danoeh/antennapod/view/DividerItemDecoration.java
new file mode 100644
index 000000000..c32f7e702
--- /dev/null
+++ b/app/src/main/java/de/danoeh/antennapod/view/DividerItemDecoration.java
@@ -0,0 +1,124 @@
+package de.danoeh.antennapod.view;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.util.AttributeSet;
+import android.view.View;
+
+public class DividerItemDecoration extends RecyclerView.ItemDecoration {
+
+ private Drawable mDivider;
+ private boolean mShowFirstDivider = false;
+ private boolean mShowLastDivider = false;
+
+
+ public DividerItemDecoration(Context context, AttributeSet attrs) {
+ final TypedArray a = context.obtainStyledAttributes(attrs, new int[] { android.R.attr.listDivider });
+ mDivider = a.getDrawable(0);
+ a.recycle();
+ }
+
+ public DividerItemDecoration(Context context, AttributeSet attrs, boolean showFirstDivider,
+ boolean showLastDivider) {
+ this(context, attrs);
+ mShowFirstDivider = showFirstDivider;
+ mShowLastDivider = showLastDivider;
+ }
+
+ public DividerItemDecoration(Drawable divider) {
+ mDivider = divider;
+ }
+
+ public DividerItemDecoration(Drawable divider, boolean showFirstDivider,
+ boolean showLastDivider) {
+ this(divider);
+ mShowFirstDivider = showFirstDivider;
+ mShowLastDivider = showLastDivider;
+ }
+
+ @Override
+ public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
+ RecyclerView.State state) {
+ super.getItemOffsets(outRect, view, parent, state);
+ if (mDivider == null) {
+ return;
+ }
+ if (parent.getChildPosition(view) < 1) {
+ return;
+ }
+
+ if (getOrientation(parent) == LinearLayoutManager.VERTICAL) {
+ outRect.top = mDivider.getIntrinsicHeight();
+ } else {
+ outRect.left = mDivider.getIntrinsicWidth();
+ }
+ }
+
+ @Override
+ public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
+ if (mDivider == null) {
+ super.onDrawOver(c, parent, state);
+ return;
+ }
+
+ // Initialization needed to avoid compiler warning
+ int left = 0, right = 0, top = 0, bottom = 0, size;
+ int orientation = getOrientation(parent);
+ int childCount = parent.getChildCount();
+
+ if (orientation == LinearLayoutManager.VERTICAL) {
+ size = mDivider.getIntrinsicHeight();
+ left = parent.getPaddingLeft();
+ right = parent.getWidth() - parent.getPaddingRight();
+ } else { //horizontal
+ size = mDivider.getIntrinsicWidth();
+ top = parent.getPaddingTop();
+ bottom = parent.getHeight() - parent.getPaddingBottom();
+ }
+
+ for (int i = mShowFirstDivider ? 0 : 1; i < childCount; i++) {
+ View child = parent.getChildAt(i);
+ RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
+
+ if (orientation == LinearLayoutManager.VERTICAL) {
+ top = child.getTop() - params.topMargin;
+ bottom = top + size;
+ } else { //horizontal
+ left = child.getLeft() - params.leftMargin;
+ right = left + size;
+ }
+ mDivider.setBounds(left, top, right, bottom);
+ mDivider.draw(c);
+ }
+
+ // show last divider
+ if (mShowLastDivider && childCount > 0) {
+ View child = parent.getChildAt(childCount - 1);
+ RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
+ if (orientation == LinearLayoutManager.VERTICAL) {
+ top = child.getBottom() + params.bottomMargin;
+ bottom = top + size;
+ } else { // horizontal
+ left = child.getRight() + params.rightMargin;
+ right = left + size;
+ }
+ mDivider.setBounds(left, top, right, bottom);
+ mDivider.draw(c);
+ }
+ }
+
+ private int getOrientation(RecyclerView parent) {
+ if (parent.getLayoutManager() instanceof LinearLayoutManager) {
+ LinearLayoutManager layoutManager = (LinearLayoutManager) parent.getLayoutManager();
+ return layoutManager.getOrientation();
+ } else {
+ throw new IllegalStateException(
+ "DividerItemDecoration can only be used with a LinearLayoutManager.");
+ }
+ }
+}