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)