ExpandableListView duplicating checkbox check - android

hi I am using ExpandableListview in android. My requirement is, at a time one group plus its child group must selected(using check boxes). If I go for another group then the previously selected group should get unchecked.
But From my code when I check first group automatically the last group will check. This is my issue and below is my code. Thanks in advance.
listView.setOnGroupClickListener(new OnGroupClickListener() {
#Override
public boolean onGroupClick(ExpandableListView parent, View v,
int groupPosition, long id) {
CheckBox last = holder.groupCHeck;
CheckBox current = (CheckBox) v
.findViewById(R.id.groupCheckBox);
last.setChecked(false);
current.setChecked(true);
if (listExpandedPosition.size() >= 1) {
if (listExpandedPosition.get(0) != groupPosition) {
listView.collapseGroupWithAnimation(listExpandedPosition
.get(0));
last.setChecked(false);
}
} else {
}
if (listView.isGroupExpanded(groupPosition)) {
listView.collapseGroupWithAnimation(groupPosition);
} else {
listView.expandGroupWithAnimation(groupPosition);
}
if (!listExpandedPosition.isEmpty())
listExpandedPosition.clear();
listExpandedPosition.add(groupPosition);
holder.groupCHeck = current;
return true;
}
});

This is a common issue that usually happens with listview,expandable listview and gridview.These widgets doesn't maintain states of checked checkbox.
Have a look at this example,you will get the idea how to deal with that...
http://lalit3686.blogspot.in/2012/06/today-i-am-going-to-show-how-to-deal.html

Make a SparseBooleanArray or Arraylist and hold Checked and Unchecked states in the array itself and set it accordingly, Or if you are using a custom Java Pojo/Object add another field for getting setting a boolean for checked/unchecked state. This is a common scenario because AdapterView recycle views and items for saving memory.

Related

Expandable listview not to select rows

i checked the documentation & tried few ways to disable the click of group items of expandable listview. None came to use.
There is a method isChildSelectable in Expandablelistadapter. But not isGroupSelectable. I tried manyways like disabling the click of list item etc.. no luck. I want to disable the click of certain listview group items.
expandableList.setOnGroupClickListener(new OnGroupClickListener() {
#Override
public boolean onGroupClick(ExpandableListView parent,
View childView, int groupPosition, long id) {
if (groupPosition == desirePosition) {// give your condition here
//temporary condition is given
return true; // the expander cannot be collapsed
}
return false;
}
});

How to disable all elements (also the ones not currently visible in the screen) in a listview?

I have a ListView with a set of elements. When I click one of the I would like to disable all the others. If I click again on the selected item all the other items are enabled again.
I tried the different proposed solution without success. I hope someone can help me.
This is my code:
//action to take when a presentation is selected
listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, final View view,
int position, long id) {
//disable the other items when one is selected
if(position!=selectedPresentation){
for(int i=0;i<parent.getCount();i++){
if(i!=position)//disable all the items except the select one
parent.getChildAt(i).setEnabled(false);
}
selectedPresentation=position;
}else if(selectedPresentation==position){
//enable again all the items
for(int i=0;i<parent.getCount();i++){
parent.getChildAt(i).setEnabled(true);
}
selectedPresentation=-1;
}
Where selectedPresentation is a global variable storing the selected item. If no item is selected its value is -1.
Thank you for your help!
Make your own subclass of ArrayAdapter that has AreAllItemsEnabled() return false, and define isEnabled(int position) to return false for a given item in your the ones you want to disable.
In your custom ArrayAdapter overide isEnabled method as following
#Override
public boolean isEnabled(int position) {
return false;
}
other option
Don't implement onItemclickListener. This will not give you any update of item click. Only register onClick listener to views.
You may take another object of the List(Arraylist) which is populating elements in listview then on click copy the corresponding position data to new arraylist you made and then notifyDataSet and when you click again you populate listview with original list so it will apear again....Just do this trick it might work for you
parent.getChildeAt() only work for visible Item.
you should change something in adapter.
if make custom adapter then you can do some thing like #ṁᾶƔƏň ツ answer, but if you use default adapter you can change adapter's arraylist that before you pass it to adapter.
put boolean in it (in arraylist) and in on item click true/false it for all item.
I wrote this solution and seems it works fine!
listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, final View view,
int position, long id) {
//disable the other items when one is selected
Toast.makeText(context, "onClick called",Toast.LENGTH_SHORT).show(); // this will flash up twice
if(position!=selectedPresentation){
selectedPresentation=position;
for(int i=0;i<adapter.getCount();i++){
if(i!=position)//disable all the items except the select one
adapter.isEnabled(i);
}
}else if(selectedPresentation==position){
//enable again all the items
selectedPresentation=-1;
for(int i=0;i<adapter.getCount();i++){
adapter.isEnabled(i);
}
}
And in my adapter I wrote:
public boolean isEnabled(int position) {
if(selectedPresentation==-1 || selectedPresentation==position)
return true;
return false;
Now my concern is how to show the items in the listView as disabled

ListeView recycling Views causing problems

When I click a list item, every 12th item is also selected. ListViews recycle views and therefore many items are being selected, any idea how I overcome the problem so just the items I click are marked as checked.
#Override
public void onListItemClick(ListView l, View v, int position, long id){
CheckedTextView check = (CheckedTextView) v;
if (check.isChecked()){
check.setChecked(false);
selections.remove((Integer) position);
}
else{
check.setChecked(true);
selections.add((Integer) position);
}
}
I use an ArrayAdapter. Names is a String[] of about 1000 options.
adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_multiple_choice, names);
setListAdapter(adapter);
As this answer CheckBox in ListView says maintain a list of your checked items and then check your CheckBox in getView based on that list.
Also set the onCheckedChangeListener for that CheckBox null before checking it or else the corresponding listener will be called.
In lisview, recycling is very tricky concept, first by recycled view android means view which were used earlier, so basically this view will contain all the parameter which you or user set earlier.
This view is now returned to your adapter, what you do is to check if its null inflate a new view set new values supply it back, if its not then refresh the widgets view contains with new values and then supply it back.
Now coming back to your code, you are simply checking if this view was checked or not, say suppose you checked first view in you list, now when you scroll down further this same view will be returned to you through recycling and guess what it will be checked again, remember it was the same first view you used, this is reason for your problem for founding a unchecked view checked.
Now to your resolution, maintain a separate list somewhere globally to hold on checked index, and from your adapter just check or uncheck the checkbox before sending it to list depending about its index presence in maintained list. this will resolve your probelm.
Please try something like this.
-- Have a static HashMap on your main activity.
--Implement two methods over you activity, AddSelection and RemoveSelection
--On your adapter, implement onCheckedStateChanged listener and, perform either addition or deletion from the map, based on position in list.
In Your Activity:
private static HashMap<Integer,Integer> selectedPositions = new HashMap<Integer,Integer>();
public static boolean isSelected(int position){
System.out.println("#### Position: " + position + " Value: " + selectedPositions.containsKey(position));
return selectedPositions.containsKey(position);
}
public static void addSelection(int position){
System.out.println("#### Puttin Position: " + position);
selectedPositions.put(position,position);
}
public static void removeSelection(int position){
System.out.println("#### Removing Position: " + position);
selectedPositions.remove(position);
}
In your adapter:
checkbox.setChecked(MainActivity.isSelected(position));
checkbox.setOnCheckedChangeListener(new OnCheckedChangeListener(){
#Override
public void onCheckedChanged(CompoundButton view, boolean state) {
// TODO Auto-generated method stub
if(state == true){
MainActivity.addSelection(position);
}else{
MainActivity.removeSelection(position);
}
}
});
thats it now, whenever you want iterate through the hasmap for finding out selected items, make sure you clear it when job is done, else u will end up piling selected positions again and again.

Android Multiple Choice List SQLite

How can i save the info from a multiple choice listview into the database? I want to save the status of a item from a list. For instance, if i have 2 items checked i want to save this status in the database.
Thanks
Sure fegol,
I assume you already set up the multiple choice listview. (if not, please check online there are heaps of them http://www.androidpeople.com/android-listview-multiple-choice-example).
Here I'd like to give you some hint on data-saving problem.
Basically, there are two common choices. The first is to use getCheckedItemIds() or getCheckedItemPositions() on your listview (http://developer.android.com/reference/android/widget/AbsListView.html#getCheckedItemIds()).
The second one which is more flexible is to write a custom adapter. You can use isChecked() to check whether the checkbox was checked, and then save the status into your hashmap. Then you can get all status of checkboxes at the last.
I put some pseudo-code for the second approach for you. Hope this helps.
ArrayList<Boolean> checkList = new ArrayList<Boolean>();
// TODO: put some empty data into checkList
private OnItemClickListener myListItemClickListener = new ListView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View v, int position, long id) {
if(checkList.get(position)){
checkList.set(position, false);
}else{
checkList.set(position, true);
}
((mAdapter)mList.getAdapter()).notifyDataSetChanged();
}
}
class mAdapter extends BaseAdapter{
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (checkList.get(position)){
checkBox.setChecked(true);
}else{
checkBox.setChecked(false);
}
}
}

get correct values in childcursor for clicked group

I can use SimpleCursorTreeAdapter to create ExpandableListView with correct groupcursors and childcursors. For my program, each child contains three TextViews. When I expand group and click on child, I use custom dialog to show the three values in EditText view.
The program is ok if I only open "ONE" group at a time. I can get correct child values if clicked. But if I expand several groups at the same time. It only shows the latest children under latest group.
For example: Group A has 3 items, Group B has 5 items, Group C has 2 items. First I clicked on children under Group A, no problem, then children under Group B, no problem, but if I go back to click children under Group A, it still shows child under Group B. I don't know how can show correct children. If I use Toast to display, all children are correct, so strange. What can I do in this methods ?
epView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener()
{
#Override
public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long row)
{
return false;
}
});
epView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
#Override
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id)
{
int tempid = childcursor.getInt(0);
String temp1 = childcursor.getString(1);
String temp2 = childcursor.getString(2);
String temp3 = childcursor.getString(3);
CustomDialog custom = new CustomDialog(ListCateActivity.this,catecursor,childcursor,temp1,temp2,temp3,tempid);
custom.setTitle("Record Information");
custom.show();
Toast.makeText(ListCateActivity.this, "Group:"+String.valueOf(groupPosition).toString()+" Child: "+String.valueOf(childPosition).toString()+temp1+" "+temp2+" "+temp3, Toast.LENGTH_SHORT).show();
return true;
}
});
thanks !!
Finally I know what happened to my code now, but it is so strange. As I define childcursor in getChildrenCursor method. It should be inherited as I define childcursor as instance variable, so it can be shared among the class. Anyway, Java and Android is interesting. But when you are stuck with unexpected result, you need to debug to find out what the problem is.

Categories

Resources