RecyclerView context menus (with ripple)
This commit is contained in:
parent
32a47d0f65
commit
51aba83ae2
|
@ -7,8 +7,10 @@ import android.support.v7.widget.PopupMenu;
|
|||
import android.support.v7.widget.RecyclerView;
|
||||
import android.text.format.DateUtils;
|
||||
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;
|
||||
|
@ -51,6 +53,8 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
|
|||
private final boolean showOnlyNewEpisodes;
|
||||
private final WeakReference<MainActivity> mainActivityRef;
|
||||
|
||||
private int position = -1;
|
||||
|
||||
public AllEpisodesRecycleAdapter(Context context,
|
||||
MainActivity mainActivity,
|
||||
ItemAccess itemAccess,
|
||||
|
@ -96,6 +100,10 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
|
|||
public void onBindViewHolder(final Holder holder, int position) {
|
||||
final FeedItem item = itemAccess.getItem(position);
|
||||
if (item == null) return;
|
||||
holder.itemView.setOnLongClickListener(v -> {
|
||||
this.position = position;
|
||||
return false;
|
||||
});
|
||||
holder.item = item;
|
||||
holder.position = position;
|
||||
holder.placeholder.setVisibility(View.VISIBLE);
|
||||
|
@ -189,6 +197,10 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
|
|||
return itemAccess.getItem(position);
|
||||
}
|
||||
|
||||
public int getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
private class CoverTarget extends GlideDrawableImageViewTarget {
|
||||
|
||||
private final WeakReference<Uri> fallback;
|
||||
|
@ -235,63 +247,8 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
|
|||
}
|
||||
};
|
||||
|
||||
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();
|
||||
|
||||
// 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{
|
||||
implements View.OnClickListener, View.OnCreateContextMenuListener {
|
||||
TextView placeholder;
|
||||
TextView title;
|
||||
TextView pubDate;
|
||||
|
@ -308,7 +265,7 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
|
|||
public Holder(View itemView) {
|
||||
super(itemView);
|
||||
itemView.setOnClickListener(this);
|
||||
itemView.setOnLongClickListener(this);
|
||||
itemView.setOnCreateContextMenuListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -321,12 +278,30 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
|
|||
|
||||
public FeedItem getFeedItem() { return item; }
|
||||
|
||||
public int getItemPosition() { return position; }
|
||||
|
||||
@Override
|
||||
public boolean onLongClick(View view) {
|
||||
return showContextMenu(view);
|
||||
public void onCreateContextMenu(final ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
|
||||
FeedItem item = itemAccess.getItem(getAdapterPosition());
|
||||
|
||||
MenuInflater inflater = mainActivityRef.get().getMenuInflater();
|
||||
inflater.inflate(R.menu.allepisodes_context, menu);
|
||||
|
||||
if (item != null) {
|
||||
menu.setHeaderTitle(item.getTitle());
|
||||
}
|
||||
|
||||
FeedItemMenuHandler.MenuInterface contextMenuInterface = (id, visible) -> {
|
||||
if (menu == null) {
|
||||
return;
|
||||
}
|
||||
MenuItem item1 = menu.findItem(id);
|
||||
if (item1 != null) {
|
||||
item1.setVisible(visible);
|
||||
}
|
||||
};
|
||||
FeedItemMenuHandler.onPrepareMenu(mainActivityRef.get(), contextMenuInterface, item, true,
|
||||
null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public interface ItemAccess {
|
||||
|
|
|
@ -58,6 +58,8 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap
|
|||
|
||||
private boolean locked;
|
||||
|
||||
private int position = -1;
|
||||
|
||||
public QueueRecyclerAdapter(MainActivity mainActivity,
|
||||
ItemAccess itemAccess,
|
||||
ActionButtonCallback actionButtonCallback,
|
||||
|
@ -84,13 +86,19 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap
|
|||
public void onBindViewHolder(ViewHolder holder, int pos) {
|
||||
FeedItem item = itemAccess.getItem(pos);
|
||||
holder.bind(item);
|
||||
holder.position = pos;
|
||||
holder.itemView.setOnLongClickListener(v -> {
|
||||
position = pos;
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
public int getItemCount() {
|
||||
return itemAccess.getCount();
|
||||
}
|
||||
|
||||
public int getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
public class ViewHolder extends RecyclerView.ViewHolder
|
||||
implements View.OnClickListener, View.OnCreateContextMenuListener {
|
||||
|
@ -106,7 +114,6 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap
|
|||
private final ImageButton butSecondary;
|
||||
|
||||
private FeedItem item;
|
||||
private int position;
|
||||
|
||||
public ViewHolder(View v) {
|
||||
super(v);
|
||||
|
|
|
@ -18,6 +18,7 @@ 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.Toast;
|
||||
|
||||
|
@ -39,7 +40,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.menuhandler.FeedItemMenuHandler;
|
||||
import de.danoeh.antennapod.menuhandler.MenuItemUtils;
|
||||
import de.danoeh.antennapod.view.DividerItemDecoration;
|
||||
import rx.Observable;
|
||||
|
@ -260,6 +263,28 @@ public class AllEpisodesFragment extends Fragment {
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onContextItemSelected(MenuItem item) {
|
||||
if(!isVisible()) {
|
||||
return false;
|
||||
}
|
||||
int pos = listAdapter.getPosition();
|
||||
FeedItem selectedItem = itemAccess.getItem(pos);
|
||||
|
||||
if (selectedItem == null) {
|
||||
Log.i(TAG, "Selected item at position " + pos + " 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;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
return onCreateViewHelper(inflater, container, savedInstanceState,
|
||||
|
@ -280,6 +305,7 @@ public class AllEpisodesFragment extends Fragment {
|
|||
recyclerView.setHasFixedSize(true);
|
||||
RecyclerView.ItemDecoration itemDecoration = new DividerItemDecoration(getActivity(), null);
|
||||
recyclerView.addItemDecoration(itemDecoration);
|
||||
registerForContextMenu(recyclerView);
|
||||
|
||||
progLoading = (ProgressBar) root.findViewById(R.id.progLoading);
|
||||
|
||||
|
|
|
@ -79,9 +79,6 @@ public class QueueFragment extends Fragment {
|
|||
private TextView txtvEmpty;
|
||||
private ProgressBar progLoading;
|
||||
|
||||
private ContextMenu contextMenu;
|
||||
private AdapterView.AdapterContextMenuInfo lastMenuInfo = null;
|
||||
|
||||
private List<FeedItem> queue;
|
||||
private List<Downloader> downloaderList;
|
||||
|
||||
|
@ -166,7 +163,10 @@ public class QueueFragment extends Fragment {
|
|||
recyclerAdapter.notifyDataSetChanged();
|
||||
break;
|
||||
case MOVED:
|
||||
// ItemTouchHelper already handled everything
|
||||
int from = FeedItemUtil.indexOfItemWithId(queue, event.item.getId());
|
||||
int to = event.position;
|
||||
Collections.swap(queue, from, to);
|
||||
recyclerAdapter.notifyItemMoved(from, to);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -217,7 +217,6 @@ public class QueueFragment extends Fragment {
|
|||
}
|
||||
|
||||
private void resetViewState() {
|
||||
unregisterForContextMenu(recyclerView);
|
||||
blockDownloadObserverUpdate = false;
|
||||
if (downloadObserver != null) {
|
||||
downloadObserver.onPause();
|
||||
|
@ -319,32 +318,19 @@ public class QueueFragment extends Fragment {
|
|||
} else {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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 boolean onContextItemSelected(MenuItem item) {
|
||||
AdapterView.AdapterContextMenuInfo menuInfo = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
|
||||
if(menuInfo == null) {
|
||||
menuInfo = lastMenuInfo;
|
||||
if(!isVisible()) {
|
||||
return false;
|
||||
}
|
||||
FeedItem selectedItem = itemAccess.getItem(menuInfo.position);
|
||||
int pos = recyclerAdapter.getPosition();
|
||||
FeedItem selectedItem = itemAccess.getItem(pos);
|
||||
|
||||
if (selectedItem == null) {
|
||||
Log.i(TAG, "Selected item at position " + menuInfo.position + " was null, ignoring selection");
|
||||
Log.i(TAG, "Selected item at position " + pos + " was null, ignoring selection");
|
||||
return super.onContextItemSelected(item);
|
||||
}
|
||||
|
||||
|
@ -371,6 +357,7 @@ public class QueueFragment extends Fragment {
|
|||
RecyclerView.ItemDecoration itemDecoration = new DividerItemDecoration(getActivity(), null);
|
||||
recyclerView.addItemDecoration(itemDecoration);
|
||||
recyclerView.setHasFixedSize(true);
|
||||
registerForContextMenu(recyclerView);
|
||||
|
||||
itemTouchHelper = new ItemTouchHelper(
|
||||
new ItemTouchHelper.SimpleCallback(ItemTouchHelper.UP | ItemTouchHelper.DOWN, ItemTouchHelper.RIGHT) {
|
||||
|
@ -380,8 +367,6 @@ public class QueueFragment extends Fragment {
|
|||
int from = viewHolder.getAdapterPosition();
|
||||
int to = target.getAdapterPosition();
|
||||
Log.d(TAG, "move(" + from + ", " + to + ")");
|
||||
Collections.swap(queue, from, to);
|
||||
recyclerAdapter.notifyItemMoved(from, to);
|
||||
DBWriter.moveQueueItem(from, to, true);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/listitem_threeline_height"
|
||||
android:orientation="horizontal"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
tools:background="@android:color/darker_gray">
|
||||
|
||||
<RelativeLayout
|
||||
|
|
Loading…
Reference in New Issue