CheckBox gets unchecked on scroll in a custom listview - android

I know that this question has been asked over and over again but still I've not been a able to find a suggestion that really helps me. The checkbox is unchecked whenever the list is scrolled down. Yes I'm using a boolean array to store the values but this still doesn't fix the problem. Here is my code. Please suggest a solution for this. Thank you.
public View getView(final int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
final ViewHolder holder;
final boolean[] itemChecked=new boolean[30];
LayoutInflater inflater = context.getLayoutInflater();
if(convertView==null)
{
convertView = inflater.inflate(R.layout.custom_list, null);
holder = new ViewHolder();
holder.txtViewTitle = (TextView) convertView.findViewById(R.id.title_text);
holder.txtViewDescription = (TextView) convertView.findViewById(R.id.description_text);
holder.cb=(CheckBox) convertView.findViewById(R.id.cb);
convertView.setTag(holder);
}
else
{
holder=(ViewHolder)convertView.getTag();
}
holder.cb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
// TODO Auto-generated method stub
itemChecked[position] = isChecked;
if(itemChecked[position])
{
holder.cb.setChecked(true);
}
else
{
holder.cb.setChecked(false);
}
holder.txtViewTitle.setText(title[position]);
holder.txtViewDescription.setText(description[position]);
holder.cb.setChecked(itemChecked[position]);
holder.txtViewDescription.setFocusable(false);
holder.txtViewTitle.setFocusable(false);
return convertView;
}
}

getView() is called whenever a previously invisible list item needs to be drawn. Since you recreate itemChecked[] each time this method is called you will have the new checkbox unchecked and a different Array for each resulting View. (final in Java does not make that field unique like in C)
Simplest way to solve that is to make itemChecked a classmember and set / restore checkbox state based on that one.
public class MyListAdapter extends ArrayAdapter<Object> {
private final boolean[] mCheckedState;
private final Context mContext;
public MyListAdapter(Context context, int resource, int textViewResourceId, List<Object> objects) {
super(context, resource, textViewResourceId, objects);
mCheckedState = new boolean[objects.size()];
mContext = context;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// simplified to just a Checkbox
// ViewHolder and OnCheckedChangeListener stuff left out
CheckBox result = (CheckBox)convertView;
if (result == null) {
result = new CheckBox(mContext);
}
result.setChecked(mCheckedState[position]);
return result;
}
}

Here is an example. Read the comments in the getView(...)
of the adapter provided below.
class TaskObject {
private int pid;
private String processName;
private boolean toKill;
///getters/setters
public boolean isToKill() {
return toKill;
}
public void setToKill(boolean toKill) {
this.toKill = toKill;
}
................................
}
class TaskListAdapter extends BaseAdapter {
private static final String TAG = "adapter";
ArrayList<TaskObject> list;
Context context;
public TaskListAdapter(Context context) {
Log.d(TAG, "created new task list adapter");
this.context = context;
if (list == null) {
list = new ArrayList<TaskObject>();
}
}
public void addTask(TaskObject taskObject) {
list.add(taskObject);
}
public void clearTasks() {
list.clear();
Log.d(TAG, "list size:" + list.size());
this.notifyDataSetChanged();
}
public int getCount() {
return list.size();
}
public TaskObject getItem(int position) {
return list.get(position);
}
public long getItemId(int position) {
return position;
}
public View getView(final int position, View convertView, ViewGroup parent) {
RelativeLayout rl = new RelativeLayout(context);
TextView textPid = new TextView(context);
textPid.setText(Integer.toString(getItem(position).getPid()));
TextView textName = new TextView(context);
textName.setText(getItem(position).getProcessName());
/////Here is your and it will set back your checked item after scroll
CheckBox chckKill = new CheckBox(context);
if(getItem(position).isToKill())
{
chckKill.setChecked(true);
}
////////////////////////////////////////////////////////////////////
chckKill.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
//is chkIos checked?
if (((CheckBox) v).isChecked()) {
getItem(position).setToKill(true);
}
}
});
chckKill.setTag(getItem(position).getPid());
/////////NOT LAYOUTED USE LAYOUT
rl.addView(chckKill);
rl.addView(textName);
rl.addView(textPid);
return rl;
}
hope it helps abit.

In mycase, I solved this issue as follows :
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
TextView title = null;
ImageView thumbnail = null;
CheckBox checkBox = null;
Content rowData = GridViewActivity.contents.get(position);
if (null == convertView) {
convertView = mInflater.inflate(R.layout.grid_item, null);
holder = new ViewHolder(convertView);
convertView.setTag(holder);
}
holder = (ViewHolder) convertView.getTag();
title = holder.getContentTitle();
title.setText(rowData.getTitle());
thumbnail = holder.getThumbnail();
thumbnail.setImageResource(rowData.getIcon());
checkBox = holder.getCheckBox();
checkBox.setTag(position);
checkBox.setChecked(rowData.isCheckBox());
checkBox.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
int getPosition = (Integer) buttonView.getTag();
GridViewActivity.notifyCheckChanges(getPosition,
buttonView.isChecked());
}
});
return convertView;
}

You should place setChecked() after setOnCheckedChangeListener().

Related

Select only one checkbox/radiobutton in the same row and column with Two checkbox/Radio button in a row using Listview Android

I have used Customized Listview using Adapter class in the Adapter class Two checkbox in a ROW For this I need Select Only one check box Either Checkbox1 Row/Column same as Checkbox 2.
For Example I have 5 rows in a Listview Totally 10 Checkbox inside Listview Out 10 Only one select at a Time all Other should unselect
Any idea About that I tried Lot but select only Checkbox1 column only
Please help
public class ListViewAdapter extends ArrayAdapter<Friend> {
private List<Friend> myFriends;
private Activity activity;
private int selectedPosition = -1;
String flag="";
String[]ids=new String[100];
String[]ids1=new String[100];
public ListViewAdapter(Activity context, int resource, List<Friend> objects) {
super(context, resource, objects);
this.activity = context;
this.myFriends = objects;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
LayoutInflater inflater = (LayoutInflater) activity.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
// If holder not exist then locate all view from UI file.
if (convertView == null) {
// inflate UI from XML file
convertView = inflater.inflate(R.layout.item_listview, parent, false);
// get all UI view
holder = new ViewHolder(convertView);
// set tag for holder
convertView.setTag(holder);
} else {
// if holder created, get tag from view
holder = (ViewHolder) convertView.getTag();
}
holder.checkBox.setTag(position); // This line is important.
holder.checkBox1.setTag(position + 100);
holder.friendName.setText(getItem(position).getName());
holder.rdgrp.setTag(position);
ids[position]=holder.checkBox.getTag().toString();
ids1[position]=holder.rdgrp.getTag().toString();
// System.out.println("praveen"+ids[position]);
if (position == selectedPosition) {
holder.rdgrp.setActivated(true);
} else holder.rdgrp.setActivated(false);
if( holder.checkBox.getTag().equles(position)){
holder.checkBox.setOnClickListener(onStateChangedListener(holder.checkBox, position));
}else{
holder.checkBox1.setOnClickListener(onStateChangedListener(holder.checkBox1, position));
}
return convertView;
}
public View.OnClickListener onStateChangedListener(final RadioGroup gry, final int position ){
return new View.OnClickListener() {
#Override
public void onClick(View v) {
if (gry.isClickable()) {
selectedPosition = position;
} else {
selectedPosition = -1;
}
notifyDataSetChanged();
}
};
}
private static class ViewHolder {
private TextView friendName;
private CheckBox checkBox,checkBox1;
public ViewHolder(View v) {
checkBox = (CheckBox) v.findViewById(R.id.check);
checkBox1 = (CheckBox) v.findViewById(R.id.check1);
friendName = (TextView) v.findViewById(R.id.name);
}
}
}
you can use group for check box of a single row of list view which has two check box and then apply following line of code
"listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE)"
Try with following code:
public class CustomAdapter extends BaseAdapter{
int selectedPosition = -1; // row position
int selectedCheckbox = -1; // 1 for 1st, 2 for 2nd on each row
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if(position == selectedPosition){
if(selectedCheckbox == 1){
checkbox1.setChecked(true);
checkbox2.setChecked(false);
} else if(selectedCheckbox == 2){
chkbox1.setChecked(false);
chkbox2.setChecked(true);
}
} else{
checkbox1.setChecked(false);
checkbox2.setChecked(false);
}
checkbox1.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(isChecked){
selectedPosition = position;
selectedCheckbox = 1;
} else{
selectedPosition = -1;
selectedCheckbox = -1;
}
notifyDataSetChanged();
}
});
checkbox2.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(isChecked){
selectedPosition = position;
selectedCheckbox = 2;
} else{
selectedPosition = -1;
selectedCheckbox = -1;
}
notifyDataSetChanged();
}
});
return convertView;
}
}
Hope, it will help you!

Checkbox in Spinner adapter is automatically checked when I scroll it

What I have: I have a spinner, foe which I have set the adapter, the adapter displayed in coed below has a checkbox and a textview
What is happening:: When I check the checkbox in one row and scroll below, some item in the below adapter is checked automatically. also when i scroll back up the adapter i checked also remained checked
What I am trying to do::
How can I preserve the proper selection of checkbox in the adapter all teh time. when i scroll up and down
AdptCategories.java
public class AdptCategories extends BaseAdapter {
ArrayList<HashMap<String, String>> categorySpinnerData;
Context context;
//ArrayList<ListObject> objects;
public AdptCategories(ArrayList<HashMap<String, String>> _categorySpinnerData, Context _context) {
super();
context=_context;
categorySpinnerData=_categorySpinnerData;
}
#Override
public int getCount() {
return categorySpinnerData.size();
}
#Override
public Object getItem(int position) {
return categorySpinnerData.get(position);
}
#Override
public long getItemId(int position) {
return 0;
}
public View getView(int position, View convertView, ViewGroup parent) {
HashMap<String, String> mapData=categorySpinnerData.get(position);
if (convertView == null) {
LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
convertView = mInflater.inflate(R.layout.adpt_categories_spinner, null);
}
TextView txtCategoryNameId = (TextView) convertView.findViewById(R.id.txtCategoryNameId);
CheckBox categoryChkBxId = (CheckBox)convertView.findViewById(R.id.categoryChkBxId);
if(position==0){
txtCategoryNameId.setText(mapData.get("name"));
categoryChkBxId.setVisibility(View.INVISIBLE);
}else{
txtCategoryNameId.setText(mapData.get("name"));
txtCategoryNameId.setTag(mapData.get("id"));
categoryChkBxId.setVisibility(View.VISIBLE);
}
return convertView;
}
}
{EDIT}
public class AdptCategories extends BaseAdapter {
ArrayList<HashMap<String, String>> categorySpinnerData;
Context context;
private ArrayList<Boolean> checked = new ArrayList<Boolean>();
//ArrayList<ListObject> objects;
public AdptCategories(ArrayList<HashMap<String, String>> _categorySpinnerData, Context _context) {
super();
context=_context;
categorySpinnerData=_categorySpinnerData;
}
#Override
public int getCount() {
return categorySpinnerData.size();
}
#Override
public Object getItem(int position) {
return categorySpinnerData.get(position);
}
#Override
public long getItemId(int position) {
return 0;
}
static class ViewHolderItem {
TextView txtCategoryNameId;
static CheckBox categoryChkBxId;
}
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolderItem viewHolder;
HashMap<String, String> mapData=categorySpinnerData.get(position);
for (int i = 0; i < this.getCount(); i++)
{
checked.add(i, false);
}
ViewHolderItem.categoryChkBxId.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton checkbox,
boolean isChecked) {
// TODO Auto-generated method stub
if (isChecked)
{
checked.set(position,true);
}
else
{
checked.set(position,false);
}
}
});
ViewHolderItem.categoryChkBxId.setChecked(checked.get(position));
if(convertView==null){
LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
convertView = mInflater.inflate(R.layout.adpt_categories_spinner, null);
// well set up the ViewHolder
viewHolder = new ViewHolderItem();
viewHolder.txtCategoryNameId = (TextView) convertView.findViewById(R.id.txtCategoryNameId);
viewHolder.categoryChkBxId = (CheckBox)convertView.findViewById(R.id.categoryChkBxId);
// store the holder with the view.
convertView.setTag(viewHolder);
}else{
// we've just avoided calling findViewById() on resource every time
// just use the viewHolder
viewHolder = (ViewHolderItem) convertView.getTag();
}
if(position==0){
viewHolder.txtCategoryNameId.setText(mapData.get("name"));
viewHolder.categoryChkBxId.setVisibility(View.INVISIBLE);
}else{
viewHolder.txtCategoryNameId.setText(mapData.get("name"));
viewHolder.txtCategoryNameId.setTag(mapData.get("id"));
viewHolder.categoryChkBxId.setVisibility(View.VISIBLE);
}
return convertView;
}
}
this is due to the recycling of views in spinner,what you can do is declare an boolean array private ArrayList<Boolean> checked = new ArrayList<Boolean>();
and initialize in your adapter constructor
for (int i = 0; i < this.getCount(); i++)
{
checked.add(i, false);
}
and now your get view method use it like this:-
your_checkbox.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton checkbox,
boolean isChecked) {
// TODO Auto-generated method stub
if (isChecked)
{
checked.set(position,true);
}
else
{
checked.set(position,false);
}
}
});
your_checkbox.setChecked(your_data.get(position));
and please use viewholder, its a good practice.

custom listview with only one checkbox is selected one at a time

I have a custom listview with each row contaning a checkbox and text. now what i want that if any one checkbox of listview row is checked so others checkbox in other row if checked .it will be delected automatically.(i.e only one checkbox should be selected one at a time).how should i do that.
So far what i have done is as follows:
public class CustomAdapter extends BaseAdapter{
Context context;
List<String> items;
boolean array[];
public CustomAdapter(Context context, List<String> items) {
super();
this.context = context;
this.items = items;
array =new boolean[items.size()];
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return items.size();
}
#Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return items.get(position);
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View v=convertView;
final int pos=position;
if(v==null)
{
v=LayoutInflater.from(context).inflate(R.layout.list,null);
}
TextView txt1=(TextView) v.findViewById(R.id.textView1);
final CheckBox chkbox=(CheckBox) v.findViewById(R.id.checkBox1);
txt1.setText(items.get(position));
int selectedindexitem=0;
chkbox.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(chkbox.isChecked())
{
array[pos]=true;
}else{
array[pos]=false;
}
}
});
chkbox.setChecked(array[pos]);
return v;
}
}
In this code i can select multiple checkbox at a time but i need only one checkbox should be checked one at a time.
You need to keep track of selected item and code accordingly.
public class CustomAdapter extends BaseAdapter{
Integer selected_position = -1;
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// Your Code
chkbox.setChecked(position==selected_position);
chkbox.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(isChecked)
{
selected_position = position;
}
else{
selected_position = -1;
}
notifyDataSetChanged();
}
});
return convertView;
}
}
Try to change all item boolean value false exclude selected item after notify adapter and also implement ViewHolder design pattern for ListView performance :
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if(convertView==null){
holder = new ViewHolder();
convertView = LayoutInflater.from(context).inflate(R.layout.list,null);
holder.txt1 = (TextView) convertView.findViewById(R.id.textView1);
holder.chkbox = (CheckBox) convertView.findViewById(R.id.checkBox1);
convertView.setTag(holder);
}else{
holder = (ViewHolder) convertView.getTag();
}
holder.txt1.setText(items.get(position));
holder.chkbox.setChecked(array[position]);
holder.chkbox.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
for (int i=0;i<array.length;i++){
if(i==position){
array[i]=true;
}else{
array[i]=false;
}
}
notifyDataSetChanged();
}
});
return convertView;
}
class ViewHolder{
TextView txt1;
CheckBox chkbox;
}
Maintain a variable:
int checked = -1; //say
Whenever you try to check a checkbox you check this variable, if it is -1 then check the checkbox and save the position of the list item in checked variable, when you try to check other checkbox again, if the variable ain't equal to -1 you first uncheck the checkbox at the position stored in checked variable, and then check the checkbox at current position and save the current position in checked variable
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View v=convertView;
final int pos=position;
if(v==null)
{
v=LayoutInflater.from(context).inflate(R.layout.list,null);
}
TextView txt1=(TextView) v.findViewById(R.id.textView1);
final CheckBox chkbox=(CheckBox) v.findViewById(R.id.checkBox1);
txt1.setText(items.get(position));
int selectedindexitem=0;
if(position==selected_position)
{
chkbox.setChecked(true);
}
else
{
chkbox.setChecked(false);
}
chkbox.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(chkbox.isChecked())
{
array[pos]=true;
selected_position = pos;
}else{
array[pos]=false;
}
}
});
chkbox.setChecked(array[pos]);
MainActivity.lv.setAdapter(new CustomAdapter(context,MainActivity.listitems));
return v;
}
Easy to maintain your selection. Get your selection from the model.
class PropertyModel{
String VAL= "SOME VALUE"
boolean selected = false;
public String getVAL() {return VAL;}
public void setVAL(String VAL) {this.VAL = VAL;}
public boolean isSelected() {return selected;}
public void setSelected(boolean selected) {this.selected = selected;}
}
Prepare your view like this:
public class CheckBoxAdptr extends BaseAdapter{
/*
..........
*/
public View getView(int position, View view, ViewGroup parent) {
PropertyModel items = list.get(position);
View row;
if (view == null) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.list_item_checkbox, null);
}
else{row = view;}
TextView T1 = (TextView) row.findViewById(R.id.list_item_1);
CheckBox checkBox = (CheckBox) row.findViewById(R.id.list_item_check_box);
T1.setText(""+items.getVAL());
if(items.isSelected()){
checkBox.setChecked(true);
}
else {checkBox.setChecked(false);}
return row;
}
}
Now in your activity or fragment set the adapter and do something like this:
final ArrayList<PropertyModel> list = getList();
CheckBoxAdptr adpt = new CheckBoxAdptr(getActivity(), list);
listview.setAdapter(adpt);
listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
for(int i = 0; i<list.size(); i++){
if(i!=position){
list.get(i).setSelected(false);
}
else{
list.get(i).setSelected(true);
}
}
adpt.notifyDataSetChanged();
}
});
Notice that all your work is done by adpt.notifyDataSetChanged() . Hope this helps.
Working with getView (like most of the answers posted) was not working properly for me. It was not responsive enough. Sometimes it would uncheck the previous checkbox, sometimes not.
This worked perfectly for me:
First we need to store the position of all previously checked checkboxes:
Set<Integer> selectedPreviousPositions = new HashSet<>();
Then in the onItemClick listener we uncheck all checkboxes before checking the one we selected.
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
boolean isChecked = ((CheckBox) view.findViewById(R.id.cbSelected)).isChecked();
if (!isChecked) {
final ListView listDevices = (ListView) findViewById(R.id.lvDevices);
for (Integer pos : selectedPreviousPositions ) {
View pView = listDevices.getChildAt(pos);
if (pView != null) { // unnecessary but we never know !
((CheckBox)pView.findViewById(R.id.checkboxID)).setChecked(false);
}
}
selectedUniquePositions.add(new Integer(position));
// Now we can check the selected checkbox
((CheckBox) view.findViewById(R.id.cbSelected)).setChecked(true);
} else {
((CheckBox) view.findViewById(R.id.cbSelected)).setChecked(false);
selectedPreviousPositions.remove(new Integer(position));
}
}
Inside the adapter, set OnClickListener() for checkBox. Whenever checkBox is clicked, store clicked checkBox position and call notifyDataSetChanged(). This will getView() method again for all views in your listview. Whenever, getView() called, you check the checkBox of previously stored postition and uncheck remaining checkboxes.
public class CustomAdapter extends ArrayAdapter<YourModelObject>
{
private int selectedCheckBoxPosition = -1;
public int getSelectedCheckBoxPosition()
{
return selectedCheckBoxPosition;
}
#Override
public View getView(final int position, View convertView, final ViewGroup parent)
{
final ViewHolder viewHolder;
LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null)
{
convertView = layoutInflater.inflate(R.layout.list_item, null);
viewHolder = new ViewHolder();
viewHolder.checkBox = (CheckBox) convertView;
convertView.setTag(viewHolder);
}
else
{
viewHolder = (ViewHolder) convertView.getTag();
}
if (position == selectedCheckBoxPosition)
{
viewHolder.checkBox.setChecked(true);
Log.d(TAG, "checkbox CHECKED at pos: " + position);
}
else
{
viewHolder.checkBox.setChecked(false);
Log.d(TAG, "checkbox UNCHECKED at pos: " + position);
}
//viewHolder.checkBox.setText("sample text");
viewHolder.checkBox.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View view) {
selectedCheckBoxPosition = position;
Log.d(TAG, "onClick() - set selectedCheckBoxPosition = " + position);
notifyDataSetChanged();
}
});
return convertView;
}
private class ViewHolder
{
CheckBox checkBox;
}
}

Android: Listview don't save a state of checkbox

I check all topic with similar problem, but I stil stay in deadpoint. I have a listview with contact list, but when i scroll down and scroll up listview don't save a state of my choices. All checkboxes was setting on false. When i debug i see, when i scrolled listview, my onClickListener thinking that checkbox was signed and reset this. I do everything, other array with position boolean, etc etc and I still don't know what to do :( I will be very gratefull for any help:)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
readContacts();
Contact_Database dbhandler = new Contact_Database(
getApplicationContext(), null, null, 1);
numbers.addAll( dbhandler.getAllNumbers());
System.out.println("onCreate");
ListView lv = getListView();
registerForContextMenu(lv);
lv.setTextFilterEnabled(true);
lv.clearChoices();
MyAdapter adapter = (new MyAdapter(this, R.layout.contact_list_sms, contacts));
adapter.notifyDataSetChanged();
lv.setAdapter(adapter);
}
/**
* When I destroy intent i send request to database, faster!
*/
#Override
protected void onDestroy() {
super.onDestroy();
for (int i = 0; i < numbers.size(); ++i)
System.out.println("####" + numbers.get(i));
swap_contacts();
}
class MyAdapter extends ArrayAdapter<Contact> {
LayoutInflater inflat;
public MyAdapter(Context context, int textViewResourceId,
ArrayList<Contact> objects) {
super(context, textViewResourceId, objects);
inflat = LayoutInflater.from(context);
System.out.println("LOLLLLL");
notifyDataSetChanged();
}
#Override
public int getItemViewType(int position) {
return (position == this.getCount() - 1) ? 1 : 0;
}
#Override
public int getViewTypeCount() {
return 2;
}
// if that contact exist in database? numbers, in onCreate method
// i init this with saved position from databse
private boolean exist(String x) {
for (int i = 0; i < numbers.size(); i++)
if (numbers.get(i).compareTo(x) == 0)
return true;
return false;
}
#SuppressLint("NewApi")
#Override
public View getView(int position, View convertView, ViewGroup parent) {
System.out.println("ROWS !!! ->" + numbers.size());
ViewHolder holder = null;
if (convertView == null) {
holder = new ViewHolder();
convertView = inflat.inflate(R.layout.contact_row, null);
holder.textView1 = (TextView) convertView
.findViewById(R.id.name);
holder.textView2 = (TextView) convertView
.findViewById(R.id.number);
holder.on_off = (CheckBox) convertView
.findViewById(R.id.enable);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
Contact it = contacts.get(position);
Log.v("XXX", holder.toString());
if (it != null) {
holder.textView1.setText(contacts.get(position).name);
holder.textView2.setText(contacts.get(position).phone);
// update state of checbox from database
if (exist(contacts.get(position).phone))
holder.on_off.setChecked(true);
else
holder.on_off.setChecked(false);
}
final int element_position = position;
holder.on_off
.setOnCheckedChangeListener(new OnCheckedChangeListener() {
// update list when we click on it
#Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
String nr_telefonu = contacts.get(element_position).phone;
if (isChecked) {
numbers.add(nr_telefonu);
} else {
numbers.remove(nr_telefonu);
}
}
});
return convertView;
}
#Override
public Contact getItem(int position) {
return contacts.get(position);
}
private class ViewHolder {
TextView textView1, textView2;
CheckBox on_off;
public String toString() {
return "-";
}
}
}
List does not save it state while scrolling , because each time new object is created for row item. So you need to explicitly save the state of CheckBox with help of Pojo class(Setter and getter).
in getView() method you need to check the value for each checkbox.
#Override
public View getView(int position, View convertView, ViewGroup parent) {
////////////////////
and on setOnCheckedChangeListener you need to save the state of checkbox
holder.on_off
.setOnCheckedChangeListener(new OnCheckedChangeListener() {
// update list when we click on it
#Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
// need to save the state
for more details please refer to this below blog
http://amitandroid.blogspot.in/2013/03/android-listview-with-checkbox-and.html
you can change it according to your requirement.
Thank's for answer :) I create a array stan with state for every checkbox button. Tommorrow i will try rebuild all my class like the list on the blog, mayby this help me.
But when I do this :
save state:
holder.on_off
.setOnCheckedChangeListener(new OnCheckedChangeListener() {
// update list when we click on it
// this.setChecked(stan[position]);
#Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
String nr_telefonu = p.get(element_position).phone;
buttonView.setChecked(stan[element_position]);
stan[element_position] = isChecked;
}
});
Refresh state of button
if (it != null) {
holder.textView1.setText(contacts.get(position).name);
holder.textView2.setText(contacts.get(position).phone);
// update state of checbox from database
holder.on_off.setChecked(stan[position]);
}
I still stand In dead point, nothing is changed
I've posted the solution to this problem below which I spent a lot of time finding and it works for me!
public class RowAdapter extends ArrayAdapter<Rows> {
Context context;
int layoutResourceId;
ArrayList<Rows> data;
boolean[] checkBoxState;
RowHolder rowHolder;
public RowAdapter(Context context, int layoutResourceId, ArrayList<Rows> data) {
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = data;
checkBoxState = new boolean[data.size()];
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View row = convertView;
RowHolder holder = null;
if(row == null)
{
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false);
holder = new RowHolder();
holder.textView1 = (TextView)row.findViewById(R.id.textView1);
holder.textView2 = (TextView)row.findViewById(R.id.textView2);
holder.textView3 = (TextView)row.findViewById(R.id.textView3);
holder.textView4 = (TextView)row.findViewById(R.id.textView4);
holder.checkBox=(CheckBox) row.findViewById(R.id.checkBox1);
row.setTag(holder);
}
else{
holder = (RowHolder)row.getTag();
}
Rows rows = data.get(position);
holder.textView1.setText(rows.address);
holder.textView2.setText(rows.tenancy);
holder.textView3.setText(rows.location);
holder.textView4.setText(rows.name);
holder.checkBox.setChecked(checkBoxState[position]);
holder.checkBox.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if(((CheckBox)v).isChecked())
checkBoxState[position]=true;
else
checkBoxState[position]=false;
}
});
return row;
}
static class RowHolder
{
TextView textView1;
TextView textView2;
TextView textView3;
TextView textView4;
CheckBox checkBox;
}
}

android checkbox is not checked for custom listview when listview is in scrollview

i have implemented custom list view with check box and textviews. It is working fine when list view is not in scroll but if the rows are increased then listviews is in scroll view that time when i click on check box the checked mark is not staying. here is my code, Please suggest me if anything wrong in that code
public class ArchivedAdapter extends ArrayAdapter<MessageBean> {
final ArrayList<MessageBean> updatedList = new ArrayList<MessageBean>();
private List<MessageBean> list;
private TextView officenameView, sentOnView, messageView;
public final static String MY_ACTION = "com.android.threeptalk.broadcast";
private boolean isDeleted = false;
int count = 0;
HashMap<Integer, CheckBox> checkList = new HashMap<Integer, CheckBox>();
public ArchivedAdapter(Context context, int resourseID,
List<MessageBean> list) {
super(context, resourseID, list);
this.list = list;
}
#Override
public int getCount() {
return list.size();
}
#Override
public MessageBean getItem(int arg0) {
return list.get(arg0);
}
#Override
public long getItemId(int arg0) {
return arg0;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View row = convertView;
LayoutInflater inflater = (LayoutInflater) this.getContext()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.archievedmsgrow, parent, false);
row.setId(position);
Object obj = getItem(position);
if (obj instanceof MessageBean) {
final MessageBean message = (MessageBean) obj;
CheckBox checkBox = (CheckBox) row.findViewById(R.id.checkBox);
officenameView = (TextView) row.findViewById(R.id.officename);
sentOnView = (TextView) row.findViewById(R.id.time);
messageView = (TextView) row.findViewById(R.id.message);
officenameView.setText(message.getOfficeName());
checkList.put(position, checkBox);
checkBox.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
CheckBox c = (CheckBox) v;
if (c.isChecked()) {
c.setChecked(true);
count++;
updatedList.add(message);
} else {
c.setChecked(false);
count--;
updatedList.remove(message);
updatedList.size());
}
checkedCount(count, updatedList);
}
});
row.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
rowclicked(message, position);
}
});
sentOnView.setText(Common.getAppropriateTimeUsingTimeZone(message
.getmDate()));
if (message.getMessage() != null) {
messageView.setText((message.getMessage()));
} else {
if (message.getMessageType().equals("OPTION")) {
if (message.getOptions() != null
&& message.getOptions().size() > 0) {
String data = message.getOptions().get(0);
if (data != null && !data.equals("")) {
messageView.setText(data);
}
}
}
}
}
return row;
}
protected void messageSelected() {
}
protected void rowclicked(MessageBean message, int position) {
// TODO Auto-generated method stub
}
protected void checkedCount(int count2, ArrayList<MessageBean> updatedList) {
}
}
`
Try this example ListView with CheckBox Scrolling Issue
Seems like you are checking the check status of checkbox inside its onClickListener().
First define an Hashmap or SparseBooleanArray to save your selections.
private HashMap<Integer, Boolean> mSelection = new HashMap<Integer, Boolean>();
Then add the following code to your getView() method.
CheckBox checkBox = (CheckBox) row.findViewById(R.id.checkBox);
checkBox.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
mSelection.put(position, isChecked);
}
});
if (mSelection.get(position) != null) {
if (mSelection.get(position))
checkBox.setChecked(true);
else
checkBox.setChecked(false);
}
Try this, Assuming that you are using the Custom Adapter for your ListView, you will be able to set Tag for each Item inside your Adapter's getView(),
public View getView(int position, View convertView, ViewGroup parent) {
EvenViewHolder holdereven;
if (convertView == null) {
convertView = mInfaltor.inflate(R.layout.schedule_adapter_view,
null);
holdereven = new EvenViewHolder();
holdereven.time = (TextView) convertView
.findViewById(R.id.time);
holdereven.title = (TextView) convertView
.findViewById(R.id.title);
holdereven.des = (TextView) convertView.findViewById(R.id.des);
convertView.setTag(holdereven);
} else {
holdereven = (EvenViewHolder) convertView.getTag();
}
static class EvenViewHolder {
TextView time, title, des;
}
}

Categories

Resources