问题
I know that this question has been asked over and over again but still I've not been able to find a helpful suggestion. Check box is getting unchecked when I scroll the List view. I am using Array List to store id of a selected item in the list view when particular item is unchecked it is removed from List view.
public class ManagePracticeLogAdapter extends BaseAdapter
{
Context context;
LayoutInflater inflater;
MenuItem menu,addlog;
List<Integer> SelectedBox;
ArrayList<HashMap<String, String>> data;
HashMap<String, String> resultp = new HashMap<String, String>();
public ManagePracticeLogAdapter(
Context context,
ArrayList<HashMap<String, String>> arraylist,
MenuItem mymenu,
MenuItem myaddlog)
{
this.context = context;
data = arraylist;
menu=mymenu;
addlog=myaddlog;
}
@Override
public int getCount()
{
return data.size();
}
@Override
public Object getItem(int position)
{
return null;
}
@Override
public long getItemId(int position)
{
return 0;
}
// Method to display data of Produce log Activity in list view
@Override
public View getView(final int position, View convertView, ViewGroup parent)
{
// TODO Auto-generated method stub
TextView datetime;
TextView totminutes;
TextView skills;
TextView weather;
final CheckBox chkdelete;
inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View itemView = inflater.inflate(R.layout.logitem1, parent, false);
// Get the position
resultp = data.get(position);
// Locate the TextViews in listview_item.xml
datetime = (TextView) itemView.findViewById(R.id.id_datetime);
totminutes = (TextView) itemView.findViewById(R.id.totminutes);
skills= (TextView) itemView.findViewById(R.id.id_skills);
weather=(TextView)itemView.findViewById(R.id.id_weather);
chkdelete=(CheckBox)itemView.findViewById(R.id.id_chkDelete);
// Capture position and set results to the TextViews
datetime.setText(resultp.get("Skill_practice"));
totminutes.setText(resultp.get("Day_minutes")+" min");
skills.setText(resultp.get("Night_minutes"));
weather.setText(resultp.get("Prac_Date"));
String fontPath = "fonts/Roboto-Light.ttf";
Typeface tf = Typeface.createFromAsset(context.getAssets(), fontPath);
datetime.setTypeface(tf);
totminutes.setTypeface(tf);
skills.setTypeface(tf);
weather.setTypeface(tf);
SelectedBox = new ArrayList<Integer>();
chkdelete.setOnCheckedChangeListener(new OnCheckedChangeListener()
{
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
{
if(SelectedBox.size()-1==0)
{
menu.setVisible(false);
addlog.setVisible(true);
}else
{
addlog.setVisible(false);
}
if(isChecked)
{
SelectedBox.add(buttonView.getId());
menu.setVisible(true);
addlog.setVisible(false);
}else if(!isChecked)
{
SelectedBox.remove(SelectedBox.indexOf(buttonView.getId()));
}
}
});
menu.setOnMenuItemClickListener(new OnMenuItemClickListener()
{
@Override
public boolean onMenuItemClick(MenuItem item)
{
// TODO Auto-generated method stub
if(!SelectedBox.isEmpty())
{
Toast.makeText(context, "Menu option 4 added!",
Toast.LENGTH_LONG).show();
}
return false;
}
});
itemView.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View arg0)
{
Intent intent = new Intent(context,LogEdit.class);
intent.putExtra("s11","Update Practice");
context.startActivity(intent);
}
});
return itemView;
}
}
回答1:
Your getView method should look like this
Create a ViewHolder class
static class ViewHolder {
TextView datetime;
TextView totminutes;
TextView skills;
TextView weather;
CheckBox chkdelete;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder = null;
if (convertView == null) {
LayoutInflater inflator = context.getLayoutInflater();
convertView = inflator.inflate(R.layout.logitem1, null);
viewHolder = new ViewHolder();
viewHolder.datetime = (TextView) convertView.findViewById(R.id.id_datetime);
// do the same thing for other textviews and checkbox.
viewHolder.chkdelete.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
int getPosition = (Integer) buttonView.getTag(); // Here we get the position that we have set for the checkbox using setTag.
}
});
convertView.setTag(viewHolder);
convertView.setTag(R.id.id_datetime, viewHolder.datetime);
// do the same for other textviews and checkbox
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.chkdelete.setTag(position); // This line is important.
viewHolder.datetime.setText(resultp.get("Skill_practice"));
// do the same for others
return convertView;
}
You need to modify it according to your needs. This code will solve your problem on scroll.
回答2:
You need to use for example a sparse boolean array. https://groups.google.com/forum/?fromgroups#!topic/android-developers/No0LrgJ6q2M
Listview are recycled so you basically need to save the state of your checkbox somewhere.
Juste create a sparse boolean array with a size [number of checkbox].
When one of your checkbox is clicked, get his position and set in the sparse boolean array the element (at this position) to true.
In the create view just set the checkbox to the state "enabled" IF your sparse boolean is true.
And you should use a view holder instead of creating new object each time.
Good luck !
回答3:
The buttonView in
onCheckedChanged(CompoundButton buttonView, boolean isChecked)
refers to the last item of the adapter. This is because adapter is used to recycle view. To access the id , store it in the tag.
chkdelete.setTag(R.id.id_chkDelete);
Finally you can access the id of the view via its tag inside onCheckedChanged() as
int checkBoxId=(int) view.getTag().toString();
Finally, your code looks like
SelectedBox = new ArrayList<Integer>();
chkdelete.setTag(R.id.id_chkDelete);
chkdelete.setOnCheckedChangeListener(new OnCheckedChangeListener(){
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
{
int checkBoxId=(int) view.getTag().toString();
if(SelectedBox.size()-1==0)
{
menu.setVisible(false);
addlog.setVisible(true);
}else
{
addlog.setVisible(false);
}
if(isChecked)
{
SelectedBox.add(checkBoxId);
menu.setVisible(true);
addlog.setVisible(false);
}else if(!isChecked)
{
SelectedBox.remove(SelectedBox.indexOf(checkBoxId));
}
}
});
来源:https://stackoverflow.com/questions/24257093/in-custom-list-view-check-box-is-unchecked-when-i-scrolling