Join the social network of Tech Nerds, increase skill rank, get work, manage projects...
 
  • How to create Contextual action mode over toolbar using recycler view in android?

    • 0
    • 0
    • 0
    • 0
    • 1
    • 0
    • 0
    • 0
    • 5.77k
    Comment on it

    While creating list on a recycler view we need more functionality like delete, copy and more. Like our popular apps what's app, gmail and hike we found toolbar in action mode if we long press list items on that, same UI with functionality we will implement using the contextual action mode. Below steps will help you to implement this Toolbar Action Mode.

    Step1: Starting with a recycler view layout in a xml file

     <android.support.v7.widget.RecyclerView
            android:id="@+id/recyclerView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scrollbars="none" />

    Step2: Initializing recycler view

    recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
            recyclerView.setHasFixedSize(true);
            recyclerView.setLayoutManager(new LinearLayoutManager(this));
    
    	// creating model class(Item_Model) with two string variables title and sub_title
            // array_list to set row entries
            item_models = new ArrayList<>();
            for (int i = 1; i <= 40; i++)
                item_models.add(new Item_Model("Title of row" + i, "Sub Title of a row" + i));
    
            adapter = new RecyclerView_Adapter(ActionModeActivity.this, item_models);
            recyclerView.setAdapter(adapter);
            adapter.notifyDataSetChanged();

    Step3: Implement item click and long click over recycler view

    private void implementRecyclerViewClickListeners() {
            recyclerView.addOnItemTouchListener(new RecyclerTouchListener(this, recyclerView, new RecyclerClick_Listener() {
                @Override
                public void onClick(View view, int position) {
                    //If ActionMode not null select item
                    if (mActionMode != null)
                        onListItemSelect(position);
                }
    
                @Override
                public void onLongClick(View view, int position) {
                    //Select item on long click
                    onListItemSelect(position);
                }
            }));
        }
    
        //List item select method
        private void onListItemSelect(int position) {
    
            adapter.toggleSelection(position);//Toggle the selection
            boolean hasCheckedItems = adapter.getSelectedCount() > 0;//Check if any items are already selected or not
    
            if (hasCheckedItems && mActionMode == null)
                // there are some selected items, start the actionMode
                mActionMode = ((AppCompatActivity) this).startSupportActionMode(new Toolbar_ActionMode_Callback(this, adapter, item_models, false));
            else if (!hasCheckedItems && mActionMode != null)
                // there no selected items, finish the actionMode
                mActionMode.finish();
    
            if (mActionMode != null)
                //set action mode title on item selection
                mActionMode.setTitle(String.valueOf(adapter.getSelectedCount()) + " selected");
        }
    
        //Set action mode null after use
        public static void setNullToActionMode() {
            if (mActionMode != null)
                mActionMode = null;
        }
    
        //Delete selected rows
        public static void deleteRows() {
    
            SparseBooleanArray selected = adapter.getSelectedIds();//Get selected ids
    
            //Loop all selected ids
            for (int i = (selected.size() - 1); i >= 0; i--) {
                if (selected.valueAt(i)) {
                    //If current id is selected remove the item via key
                    item_models.remove(selected.keyAt(i));
                    adapter.notifyDataSetChanged();//notify adapter
    
                }
            }
            Toast.makeText(this, selected.size() + " item deleted.", Toast.LENGTH_SHORT).show();//Show Toast
            mActionMode.finish();//Finish action mode after use
        }

    Step4: Now creating adapter class RecyclerView_Adapter with removing seleted items methods

    //Remove selected selections
        public void removeSelection() {
            mSelectedItemsIds = new SparseBooleanArray();
            notifyDataSetChanged();
        }
    
        //Put or delete selected position into SparseBooleanArray
        public void selectView(int position, boolean value) {
            if (value)
                mSelectedItemsIds.put(position, value);
            else
                mSelectedItemsIds.delete(position);
    
            notifyDataSetChanged();
        }

    Step5: Interface for communication

    public interface RecyclerClick_Listener {
        void onClick(View view, int position);
        void onLongClick(View view, int position);
    }

    Step6: Now creating touch listener class and implementing interface we created

    public class RecyclerTouchListener implements RecyclerView.OnItemTouchListener {
    
        private GestureDetector gestureDetector;
        private RecyclerClick_Listener clickListener;
    
        public RecyclerTouchListener(Context context, final RecyclerView recyclerView, final RecyclerClick_Listener clickListener) {
            this.clickListener = clickListener;
            gestureDetector = 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 && clickListener != null) {
                        clickListener.onLongClick(child, recyclerView.getChildPosition(child));
                    }
                }
            });
        }
    
        @Override
        public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
    
            View child = rv.findChildViewUnder(e.getX(), e.getY());
            if (child != null && clickListener != null && gestureDetector.onTouchEvent(e)) {
                clickListener.onClick(child, rv.getChildPosition(child));
            }
            return false;
        }
    
        @Override
        public void onTouchEvent(RecyclerView rv, MotionEvent e) {
        }
    
        @Override
        public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
    
        }
    }

    Step7: Final step is to implement menu items click listeners

    public class Toolbar_ActionMode_Callback implements ActionMode.Callback {
        private Context context;
        private RecyclerView_Adapter recyclerView_adapter;
        private ArrayList<Item_Model> message_models;
        private boolean isListViewFragment;
    
        public Toolbar_ActionMode_Callback(Context context, RecyclerView_Adapter recyclerView_adapter, ArrayList<Item_Model> message_models, boolean isListViewFragment) {
            this.context = context;
            this.recyclerView_adapter = recyclerView_adapter;
            this.message_models = message_models;
            this.isListViewFragment = isListViewFragment;
        }
    
        @Override
        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
            mode.getMenuInflater().inflate(R.menu.menu_main, menu);         //Inflate the menu over action mode
            return true;
        }
    
        @Override
        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
            //Sometimes the meu will not be visible so for that we need to set their visibility manually in this method
            //So here show action menu according to SDK Levels
            if (Build.VERSION.SDK_INT < 11) {
                MenuItemCompat.setShowAsAction(menu.findItem(R.id.action_delete), MenuItemCompat.SHOW_AS_ACTION_NEVER);
                MenuItemCompat.setShowAsAction(menu.findItem(R.id.action_copy), MenuItemCompat.SHOW_AS_ACTION_NEVER);
                MenuItemCompat.setShowAsAction(menu.findItem(R.id.action_forward), MenuItemCompat.SHOW_AS_ACTION_NEVER);
            } else {
                menu.findItem(R.id.action_delete).setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
                menu.findItem(R.id.action_copy).setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
                menu.findItem(R.id.action_forward).setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
            }
            return true;
        }
    
        @Override
        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
            switch (item.getItemId()) {
                case R.id.action_delete:
                    ActionModeActivity.deleteRows();       //delete selected rows
                    break;
                case R.id.action_copy:
                    //Get selected ids on basis of current fragment action mode
                    SparseBooleanArray selected;
                    selected = recyclerView_adapter.getSelectedIds();
    
                    int selectedMessageSize = selected.size();
                    //Loop to all selected items
                    for (int i = (selectedMessageSize - 1); i >= 0; i--) {
                        if (selected.valueAt(i)) {
                            //get selected data in Model
                            Item_Model model = message_models.get(selected.keyAt(i));
                            String title = model.getTitle();
                            String subTitle = model.getSubTitle();
                            //Print the data to show if its working properly or not
                            Log.e("Selected Items", "Title - " + title + "\n" + "Sub Title - " + subTitle);
                        }
                    }
                    Toast.makeText(context, "You selected Copy menu.", Toast.LENGTH_SHORT).show();//Show toast
                    mode.finish();          //Finish action mode
                    break;
                case R.id.action_forward:
                    Toast.makeText(context, "You selected Forward menu.", Toast.LENGTH_SHORT).show();//Show toast
                    mode.finish();          //Finish action mode
                    break;
            }
            return false;
        }
    
        @Override
        public void onDestroyActionMode(ActionMode mode) {
            //When action mode destroyed remove selected selections and set action mode to null
            //First check current fragment action mode
            recyclerView_adapter.removeSelection();         // remove selection
            ActionModeActivity.setNullToActionMode();       //Set action mode null
        }
    }

     

 1 Comment(s)

  • Nice article, but you don't show the implementation for most of the methods that you use in the adapter. So it takes quite some effort to get this working when trying to follow the article.
Sign In
                           OR                           
                           OR                           
Register

Sign up using

                           OR                           
Forgot Password
Fill out the form below and instructions to reset your password will be emailed to you:
Reset Password
Fill out the form below and reset your password: