How do I create an Options Menu like in the following Screenshot:
The Options Menu should be opened afther clicking on the "More"-Icon of a RecyclerView Item!
My try was this:
@Override public void onBindViewHolder(Holder holder, int position) { holder.txvSongTitle.setText(sSongs[position].getTitle()); holder.txvSongInfo.setText(sSongs[position].getAlbum() + " - " + sSongs[position].getArtist()); holder.btnMore.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(mContext, "More...", Toast.LENGTH_SHORT).show(); } }); }
But this causes problems because the full item is clicked if I touch on the RecyclerView Item More-Button...
Here's my RecyclerViewOnTouchListener:
public class RecyclerViewOnTouchListener implements RecyclerView.OnItemTouchListener { private GestureDetector mGestureDetector; private OnTouchCallback mOnTouchCallback; public RecyclerViewOnTouchListener(Context context, final RecyclerView recyclerView, final OnTouchCallback onTouchCallback) { mOnTouchCallback = onTouchCallback; mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() { @Override public boolean onSingleTapUp(MotionEvent e) { return true; } @Override public void onLongPress(MotionEvent e) { View child = recyclerView.findChildViewUnder(e.getX(), e.getY()); if (child != null && onTouchCallback != null) { onTouchCallback.onLongClick(child, recyclerView.getChildLayoutPosition(child)); } super.onLongPress(e); } }); } @Override public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) { View child = rv.findChildViewUnder(e.getX(), e.getY()); if (child != null && mOnTouchCallback != null && mGestureDetector.onTouchEvent(e)) { mOnTouchCallback.onClick(child, rv.getChildLayoutPosition(child)); } return false; } @Override public void onTouchEvent(RecyclerView rv, MotionEvent e) { } @Override public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) { } public interface OnTouchCallback { void onClick(View view, int position); void onLongClick(View view, int position); } }
I wasn't able to find any similar problem so I hope you can help me!
OnClickListener() { @Override public void onClick(View view) { //creating a popup menu PopupMenu popup = new PopupMenu(mCtx, holder. buttonViewOption); //inflating menu from xml resource popup. inflate(R. menu.
The best way to do this is via a click listener which will allow you to set up a communication between your RecyclerView items and the widgets or views outside of the recycler View. And that's all.
It is very easy to create an option menu like this. Just add a button in your list item design. You can use the following string to display 3 vertical dots.
<TextView android:id="@+id/textViewOptions" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_alignParentTop="true" android:paddingLeft="@dimen/activity_horizontal_margin" android:text="⋮" android:textAppearance="?android:textAppearanceLarge" />
Now in your adapter inside onBindViewHolder() use the following code.
holder.buttonViewOption.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //creating a popup menu PopupMenu popup = new PopupMenu(mCtx, holder.buttonViewOption); //inflating menu from xml resource popup.inflate(R.menu.options_menu); //adding click listener popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { switch (item.getItemId()) { case R.id.menu1: //handle menu1 click return true; case R.id.menu2: //handle menu2 click return true; case R.id.menu3: //handle menu3 click return true; default: return false; } } }); //displaying the popup popup.show(); } });
Thats it.
Source: Options Menu For RecyclerView Item
I found out that the only Menu, that looks like the Menu above is the PopupMenu
.
So in onClick
:
@Override public void onClick(View view, int position, MotionEvent e) { ImageButton btnMore = (ImageButton) view.findViewById(R.id.item_song_btnMore); if (RecyclerViewOnTouchListener.isViewClicked(btnMore, e)) { PopupMenu popupMenu = new PopupMenu(view.getContext(), btnMore); getActivity().getMenuInflater().inflate(R.menu.menu_song, popupMenu.getMenu()); popupMenu.show(); //The following is only needed if you want to force a horizontal offset like margin_right to the PopupMenu try { Field fMenuHelper = PopupMenu.class.getDeclaredField("mPopup"); fMenuHelper.setAccessible(true); Object oMenuHelper = fMenuHelper.get(popupMenu); Class[] argTypes = new Class[] {int.class}; Field fListPopup = oMenuHelper.getClass().getDeclaredField("mPopup"); fListPopup.setAccessible(true); Object oListPopup = fListPopup.get(oMenuHelper); Class clListPopup = oListPopup.getClass(); int iWidth = (int) clListPopup.getDeclaredMethod("getWidth").invoke(oListPopup); clListPopup.getDeclaredMethod("setHorizontalOffset", argTypes).invoke(oListPopup, -iWidth); clListPopup.getDeclaredMethod("show").invoke(oListPopup); } catch (NoSuchFieldException nsfe) { nsfe.printStackTrace(); } catch (NoSuchMethodException nsme) { nsme.printStackTrace(); } catch (InvocationTargetException ite) { ite.printStackTrace(); } catch (IllegalAccessException iae) { iae.printStackTrace(); } } else { MusicPlayer.playSong(position); } }
You have to make your onClick-Method pass the MotionEvent and finally implement the Method isViewClicked
in your RecyclerViewOnTouchListener:
public static boolean isViewClicked(View view, MotionEvent e) { Rect rect = new Rect(); view.getGlobalVisibleRect(rect); return rect.contains((int) e.getRawX(), (int) e.getRawY()); }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With