I want to add a counter instead of a normal title when items get selected, for example, if the user select 2 items the title of the cab should change to 2.
i have tried setting actionMode.setTitle(String.valueOf(counter)),whre selected_items_list is where all selected items get added , but it just set to title to 0 inside onPrepareActionMode.
The Counter is increased when the Update inside TextViewHolder method is called (inside of the onClick listeners).
I'm using a RecyclerView, below is the ViewHolder and the ActionMode.Callback.
the CAB contains only two elements/items: Delete and share buttons.
EDIT
Moved actionMode.setTitle() inside Update method (TextViewholder) .
title is changed to the number of elements selected. now finding how to decreased when items get deselected.
ViewHolder
public class TextViewHolder extends ViewHolder {
// each data item is just a string in this case
private TextView titolo;
private TextView ora;
private RelativeLayout selezione_layout_testo;
public TextViewHolder(View v) {
super(v);
titolo = itemView.findViewById(R.id.testo);
selezione_layout_testo =
itemView.findViewById(R.id.layout_selezione_testo); //This element
is root view of the items
ora = itemView.findViewById(R.id.ora);
}
void selectItem(ModelloDati item) {
if (multiSelect) {
if (selected_items_list.contains(item)) {
selected_items_list.remove(item);
if(selected_items_list.size()==0)
{
if (actionMode != null ){
actionMode.finish();
}
}
selezione_layout_testo.setBackgroundColor(
context.getResources().getColor(R.color.transparent));
} else {
selected_items_list.add(item);
selezione_layout_testo.setBackgroundColor(
context.getResources().getColor(R.color.Colore_selezione));
}
}
}
void update(final ModelloDati value) {
if (selected_items_list.contains(value)) {
selezione_layout_testo.setBackgroundColor(
context.getResources().getColor(R.color.Colore_selezione));
} else {
selezione_layout_testo.setBackgroundColor(
context.getResources().getColor(R.color.transparent));
}
itemView.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View view) {
actionMode =
((AppCompatActivity)view.getContext()).startSupportActionMode(
actionModeCallback);
selectItem(value);
//-------------- EDITED!!!
String counter_string = String.valueOf(counter);
actionMode.setTitle(counter_string);
return true;
}
});
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
counter++;
selectItem(value);
}
});
}
}
ActionMode.Callback
private ActionMode.Callback actionModeCallback = new ActionMode.Callback() {
#Override
public boolean onCreateActionMode(final ActionMode actionMode, Menu menu)
{
multiSelect = true;
actionMode.getMenuInflater().inflate(R.menu.action_bar_menu, menu);
return true;
}
#Override
public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
return false;
}
#Override
public boolean onActionItemClicked(
ActionMode actionMode, MenuItem menuItem) {
switch (menuItem.getItemId()){
case R.id.delete:
for(ModelloDati oggetto : selected_items_list)
{
if(oggetto.getTYPE() == tlTEXT)
data_list.remove(data_list.indexOf(oggetto)-1);
data_list.remove(oggetto);
}
actionMode.finish();
return true;
case R.id.share:
//Do nothing
return true;
default:
return false;
}
}
#Override
public void onDestroyActionMode(ActionMode actionMode) {
multiSelect = false;
selected_items_list.clear();
notifyDataSetChanged();
counter = 0;
}
};
Variables
private ArrayList<ModelloDati> data_list;
private ArrayList<ModelloDati> selected_items_list = new ArrayList<>();
private Context context;
private static final int tlTEXT = 0;
private boolean multiSelect = false;
private ActionMode actionMode;
private int counter = 0;
I have seen a lot of tutorials where the counter is used but I'm unable to implement it inside my code :(
Related
I am trying to delete multiple items from recyclerView. The items in the recyclerView has an attribute isSelected. I am setting the attribute isSelected to true when user clicks on the recyclerView item. After selection user can click delete button present in the options menu to delete the selected items. The code has unexpected behaviour, like when delete button is pressed, some of the selected items are deleted while some are not. Also some of the items get automatically selected at random positions.
Model.java
public class Model {
private String text;
private boolean isSelected = false;
public Model(String text) {
this.text = text;
}
public String getText() {
return text;
}
public void setSelected(boolean selected) {
isSelected = selected;
}
public boolean isSelected() {
return isSelected;
}
}
RecyclerViewAdapter.java
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.MyViewHolder> {
private List<Model> mModelList;
private Context mCtx;
public RecyclerViewAdapter(Context ctx, List<Model> modelList) {
this.mModelList = modelList;
this.mCtx = ctx;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(mCtx);
View view = inflater.inflate(R.layout.item_row, parent, false);
return new MyViewHolder(view);
}
#Override
public void onBindViewHolder(final MyViewHolder holder, final int position) {
final Model model = mModelList.get(position);
holder.view.setBackgroundColor(model.isSelected() ? Color.CYAN : Color.WHITE);
holder.tvItems.setText(model.getText());
holder.tvItems.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
model.setSelected(!model.isSelected());
holder.tvItems.setBackgroundColor(model.isSelected() ? Color.CYAN : Color.WHITE);
notifyItemChanged(position);
}
});
}
#Override
public int getItemCount() {
return mModelList == null ? 0 : mModelList.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
private TextView tvItems;
private View view;
public MyViewHolder(View itemView) {
super(itemView);
view = itemView;
tvItems = itemView.findViewById(R.id.tvItems);
}
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
private List<Model> mModelList;
private RecyclerView mRecyclerView;
private RecyclerView.Adapter mAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRecyclerView = (RecyclerView) findViewById(R.id.rvListItems);
mAdapter = new RecyclerViewAdapter(this, getListData());
LinearLayoutManager manager = new LinearLayoutManager(MainActivity.this);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(manager);
mRecyclerView.setAdapter(mAdapter);
}
private List<Model> getListData() {
mModelList = new ArrayList<>();
for (int i = 1; i <= 25; i++) {
mModelList.add(new Model("TextView " + i));
}
return mModelList;
}
private void deleteSelectedItems() {
if (mModelList != null){
for (int i=0; i<mModelList.size(); i++){
if (mModelList.get(i).isSelected()){
Log.d("testingTAG", String.valueOf(i));
mModelList.remove(i);
mAdapter.notifyItemRemoved(i);
mAdapter.notifyItemRangeChanged(i, mModelList.size());
i--;
}
}
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()){
case R.id.action_delete:
deleteSelectedItems();
break;
}
return super.onOptionsItemSelected(item);
}
}
Any kind of help will be greatly appreciated.
You should use holder.getAdapterPosition() inside your clicklistener .Change your onclick as given below and try.
public void onClick(View view) {
final Model model = mModelList.get(holder.getAdapterPosition());
model.setSelected(!model.isSelected());
holder.tvItems.setBackgroundColor(model.isSelected() ? Color.CYAN : Color.WHITE);
notifyItemChanged(holder.getAdapterPosition());
}
Answer from #pop selects items, change background color to CYAN if item is selected and inverse selected flag of Model class instance.
you should delete selected items from your mModelList using a iterator, you can't delete items from list inside for loop
Calling remove in foreach loop in Java
I've got a Lsitview populated with CheckedTextViews. My goal is to be able to delete multiple rows at onece, if possible with MultiChoiceModeListener.
To use it, I have to set the ListView CHOICE_MODE_MULTIPLE_MODAL.
The frist problem is now: I cant just chek the checkboxes now, because the listview isnt ChOICE_MODE_MULTIPLE anymore.
I hade the idear to set it CHOICE MODE MULTIPLE and just set an OnItemClickListenerfor the ListView, but then the ChoiceModeMultiple and its Method onItemStateChaed Method always gets called, even if i just wanna check a checkbox in my App.
Any solutions on how to fix that?
The Code (layout is the ListVIew) :
layout.setMultiChoiceModeListener(new AbsListView.MultiChoiceModeListener() {
#Override
public void onItemCheckedStateChanged(android.view.ActionMode actionMode, int i, long l, boolean b) {
if (!list_items.contains(list.get(i))) {
count++;
list_items.add(list.get(i));
actionMode.setTitle(count + " items selected");
} else if (list_items.contains(list.get(i))) {
count--;
list_items.remove(list.get(i));
actionMode.setTitle(count + " items selected");
}
}
}
Try this example, please refer this and solve
public class MainActivity extends AppCompatActivity {
ListView list;
ArrayAdapter<String> arrayAdapter;
ArrayList<String> arrayList = new ArrayList<>();
ArrayList<String> arrayList2 = new ArrayList<>();
int count = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
list = (ListView)findViewById(R.id.listItems);
arrayList.add("one");
arrayList.add("two");
arrayList.add("three");
arrayList.add("four");
arrayList.add("five");
arrayAdapter = new ArrayAdapter<String>(this,R.layout.list_layout,R.id.textView,arrayList);
list.setAdapter(arrayAdapter);
list.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
list.setMultiChoiceModeListener(new AbsListView.MultiChoiceModeListener() {
#Override
public void onItemCheckedStateChanged(ActionMode actionMode, int position, long l, boolean b) {
count = count+1;
actionMode.setTitle(count + " items selected");
arrayList2.add(arrayList.get(position));
}
#Override
public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
MenuInflater inflater = actionMode.getMenuInflater();
inflater.inflate(R.menu.list_menu,menu);
return true;
}
#Override
public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
return false;
}
#Override
public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) {
switch (menuItem.getItemId())
{
case R.id.delete_id:
for(String msg : arrayList2) {
arrayAdapter.remove(msg);
}
Toast.makeText(getApplicationContext(),"deleted",Toast.LENGTH_SHORT).show();
count=0;
actionMode.finish();
return true;
default:
Toast.makeText(getApplicationContext(),"Nothing selected",Toast.LENGTH_SHORT).show();
break;
}
return false;
}
#Override
public void onDestroyActionMode(ActionMode actionMode) {
}
});
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
adapterView.setSelected(true);
}
});
}
}
I am using a contextual action bar and wish to retrieve each value selected to pass to another activity after I click on the 'mail' button. How can I do this?e
Code for the CAB.
mAdapter = new SelectionAdapter(this, R.layout.activity_result, R.id.name, new String[] {TAG_NAME, TAG_ROOM_PRICE});
setListAdapter(mAdapter);
lv.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
getListView().setMultiChoiceModeListener(new AbsListView.MultiChoiceModeListener() {
private int nr = 0;
#Override
public boolean onCreateActionMode(android.view.ActionMode mode, Menu menu) {
nr = 0;
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.contextual_menu, menu);
return true;
}
#Override
public boolean onPrepareActionMode(android.view.ActionMode mode, Menu menu) {
return false;
}
#Override
public boolean onActionItemClicked(android.view.ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case R.id.email:
}
return false;
}
#Override
public void onDestroyActionMode(android.view.ActionMode mode) {
mAdapter.clearSelection();
}
#Override
public void onItemCheckedStateChanged(android.view.ActionMode mode, int position, long id, boolean checked) {
if (checked) {
nr++;
mAdapter.setNewSelection(position, checked);
} else {
nr--;
mAdapter.removeSelection(position);
}
mode.setTitle("No: of resorts selected: " + nr);
}
});
lv.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
//String name = ((TextView) view.findViewById(R.id.name)).getText().toString();
getListView().setItemChecked(position, !mAdapter.isPositionChecked(position));
return true;
}
});
Selection adapter class which is used to define the object mAdapter
private class SelectionAdapter extends ArrayAdapter<String> {
private HashMap<Integer, Boolean> mSelection = new HashMap<Integer, Boolean>();
public SelectionAdapter(Context context, int resource, int textViewResourceId, String[] objects) {
super(context, resource, textViewResourceId, objects);
}
public void setNewSelection(int position, boolean value) {
mSelection.put(position, value);
notifyDataSetChanged();
}
public boolean isPositionChecked(int position) {
Boolean result = mSelection.get(position);
return result == null ? false : result;
}
public Set<Integer> getCurrentCheckedPosition() {
return mSelection.keySet();
}
public void removeSelection(int position) {
mSelection.remove(position);
notifyDataSetChanged();
}
public void clearSelection() {
mSelection = new HashMap<Integer, Boolean>();
notifyDataSetChanged();
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = super.getView(position, convertView, parent);//let the adapter handle setting up the row views
v.setBackgroundColor(getResources().getColor(android.R.color.background_light)); //default color
if (mSelection.get(position) != null) {
v.setBackgroundColor(getResources().getColor(android.R.color.holo_blue_light));// this is a selected position so make it red
}
return v;
}
}
I wish to retrieve the String value of every selection that I make
I found the solution.
mAdapter.setNewSelection(position, checked);
String get_list = resortsList.get(position).get(TAG_NAME);
stringList.add(get_list);
And to remove the item selected when deselected:`int i;
for(i = 0 ; i < stringList.size(); i++){
if(stringList.get(i).equals(resortsList.get(position).get(TAG_NAME))){
stringList.remove(i);
Log.d("String List: ", stringList.toString());
break;
}
}`
I have set a ListView with a custom CursorAdapter in MainActivity, and when "EDIT" menu is clicked, the CursorAdapter changes its View to set visibility of CheckBoxes.
At this, I found that the onClickListener is aware of changes of the CheckBox not in the MainAcitivity but in the CursorAdapter class. So I coded that the id values are restored in a ArrayList whenever the CheckBoxes are clicked, and returned when a method is called in MainActivity.
The problem is, I want for option menus to be changed if the CheckBox is checked (for example, "DELETE" and "MOVE" menu is unable when no CheckBox is checked, and enabled once CheckBoxes are clicked), but don't know how.
Some parts of my MainActivity and CursorAdapter
MainActivity.java:
public class MainActivity extends Activity {
private MenuItem itEdit, itSort, itView, itSelectAll, itDeselectAll, itDelete, itMove;
private boolean isEditChecked;
private ListView lvWords;
private WordAdapter wordadapter;
private ArrayList<Integer> checkedWords;
private Cursor wordCursor;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lvWords = (ListView) findViewById(R.id.lv_words);
dbhandler = DBHandler.open(this);
wordCursor = dbhandler.selectWords(activeNoteId);
wordadapter = new WordAdapter(this, wordCursor, isEditChecked);
lvWords.setAdapter(wordadapter);
....
...
..
}
protected void onResume() {
super.onResume();
refreshListViews();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
itEdit = menu.findItem(R.id.it_edit);
itSort = menu.findItem(R.id.it_sort);
itView = menu.findItem(R.id.it_view);
itSelectAll = menu.findItem(R.id.it_select_all);
itDeselectAll = menu.findItem(R.id.it_deselect_all);
itDelete = menu.findItem(R.id.it_delete);
itMove = menu.findItem(R.id.it_move);
itEdit.setVisible(true);
itSort.setVisible(true);
itView.setVisible(true);
itSelectAll.setVisible(false);
itDeselectAll.setVisible(false);
itDelete.setVisible(false);
itMove.setVisible(false);
return true;
}
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
....
...
return super.onPrepareOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.it_edit:
onEditMenuClicked();
break;
case R.id.it_delete:
checkedWords = wordadapter.getCheckedArrayList();
final int checkedDeleteSize = checkedWords.size();
....
...
break;
}
return super.onOptionsItemSelected(item);
}
// when edit menu clicked
private void onEditMenuClicked() {
isEditChecked = !isEditChecked;
itSort.setVisible(!isEditChecked);
itView.setVisible(!isEditChecked);
itSelectAll.setVisible(isEditChecked);
itDeselectAll.setVisible(isEditChecked);
itDelete.setVisible(isEditChecked);
itMove.setVisible(isEditChecked);
wordadapter.setVisibility(isEditChecked);
refreshListViews();
}
private void refreshListViews() {
wordCursor.close();
wordCursor = dbhandler.selectWords(activeNoteId);
wordadapter.changeCursor(wordCursor);
setVisibilityViews();
}
}
WordAdapter.java:
public class WordAdapter extends CursorAdapter {
private boolean isCheckBoxVisable;
private ArrayList<Integer> checkedArray;
private boolean setCheck;
public WordAdapter(Context context, Cursor c, boolean check) {
super(context, c);
isCheckBoxVisable = check;
checkedArray = new ArrayList<Integer>();
setCheck = false;
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
CheckBox check = (CheckBox) view.findViewById(R.id.cb_list_word_check);
final int id = cursor.getInt(cursor.getColumnIndex("_id"));
if(isCheckBoxVisable)
check.setVisibility(View.VISIBLE);
else check.setVisibility(View.GONE);
check.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
/////// I think something is added here /////
if(isChecked){
checkedArray.add(id);
}
else{
checkedArray.remove(new Integer(id));
}
}
});
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
Log.d("newView()","start of newView");
LayoutInflater inflater = LayoutInflater.from(context);
View v = inflater.inflate(R.layout.word_list_row, parent, false);
Log.d("newView()","end of newView");
return v;
}
// set visibility of checkbox
public void setVisibility(boolean check){
isCheckBoxVisable = check;
}
public ArrayList<Integer> getCheckedArrayList(){
return checkedArray;
}
}
If you want to perform a menu update, you must call invalidateOptionsMenu(). It will call onCreateOptionsMenu(Menu menu) back, were you can update (re-create) a menu depending on the state your activity is in.
Runtime changes in menu are explained here in more details.
I've a ListView and when i click on an item i would like that it's colored in a determinate color because when i click on an item compairs the Contextual Action Bar, Why do people have to see which items on the list were selected. I wrote this code.
private void onListItemSelect(int position) {
adapter.toggleSelection(position);
boolean hasCheckedItems = adapter.getSelectedCount() > 0;
if (hasCheckedItems && mActionMode == null)
// there are some selected items, start the actionMode
mActionMode = startSupportActionMode(new ActionModeCallback());
else if (!hasCheckedItems && mActionMode != null)
// there no selected items, finish the actionMode
mActionMode.finish();
if (mActionMode != null)
mActionMode.setTitle(String.valueOf(adapter.getSelectedCount()) + " selezionati");
}
private class ActionModeCallback implements ActionMode.Callback {
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
// inflate contextual menu
mode.getMenuInflater().inflate(R.menu.contextual_action_bar, menu);
return true;
}
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_item1:
item.setIcon(R.drawable.delete_pressed);
//mode.finish();
return true;
default:
return false;
}
}
#Override
public void onDestroyActionMode(ActionMode mode) {
// remove selection
adapter.removeSelection();
mActionMode = null;
}
}
applicationListView.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
adapter.isSelected(true, view);
onListItemSelect(position);
}
});
In my adapter i've
public void selectView(int position, boolean value) {
if (value)
mSelectedItemsIds.put(position, value);
else
mSelectedItemsIds.delete(position);
notifyDataSetChanged();
}
public void toggleSelection(int position) {
selectView(position, !mSelectedItemsIds.get(position));
}
public int getSelectedCount() {
return mSelectedItemsIds.size();
}
public void removeSelection() {
mSelectedItemsIds = new SparseBooleanArray();
notifyDataSetChanged();
}
public void isChecked(boolean checked, View v) {
if(checked) {
v.setBackgroundColor(Color.LTGRAY);
}
else {
v.setBackgroundColor(Color.TRANSPARENT);
}
}
The problem is that when I click on the item are colored correctly and appears contextual action bar and so far all is well. The problem is that the elements remain colored even when there is no longer the contextual action bar. I wish that when there were restored to their normal color, then clear. How can I do?