Selecting/Unselecting all items in a Listview - android

I am using a multi select listview in my application. Specifically the simple_list_item_activated_1.
I have some of code, a button, that will select all the listview items. I have some logic saying that if all the items are already selected then deselect all the items.
When I press the button the first time, it will select all the items in the list as expected. and when I press the button a second time it deselects all the items as expected.
Here is my problem:
When I press the button for a third time "selectedCount" still equals "childCount". So obviously my code will never enter the If statement.
Would anyone know why this is happening? or maybe there is a better way to do what im trying to achieve?
int childCount = officerList.getChildCount();
int selectedCount = officerList.getCheckedItemPositions().size();
if(childCount != selectedCount){
for (int i = 0; i < officerList.getChildCount(); i++) {
officerList.setItemChecked(i, true);
}
}else{
for (int i = 0; i < officerList.getChildCount(); i++) {
officerList.setItemChecked(i, false);
}
}
}

Try this logic, it will check all the items if none of the items are checked, else will check only the items which are unchecked and vice versa.
public void onClick(View v) {
SparseBooleanArray sparseBooleanArray = officerList.getCheckedItemPositions();
if(sparseBooleanArray != null && sparseBooleanArray.size() >0) {
for (int index = 0; index < sparseBooleanArray.size(); index++) {
if(sparseBooleanArray.valueAt(index)){
officerList.setItemChecked(sparseBooleanArray.keyAt(index),true);
}
else {
officerList.setItemChecked(sparseBooleanArray.keyAt(index),false);
}
}
}
else {
for (int index = 0; index < officerList.getCount(); index++) {
officerList.setItemChecked(index,true);
}
}
}

I managed to answer my own question. Using getCheckItemPositions().size() is an unreliable way of achieving what I want.
This will return a sparseBooleanArray() of all Items checked, so the first time it works correctly as initially there is nothing selected so it will return 0. Then once everything is selected the sparseBooleanArray will be equal to all the items in the list as they were all selected.
However as I learned spareBooleanArray is an Array that stores the position and a Boolean flag of if it is selected or not. In my scenario when I press the select all button for the third, the size of the array is still equal to number of list items.
How I have fixed my issue, is to use getCheckedItemCount() which only returns the number of selected items as I originally wanted. hopefully this answer will help someone else.
int childCount = officerList.getChildCount();
int selectedCount = officerList.getCheckedItemCount();
if(childCount != selectedCount){
for (int i = 0; i < officerList.getChildCount(); i++) {
officerList.setItemChecked(i, true);
}
}else{
for (int i = 0; i < officerList.getChildCount(); i++) {
officerList.setItemChecked(i, false);
}
}
}

Related

SparseBooleanArray and 2 arraylists, item not removed from arraylist

I have a listview from which I remove selected items, I am doing this through a SparseBooleanArray.
However when I remove the selected items, I also want them removed from that position from 2 other arraylists (trackedItems, dateWatchList) but in the dateWatchList arraylist always 1 item it not removed.
I already checked several threads but I cannot get this right.
Would be great if someone can help.
Code piece:
...
SparseBooleanArray checkedItems = lv.getCheckedItemPositions();
for (int i = 0; i < adapter.getCount(); i++) {
if (checkedItems.get(i)) {
// This item is checked and can be removed
trackedItems.remove(i);
dateWatchList.remove(i); // 1 item always remains and is NOT removed?
adapter.remove(adapter.getItem(i));
}
}
checkedItems.clear();
adapter.notifyDataSetChanged();
...
I solved it myself, for anyone who has the same problem, here is my working code:
SparseBooleanArray checkedItems = lv.getCheckedItemPositions();
for (int i = checkedItems.size()-1; i >= 0; i--) {
String selecteditem = adapter.getItem(checkedItems.keyAt(i));
String currentName = trackedItems.get(checkedItems.keyAt(i));
long currentDate = dateWatchList.get(checkedItems.keyAt(i));
if (checkedItems.get(checkedItems.keyAt(i))) {
adapter.remove(selecteditem);
trackedItems.remove(currentName);
dateWatchList.remove(currentDate);
}
}
checkedItems.clear();
adapter.notifyDataSetChanged();

MultiSelect List View not detecting unchecked fields on android

I have a multiSelec listView fills with days. I´m getting the items selected, my problem is when I click in one list field in order to unselect it. An example:
I check the position 1,2,3,4,5 on the list and after that I uncheck the 4,5 position , so finally I have 3 fields checked.
With my code I get 5 values checked instead 3 .
¿Can anyone help me?
What I'm doing wrong?
private void gettingDaysChecked(){
boolean isSomethingChecked = false;
SparseBooleanArray checked = mListView.getCheckedItemPositions();
Log.d(Constants.TAG,"cheched size is "+checked.size() );
if (checked.size()>0)
isSomethingChecked=true;
if (isSomethingChecked) {
for (int i = 0; i < checked.size(); i++) {
int positionItem = checked.keyAt(i);
Log.d(Constants.TAG, "in position" + positionItem);
localList.add(positionItem);
}
app.setDaysCheckedFilterPeriod(localList);
}else if(!isSomethingChecked){
Log.d(Constants.TAG,"nothing checked ");
}
}

listview with multiple_choice problem

SparseBooleanArray selectedItem=catogoryList.getCheckedItemPositions();
for(int i=0;i<selectedItem.size();i++)
{
System.out.println("Array val:"+selectedItem.valueAt(i));
if(selectedItem.valueAt(i))
{
if(temp.contains(list.get(position)))
{}
else
temp.add(list.get(position));
}
else
{
temp.remove(list.get(position));
}
}
I use listview with multiple_choice (listview with checkbox) when i get items in listview that is checked with out scrolling i received correct values if i scroll the listview i don't get correct values. i found that selectedItem.valueAt(i) i get false when i check the items while scrolling. i don't know why false value is returned instead of true value.
How do you obtain your values? This process should be like this:
SparseBooleanArray checked = getCheckedItemPositions();
List<String> checkedResult = new ArrayList<String>();
for (int i = 0; i < checked.size(); i++) {
if (checked.valueAt(i)) {
checkedResult.add(getAdapter().getItem(checked.keyAt(i)).toString());
}
}
return checkedResult;

Encountered IndexOutOfBoundException while removing items from ListView in Android?

I have one simple_list_item_multiple_choice listview in my layout and i am trying to remove all the selected items from it. I know how to delete it but i am having two major problems while deleting the items :-
My program isn't deleting more than 2 items like if i selected 4 items then only 2 will be deleted and sometime its even deleting the wrong items.
When i debug my code i found Array IndexOutOfBoundException in my code and as far as i know there is no exception like this in my code and its all because of deleting the wrong or less items.
here is my code:-
public void onClick(View view)
{
SparseBooleanArray checkedPositions = new SparseBooleanArray();
checkedPositions.clear();
checkedPositions = lv.getCheckedItemPositions();
int size = checkedPositions.size();
if(size != 0)
{
try
{
for(int i = 0; i < size; i++)
{
if(checkedPositions.valueAt(i))
{
list.remove(checkedPositions.keyAt(i));
notes.notifyDataSetChanged();
lv.setItemChecked(i,false);
}
}}catch (IndexOutOfBoundsException ie)
{}
}
else{}
}
I caught the exception only for debugging purpose. Thanks in advance but please help because i am stuck at this part since last two days.
Each time you remove an item from the array at the lower lever, the total count is being reduced by 1. If you had 4 items to remove [ 0, 1, 2, 3], and you remove items starting with item 0, you have [0, 1, 2], then you remove item at 1, and you have [0, 1], if you try to remove item at index 2 which does not exist you will get an error. Try count down instead of up like this
for(int i = size; i > 0; --i)
{
if(checkedPositions.valueAt(i))
{
list.remove(checkedPositions.keyAt(i));
notes.notifyDataSetChanged();
lv.setItemChecked(i,false);
}
}
for(int i = size-1 ; i >= 0; i--)
{
if(checkedPositions.valueAt(i))
{
list.remove(checkedPositions.keyAt(i));
//lv.setItemChecked(checkedPositions.keyAt(i),false);
}
}
notes.notifyDataSetChanged();
From the look of it, you should change this
for(int i = 0; i <= size; i++)
to
for(int i = 0; i < size; i++)

How to get Selected items from Multi Select List View

I am using an array adapter and to this am adding an array list of string s , the list is multi select , How can i get the values of list items clicked ?
my_contacts_list.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
ArrayAdapter<String> adapter=new ArrayAdapter<String>(this, android.R.layout.simple_list_item_multiple_choice,conts_list);
my_contacts_list.setAdapter(adapter);
I was trying to do this ,
SparseBooleanArray positions = my_contacts_list.getCheckedItemPositions();
int size=positions.size();
int i=0;
while(i <= size){
conts_list.get(positions.get(i));
i++;
}
But position.get(i) is an array list , how to retrieve the selected items then ?
SparseBooleanArray.get returns a boolean, but I believe you need to check it for each position in your list, e.g.
int len = listView.getCount();
SparseBooleanArray checked = listView.getCheckedItemPositions();
for (int i = 0; i < len; i++)
if (checked.get(i)) {
String item = cont_list.get(i);
/* do whatever you want with the checked item */
}
This API is a mess. Here is what works for me.
SparseBooleanArray checked = tags.getCheckedItemPositions();
for (int i = 0; i < checked.size(); i++) {
if(checked.valueAt(i)) {
Tag tag = (Tag) tags.getItemAtPosition(checked.keyAt(i));
Log.i("xxxx", i + " " + tag);
}
}
I believe the fastest way to get the info out of this SparseArray is to iterate over the keys (actually I'm fairly sure that the solutions above won't work in all cases). The ListView will enter a pair (index, true) into the SparseBooleanArray for every selected index.
So the code might look like this:
SparseBooleanArray checked = lv.getCheckedItemPositions();
int size = checked.size(); // number of name-value pairs in the array
for (int i = 0; i < size; i++) {
int key = checked.keyAt(i);
boolean value = checked.get(key);
if (value)
doSomethingWithSelectedIndex(key);
}
I think the Answer from Daren Robbins is Wrong, here is my answer:
ArrayList<String> ids = extras.getStringArrayList("commonids");
SparseBooleanArray checked = lv.getCheckedItemPositions();
for (int i = 0; i < checked.size(); i++) {
if(checked.get(i))
Log.i("CheckedItem", ids.get(checked.indexOfKey(i)));
}
Assume ids is an arraylist with the same size of the listview containing the ids of the items in the list view
The thing is you must iterate all the list view items but not checkedPositions.
Define the variables:
listView (The instance of you ListView)
names (the ArrayList you are )
saveCheckedName (save all checked name to this Arraylist)
SparseBooleanArray checkedPositions = listView.getCheckedItemPositions();
for (int i = 0; i < subjectListView.getCount(); i++) {
if (checkedPositions.get(i) == true) {
saveCheckedName.add(names.get(i));
}
}
Like so many other things, multi-select ListViews are a real problem in Android.
Instead of simply requesting the selected items as a List of Objects (dear Google, this is what we expect):
List selected_items = my_list_view.getSelectedItems();
we are forced to use this stupendously ridiculous API:
SparseBooleanArray checked = my_list_view.getCheckedItemPositions();
int num_selected = 0;
for(int i = 0; i < checked.size(); i++) {
if(checked.valueAt(i)) {
num_selected++;
int key = checked.keyAt(i);
boolean value = checked.get(key);
if (value) {
//
}
}
}
The horribly named SparseBooleanArray is populated by calling the even more horribly named getCheckedItemPositions() on the ListView. But instead of returning the positions of each selected/checked item in the list, it returns the position of every item in the list that WAS EVER touched, whether it is currently actually selected or not! Unbelievable, but true.
To calculate whether the item is ACTUALLY CURRENTLY checked, we are forced to test valueAt(i) for truthiness while looping through the 'was ever touched' array of items.
In addition to this madness, if we want to calculate the number of selected items, we appear to be forced to increment our own counter (e.g. num_selected).
With APIs like this one, it's little wonder developers are an angry lot!
I think another option is to just keep track of all of this yourself.
list.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> listView, View selectedItem,
int position, long itemId) {
//Keep a reference here, and toggle a global variable.
HOW I SOLVED THE ISSUE with a second ArrayList :
Created a second ArrayList instance
Updated that ArrayList instance with the UNCHECKED items
added it to the my listadapter
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)); //liveNames is the current ArrayList
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 helpfull :)
Foo objectAtCheckedRow = null;
for (int i = 0; i < positions.size(); i++) { //positions.size() == 2
objectAtCheckedRow = adapter.getItem(positions.keyAt(i));
//Do something significant with object here
}
A couple things to understand
It's a key-value pair list.
The key is the index of a row, get it with positions.keyAt(i)
The value is whether the row at that index is checked or not(true or false), get it with positions.valueAt(i)
positions.get(i) returns the same boolean as .valueAt(i)
Careful not to get indexes mixed up. You do not need to(and should not) iterate over your whole list. Use int i to iterate over positions, but don't use i to get objects from your list
But in this specific case(listView.getCheckedPositions()) it only fills in true(checked rows), so you don't actually need to verify using .get(i) nor .valueAt(i)
Example:
Let's say you've checked the 5th and 8th items in the list(index 4 and 7), then positions.size() == 2 and i will be 0 and then 1
So when:
i == 0 then keyAt(i) == 4
i == 1 then keyAt(i) == 7
i == 0 OR i == 1 then valueAt(i) == true AND get(i) == true
FYI, Here is how Google did it:
Excerpted from http://mytracks.googlecode.com/hg/MyTracks/src/com/google/android/apps/mytracks/util/Api11Adapter.java
/**
* Gets the checked positions in a list view.
*
* #param list the list view
*/
private int[] getCheckedPositions(ListView list) {
SparseBooleanArray positions = list.getCheckedItemPositions();
ArrayList<Integer> arrayList = new ArrayList<Integer>();
for (int i = 0; i < positions.size(); i++) {
int key = positions.keyAt(i);
if (positions.valueAt(i)) {
arrayList.add(key);
}
}
int[] result = new int[arrayList.size()];
for (int i = 0; i < arrayList.size(); i++) {
result[i] = arrayList.get(i);
}
return result;
}
and here is my adapted version:
public static List<Integer> getAbsListViewCheckedItemPositions(AbsListView absListView) {
SparseBooleanArray checked = absListView.getCheckedItemPositions();
List<Integer> positions = new ArrayList<>();
int checkedSize = checked.size();
for (int i = 0; i < checkedSize; i++) {
if (checked.valueAt(i)) {
positions.add(checked.keyAt(i));
}
}
return positions;
}
We use this in our Android utility class. The generics help prevent compiler warnings, but you can remove them if your adapter returns multiple types.
public static <T> Collection<T> getCheckedItems(ListView listView) {
Collection<T> ret = new ArrayList();
SparseBooleanArray checkedItemPositions = listView.getCheckedItemPositions();
for (int i = 0; i < checkedItemPositions.size(); i++) {
if (checkedItemPositions.valueAt(i)) {
T item = (T) listView.getAdapter().getItem(checkedItemPositions.keyAt(i));
ret.add(item);
}
}
return ret;
}
Very simple, use below code
listViewRequests.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
AppCompatCheckedTextView checkBox = (AppCompatCheckedTextView) view;
if (checkBox.isChecked() == true){
Log.i("CHECK",checkBox.isChecked()+""+checkBox.getText().toString());
}
}
});
for(int i =0; i< listView.getAdapter().getCount(); i++){
if(listView.isItemChecked(i)){
listView.getAdapter().getItem(i); // item
}
}
should be used after setAdapter() method

Categories

Resources