delete selected list items - android

I have an array string that i used in my Fragment,and i show the array string items with setListAdapter in my list:
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
String[] array = getResources().getStringArray(R.array.examlearray);
final ArrayList<String> str = new ArrayList<String>(Arrays.asList(array));
final ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(getActivity(),android.R.layout.simple_list_item_1, str );
setListAdapter(arrayAdapter);
final ListView listView = getListView();
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
listView.setMultiChoiceModeListener(new MultiChoiceModeListener() {...
and under my onActionItemClicked i want to implement my deleteSelectedItem() method,that delete selected list items,and this my code,but it didn't remove selected item,it is just remove from first of list,and when i select all the items and press remove,the app crash!what should do?,Any help would be appreciated! Thanks!
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
// Respond to clicks on the actions in the CAB
switch (item.getItemId()) {
case R.id.delete:
// deleteSelectedItems();
Log.i(TAG, "deleteSelectedEntries");
SparseBooleanArray checkedItems = listView.getCheckedItemPositions();
for(int i=0;i<checkedItems.size();++i)
{ if(checkedItems.valueAt(i))
str.remove(i);
}
arrayAdapter.notifyDataSetChanged();

Instead of looping through the SparseBooleanArray you get from listView.getCheckedItemPositions(), you have to loop through the items of the ArrayAdapter and then check if the SparseBooleanArray returns true for this item. This is because when you remove items from the ArrayAdapter, listView.getCheckedItemPositions() still returns items that don't exist anymore.
So in your case:
SparseBooleanArray checkedItems = listView.getCheckedItemPositions();
// Loop backwards, so you can remove the items from within the loop
for (int i = arrayAdapter.getCount() - 1; i >= 0; i--) {
if (checkedItems.get(i)) {
// This item is checked and can be removed
arrayAdapter.remove(arrayAdapter.getItem(i));
}
}
The reason your app crashed is because you try to remove non existing items.

You will need to hold a reference to your array adapter. Then try calling the remove function on the adapter followed by notifyDataSetChanged. If you only have a reference to the position, you will also need to use getItem.

Keep the reference of adapter and data list used for creating adapter, Its better to use ArrayList, since it gives flexibility to remove elements easily. To set the adapter you can use following code -
String[] array = getResources().getStringArray(R.array.examlearray);
ArrayList<String> str = new ArrayList<String>(Arrays.asList(array));
ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(getActivity(),android.R.layout.simple_list_item_1, str );
menuListView.setAdapter(arrayAdapter);
To remove element first remove the element from the data list and then calling notifyDatasetChnaged will update the listView as well. you can call following code inside onActionItemClicked
`for(int i=0;i<checkedItems.size();++i)
{ if(checkedItems.valueAt(i))
str.remove(i);
}
arrayAdapter.notifyDataSetChanged();

Related

Check all of adapter elements in ListView

I have CustomAdapter which I am using for populating ListView with some data.
Each element in ListView has two variables. For each listview (in onItemClick method) I must check this variables and If they are the same - do some code and If they are different - do another code, for example Toast.makeText(EPG.this, "Variables are different", Toast.LENGTH_SHORT).show();
So I have tried this:
private List<SomeItem> items = new ArrayList();
//items were created
SomeAdapter adapter = new SomeAdapter(this, R.layout.list_item, items);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new android.widget.AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
for(int i=0; i<=items.size(); i++) {
SomeItem item = items.get(position);
String tmpCI = item.getFirstVariable();
String tmpPCI = item.getecondVariable();
if (!tmpCI.equals(tmpPCI)) {
//some code
} else {
Toast.makeText(EPG.this, "Variables are different", Toast.LENGTH_SHORT).show();
}
}
}
});
But all of my listview elements have values of the first element in those two variables.
So how can I do something like item.next(); for validating all of items in listview?
UPD:
Sorry, I will provide more information about what I am doing after checking variables of listview items for understanding my issue.
I have one more adapter:
SomeAnotherAdapter adapterPr = new SomeAnotherAdapter(this, R.layout.list_tem_another, itemsAnother);
and one more listview:
listViewAnother.setAdapter(adapterPr);
First of all I understood, that first variable should be from first listview and the second variable from another listview.
In this listViewAnother I have many items, which has some "id". For example 1st, 5th and 20th elements have id 90 and other elements have id 100.
We can say, that items from the first listview also have "id".
So I must check if(first variable = second variable) and then show in listViewAnother only items that have id which equals ID from clicked item in listView.
I tried: adapterPr.remove(item2); but then I understood, that I need all of items because I can go back to listView and press another item which will need those removed elements.
Now, hope I provided full information and you will be able to help me improve my code.
Do you need to perform the check on every element of the adapter when you click on one element of the adapter? If not, you don't need a loop. If you do, your loop should be iterating over the original list, and does not need adapter position at all.
In general when using adapters and lists, you should use the adapter's position and the adapter's data set to perform any tasks. It's not good practice to use the adapter position to get an item from the original list.
Simply set one onItemClickListener which gets the corresponding item from the adapter, and do what you need to from there:
private List<SomeItem> items = new ArrayList();
//items were created
SomeAdapter adapter = new SomeAdapter(this, R.layout.list_item, items);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new android.widget.AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
SomeItem item = adapter.getItem(position);
String tmpCI = item.getFirstVariable();
String tmpPCI = item.getecondVariable();
if (!tmpCI.equals(tmpPCI)) {
//some code
} else {
Toast.makeText(EPG.this, "Variables are different", Toast.LENGTH_SHORT).show();
}
}
});

Android : loop through all items in a listview

Want to get quick answer how to list all items on my listview, in order to print out a list or share to a notepad app etc. That is, to get a variable with following information from the listview: "apple", "banana", "orange". Below is my listview. Thanks
String[] values = new String[] { "apple", "banana", "orange" };
listItems = new ArrayList<String>();
for (int i = 0; i < values.length; ++i) {
listItems.add(values[i]);
}
adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, android.R.id.text1,
listItems);
// Assign adapter to ListView
listView.setAdapter(adapter);
Your question says,
Loop through all items in a listview.
I understand from your code that you want to add the items from String array to ArrayList.
But, you can pass String array directly as a third parameter to your ArrayAdapter.
Look at the suggestions provided by Android studio for ArrayAdapter. You can pass String[] or ArrayList too :
Either you can pass String[] or if you wanted to loop through all String[] items to ArrayList, you can simply do by a single line.
Collections.addAll(arrayList,values);
arrayList - ArrayList
values - String[]
instead of,
listItems = new ArrayList<String>();
for (int i = 0; i < values.length; ++i) {
listItems.add(values[i]);
}
And in comment section, you said
I think I may add/remove item at a time to the listView later.
In this case, you can have some button to reload the list to show the old items + added new items or to show the list except the items which you've deleted. I'll add below how you have to achieve it.
Have a button AddMore in your layout and whenever you want to add new items, then do like this
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
arrayList.add("lemon"); // this adds item lemon to arraylist
arrayList.add("Pomgranete");
arrayAdapter.notifyDataSetChanged(); // this will refresh the listview and shows the newly added items too
}
});
You can delete the item similarly by passing the position of the item in arrayList,
arrayList.remove(arrayList.get(i)); // i is the position & note arrayList starts from 0
So, by summing up everything, here's the full working code :
public class MainActivity extends AppCompatActivity {
ListView listView;
String[] values = {"Apple", "Orange", "Banana"};
List<String> arrayList;
Button button;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ListView)findViewById(R.id.listView);
button = (Button)findViewById(R.id.button);
arrayList = new ArrayList<String>();
Collections.addAll(arrayList,values); // here you're copying all items from String[] to ArrayList
final ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,arrayList);
listView.setAdapter(arrayAdapter);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
arrayList.remove(arrayList.get(2)); // here i remove banana since it's position is two. My ordering of items is different so it removed banana. If i use ordering from your quest, it will remove orange.
arrayList.add("lemon"); // adding lemon to list
arrayList.add("Pomgranete"); // adding pomgranete
arrayAdapter.notifyDataSetChanged(); // this used to refresh the listView
}
});
}
}
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" tools:context=".MainActivity">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="ADD MORE"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:id="#+id/button" />
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/listView"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_above="#+id/button" />
</RelativeLayout>
Output :
List with pre-defined 3 items and one button to load more items.
List with old 3 items + newly added 2 items (Here i didn't use arrayList.remove)
List with old items except deleted item + newly added 2 items (Here i used arrayList.remove to remove banana by arrayList.remove(arrayList.get(2));)
As I understand you want to create an ArrayAdapter, later add a few items to it and at some point retrieve all items from it, right?
Since you use ArrayAdapter you can just iterate over its content:
String[] items = new String[adapter.getCount()];
for(int i = 0; i < adapter.getCount(); i++){
items[i] = adapter.getItem(i);
Log.d("TAG", "Item nr: " +i + " "+ adapter.getItem(i));
}
ArrayAdapter documentation
Since you already have an array AND an arraylist in your code it should be easy.
But if you want to loop later and you have only your listview, I believe there is a getter for the adapter in your listview, and if you cast the given adapter to ArrayAdapter, it should then have a getter to the the items you are looking for.
ArrayAdapter<String> adapter = (ArrayAdapter<String>)mListView.getAdapter();
for(int i=0; i<adapter.getCount();i++){
String item = adapter.getItem(i);
/*...*/
}
You don't need to loop or anything just pass the array directly to the adapter.
adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, android.R.id.text1,
values);
the new ArrayAdapter took an array as a third parameter.

How to remove item from adapter

I have a container, adapter, and couple items. I would like to save items into database one by one.
However, I have issue on getting next item from adapter and resize adapter.
So far I have the code below:
adapter.add(item[0]);
adapter.add(item[1]);
adapter.add(item[2]);
item = adaper.getItem(0);
item.setDismissListener(new Item.OnDimissedListener(){
#Override
public void save(){
1. save item to database, it works here
2. get next item, I do
item = adapter.removeFirst(); // this one returns null pointer exception.
}
}
container.setAdapter(adapter); // set adapter here
Do you guys have any idea?
I had a similar project where I stored strings in a SQLite database and users could add/delete/modify items. What I did was to temporarily store the list of items in an ArrayList<String> and then update the ListView adapter with adapter.notifyDataSetChanged(); when that ArrayList changes.
In your case, I'd try something like this:
// Create an ArrayList <String>
ArrayList<String> itemsArray = new ArrayList<String>();
itemsArray.add( YOUR_ITEMS_GO_HERE );
...
// add data in ArrayAdapter
adapter = new ArrayAdapter<String>(this, R.layout.list, itemsArray);
ListView dataList = (ListView) findViewById(R.id.list);
dataList.setAdapter(adapter);
// Perform your Save actions
// Delete the first item in the ArrayList
list.remove(0); // removes the first item
// Update the ListView
adapter.notifyDataSetChanged();
If you are not using Strings, replace <String> with your <Object Type>

How to delete the checked Items in a multiple choice listview

How to delete the checked Items in a multiple choice listview with a contextual action for deletion -
ArrayList<String> liveNames = new ArrayList<String>() {
{
add("dani");
add("john");
add("dave");
add("alen");
add("deno");
add("feliks");
add("jupi");
}
};
adapter = new ArrayAdapter(this,
android.R.layout.simple_list_item_multiple_choice, liveNames);
setListAdapter(adapter);
.......
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
lv = getListView();
// Respond to clicks on the actions in the CAB
switch (item.getItemId()) {
case R.id.item1:
if(lv.getCheckedItemCount() > 0){
removeItems = lv.getCheckedItemIds();
deleteSelectedItems(removeItems);
}
mode.finish(); // Action picked, so close the CAB
return true;
default:
return false;
}
}
now how should I implement it in the deleteSelectedItems(long[] delItms) method so that the selected item IDs from the ListView be deleted inside the "names" ArrayList. Please for some hints
I know that I can update the adapters list with
adapter.notifyDataSetChanged();
but how to get the positions of the items inside the listview with their IDs so I could just
name.remove(position) - but I have only the IDs.
Thanks
This method should do the trick for you, I guess:
/* returns item's position in ArrayList by ID */
public int getItemPositionById(int id)
{
for(int i = 0; i < names.size(); i++) {
if(names.get(i).getId() == id) {
return i; // if found item with specified id, return it's position
}
}
return -1; // didn't find item with specified id
}
Just call it for all the ids you have and store those positions somewhere. Then you can remove all items at those positions.
Anyway I could not retrieve the checked Ids with this method
removeItems = lv.getCheckedItemIds();
because the the adapter needs to have stable Ids ...or something like that
so I tried to retrieve the positions of checked items with
SparseBooleanArray checkedItemPositions = getListView().getCheckedItemPositions();
and then to delete them and update the arraylist and the adapter
public void removeSelectedItems(){
int count = lv.getCount();
SparseBooleanArray checkedItemPositions = getListView().getCheckedItemPositions();
for (int i=0;i<count;i++){
if(checkedItemPositions.get(i))
Log.e("TEST", liveNames.get(i));
liveNames.remove(i);
}
adapter.notifyDataSetChanged();
}
The problem is I suppose with the liveNames ArrayList which dynamically changes its element indexes every time I remove one element so the end results come wrong.
Here is a link of a discussion for this type of problem but without a solution -
How to get Selected items from Multi Select List View
HOW I SOLVED THE ISSUE:
Created a second ArrayList instance
Updated that ArrayList instance with the UNCHECKED items
added it to the my listadapter - here is the method
public void removeSelectedItems(){
updatedList = new ArrayList<String>(); //initialize the second ArrayList
int count = lv.getCount(); //number of my ListView items
SparseBooleanArray checkedItemPositions = getListView().getCheckedItemPositions();
for (int i=0;i < count;i++){
if(!checkedItemPositions.get(i))
updatedList.add(liveNames.get(i));
Log.e("TEST", liveNames.get(i));
}
adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_multiple_choice, updatedList);
setListAdapter(adapter);}
Hope it will be helpful :)

How to check a checkbox status inside a ListView on Android

I got on my code a listview with check boxes, but How can I check if the value of the checkbox?
I'm implementing a program with tabs, and one of the tabs has the ListView with checkboxes, the code is as follows:
spec = tabHost.newTabSpec(OPTS_TAB_TAG).setIndicator("Options",
res.getDrawable(R.drawable.ic_tab_options))
.setContent(new TabContentFactory()
{
public View createTabContent(String arg0)
{
DbAdapter databaseManager = new DbAdapter(BusTrackerBetaActivity.this);
databaseManager.open();
List<String> BusLinesList = new ArrayList<String>();
BusLinesList = databaseManager.toStringList(databaseManager.getAllBusLines(), 1);
String[] BusLinesArray = BusLinesList.toArray(new String[BusLinesList.size()]);
databaseManager.close();
ListView ls1 = new ListView(BusTrackerBetaActivity.this);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(
BusTrackerBetaActivity.this,
android.R.layout.simple_list_item_multiple_choice,
BusLinesArray);
ls1.setAdapter(adapter);
ls1.setOnCreateContextMenuListener(BusTrackerBetaActivity.this);
ls1.setItemsCanFocus(false);
ls1.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
return ls1;
}
});
It's working fine, acctually I got this way of implementing the list from some examples, but my question is: How can I check the value (true or false) of each checkbox?
You can use ListView's getCheckedItemPositions function to accomplish this. It will return a SparseBooleanArray object containing the checked status of each item in the ListView. Loop through the SparseBooleanArray to determine which items are checked.
You will need to keep a reference to your ListView object somewhere so that you can easily access it later when you need to determine checked item status.
SparseBooleanArray checkedItems = ls1.getCheckedItemPositions();
if (checkedItems != null)
for (int i = 0; i < checkedItems.size(); i++)
{
if (checkedItems.valueAt(i))
{
String s = ls1.getAdapter().getItem(checkedItems.keyAt(i)).toString();
//s contains your checked item, checkedItems.keyAt(i) is the index of the checked item
}
}

Categories

Resources