我拥有的内容:带有Textviews和复选框的自定义列表视图
问题:如果我检查屏幕上显示的初始项目然后滚动列表,当我返回列表顶部(向上滚动)时,它们的值被正确保存。但是,如果我滚动列表,例如我想检查列表中的最后一个树复选框,那么如果我上下滚动它们就会被取消选中....为什么?**
我已经在其他论坛中看到了针对同一问题的各种解决方案,也在stackoverflow上看到过,但问题仍然存在
在我的getView函数下面,我认为没问题:
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder viewHolder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.item_select_friends, null);
viewHolder=new ViewHolder();
viewHolder.nameText=(TextView) convertView.findViewById(R.id.personName);
viewHolder.surnameText=(TextView) convertView.findViewById(R.id.personSurname);
viewHolder.contactImage=(ImageView) convertView.findViewById(R.id.personImage);
viewHolder.checkBox=(CheckBox)convertView.findViewById(R.id.checkBox);
convertView.setTag(viewHolder);
viewHolder.nameText.setTag(viewHolder.nameText);
viewHolder.nameText.setTag(viewHolder.surnameText);
viewHolder.contactImage.setTag(data[position]);
viewHolder.checkBox.setChecked(data[position].isCheck());
viewHolder.checkBox.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
if(viewHolder.checkBox.isChecked()==true)
data[position].setCheck(true);
else
data[position].setCheck(false);
}
});
}
else{
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.nameText.setText(data[position].getName());
viewHolder.surnameText.setText(data[position].getSurname());
viewHolder.contactImage.setImageResource(data[position].getPhotoRes());
viewHolder.contactImage.setScaleType(ScaleType.FIT_XY);
viewHolder.checkBox.setChecked(data[position].isCheck());
return convertView;
}
已解决:我解决了我的问题getView whit这段代码:
public class NewQAAdapterSelectFriends extends BaseAdapter {
private LayoutInflater mInflater;
private Person[] data;
boolean[] checkBoxState;
ViewHolder viewHolder;
public NewQAAdapterSelectFriends(Context context) {
mInflater = LayoutInflater.from(context);
}
public void setData(Person[] data) {
this.data = data;
checkBoxState=new boolean[data.length];
}
@Override
public int getCount() {
return data.length;
}
@Override
public Object getItem(int item) {
return data[item];
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = mInflater.inflate(R.layout.item_select_friends, null);
viewHolder=new ViewHolder();
viewHolder.nameText=(TextView) convertView.findViewById(R.id.personName);
viewHolder.surnameText=(TextView) convertView.findViewById(R.id.personSurname);
viewHolder.contactImage=(ImageView) convertView.findViewById(R.id.personImage);
viewHolder.checkBox=(CheckBox)convertView.findViewById(R.id.checkBox);
convertView.setTag(viewHolder);
}
else{
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.nameText.setText(data[position].getName());
viewHolder.surnameText.setText(data[position].getSurname());
viewHolder.contactImage.setImageResource(data[position].getPhotoRes());
viewHolder.contactImage.setScaleType(ScaleType.FIT_XY);
viewHolder.checkBox.setChecked(checkBoxState[position]);
viewHolder.checkBox.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if(((CheckBox)v).isChecked()){
checkBoxState[position]=true;
data[position].setCheck(true);
}else{
checkBoxState[position]=false;
data[position].setCheck(false);
}
}
});
return convertView;
}
static class ViewHolder {
TextView nameText;
TextView surnameText;
ImageView contactImage;
CheckBox checkBox;
}
}
我已经看过这个教程来做我的getView:http://androidcocktail.blogspot.it/2012/04/adding-checkboxes-to-custom-listview-in.html
答案 0 :(得分:2)
即使在方法中使用new
创建类,也为变量创建了不同的范围。换句话说:
// Creating a new scope here --> vvv
viewHolder.checkBox.setOnClickListener(new OnClickListener() {
// Any variables not visible to the entire class, won't work properly in here!
// (variables like: viewHolder, position, possibly data)
public void onClick(View arg0) {
if(viewHolder.checkBox.isChecked()==true)
data[position].setCheck(true);
else
data[position].setCheck(false);
}
}); // Exited "new class'" scope
position
与您认为的position
不同。请尝试保存position
的值,以便再次引用它:
viewHolder.checkBox = (CheckBox) convertView.findViewById(R.id.checkBox);
viewHolder.position = position;
convertView.setTag(viewHolder);
...
viewHolder.checkBox.setOnClickListener(new OnClickListener() {
public void onClick(View view) {
ViewHolder viewHolder = (ViewHolder) view.getTag();
data[viewHolder.position].setCheck(viewHolder.checkBox.isChecked());
}
});
由于您正在处理CheckBox,我建议您使用OnCheckedChangeListener。
但如果更改ChoiceMode,则可能不需要为ListView行定义任何侦听器:
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
答案 1 :(得分:0)
在viewHolder.checkBox.setChecked(checkBoxState[position]);
或viewHolder.checkBox.setOnCheckedChangedListener
之后添加viewHolder.checkBox.setOnClickListener
。
因为在滚动之后,当listview回收它的视图时,它会在旧的侦听器的基础上使用setChecked
,在某些情况下可能会丢失值。
所以这是流程 -
getView()
---
---
---
viewHolder.checkBox.setOnCheckedChangedListener()
---
---
---
viewHolder.checkBox.setChecked()
答案 2 :(得分:0)
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder>
{
boolean[] checkBoxState;
public MyAdapter(Context context, ArrayList<String> list ) {
checkBoxState = new boolean[list.size()];
}
@Override
public void onBindViewHolder( final ViewHolder holder, final int position) {
holder.checkBox.setTag(position);
holder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener(){
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
if(compoundButton.isPressed()) // check whether user pressed the checkbox.
{
int getPosition = (Integer) compoundButton.getTag(); // Here we get the position that we have set for the checkbox using setTag.
checkBoxState[getPosition] = compoundButton.isChecked(); // Set the value of checkbox to maintain its state.
}
}
});
holder.checkBox.setChecked(checkBoxState[position]);
}
public class ViewHolder extends RecyclerView.ViewHolder {
public CheckBox checkBox;
public ViewHolder(View v,MainActivity mainActivity) {
super(v);
checkBox= (CheckBox) v.findViewById(R.id.checkBox);
}
}
@Override
public int getItemCount() {
return list.size();
}
}
滚动时,可以自动调用onCheckedChanged()方法。因此,您可能需要使用isPressed()方法来检查用户是否按下了复选框。我的适配器类如上所示。请注意,当您向列表中添加新元素时,应更新布尔数组checkBoxState,例如,当您向列表中添加元素时,应调用以下内容:
checkBoxState = new boolean[list.size()+1];
或使用arraylist来保存布尔变量并向此arraylist添加元素,无论你想要什么。
我还为此解决方案实施了一个项目。你可以在这里下载 : https://www.dropbox.com/s/ssm58w62gw32i29/recyclerView_checkbox_highlight.zip?dl=0
屏幕截图如下: