Solving the problem of checkbox misalignment in ListView
Introduction to this section:
As one of the classic problems of ListView, if you have tried to customize the item of ListView with a checkbox on it, then This problem will occur when the number of your items exceeds one page. Let’s analyze the reasons for this problem and how to solve it. solve this problem!
1. Cause of the problem:
This is a picture of the ListView getView method calling mechanism found on the Internet
There is a Recycler thing in the above picture. Usually the Item visible on our ListView is in the memory, and its Item is placed in In this Recycler, when the item is loaded for the first time, the convertView in the current page is NULL. When scrolling out of the screen, ConvertView is not empty at this time, so the new item will reuse this ConvertView! We can write a simple example and follow the log. Here are some Log diagrams after running!
As can be seen from the picture, starting from Postion 12, ConvertView is no longer empty. What does it represent specifically? I don't know, I have to go through the source code visually... We know that ConvertView will be cached here, just for this reason The checkbox is misaligned, so the first solution is not to reuse this ConvertView, or It is said that every time getView sets this ConvertView to null, but if the number of Items that need to be displayed is huge, This method will appear very bloated. Generally, in actual development, we use the following solution: Find something to save the current Item CheckBox state, and judge during initialization to set whether it is selected!
2. Solution example:
There are many good ways to store this Checkbox. You can put it in a HashMap<Integer, Boolean>. During each initialization, the corresponding boolean value is taken out according to the postion, and then the checkbox status is set; The author's approach is to add a boolean value to the entity class for judgment. The following is one of the author's projects. The extracted code is relatively simple. I believe you will understand it in seconds after reading it~
Entity class: Person.java:
private String name;
private String number;
private boolean checkStatus;
public Person(String name, String number) {
super();
this.name = name;
this.number = number;
this.checkStatus = false;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public boolean getCheckStatus() {
return checkStatus;
}
public void setCheckStatus(boolean checkStatus) {
this.checkStatus = checkStatus;
}
}
Implemented Adapter class: ContactListAdapter.java:
private List<Person> mData;
private Context mContext;
public ContactListAdapter(List<Person> data, Context context) {
mData = data;
mContext = context;
}
// 定义一个刷新数据的方法
public void changeData(List<Person> data) {
mData = data;
notifyDataSetChanged();
}
@Override
public int getCount() {
return mData.size();
}
@Override
public Person getItem(int position) {
return mData.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final int index = position;
ViewHolder viewHolder;
if (convertView == null) {
convertView = LayoutInflater.from(mContext).inflate(
R.layout.item_contact, parent, false);
viewHolder = new ViewHolder();
viewHolder.ly = (RelativeLayout) convertView
.findViewById(R.id.lyContactListItem);
viewHolder.txtName = (TextView) convertView
.findViewById(R.id.txtName);
viewHolder.txtNumber = (TextView) convertView
.findViewById(R.id.txtNumber);
viewHolder.cbxStatus = (CheckBox) convertView
.findViewById(R.id.cbxStatus);
convertView.setTag(viewHolder);
viewHolder.cbxStatus.setTag(index);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.cbxStatus.setOnCheckedChangeListener(this);
viewHolder.cbxStatus.setChecked(mData.get(position).getcheckStatus());
viewHolder.txtName.setText(mData.get(index).getName());
viewHolder.txtNumber.setText(mData.get(index).getNumber());
return convertView;
}
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
int index = (int)buttonView.getTag();
if (isChecked)
mData.get(index).setCheckStatus(true);
else
mData.get(index).setCheckStatus(false);
}
private class ViewHolder {
RelativeLayout ly;
TextView txtName;
TextView txtNumber;
CheckBox cbxStatus;
}
}
Hey, it’s very simple, don’t forget one more thing: The checkbox listener method should be added before the code that initializes the Checkbox state~
Introduction to this section:
Okay, this section explains to you a classic problem of ListView, the checkbox in ListView is misplaced The problem is solved by simply adding a value that records the checkbox selection status, and then rewriting the checkbox When clicking on an event, make a judgment first~Thank you~