Easy Tutorial
❮ Ubuntu Modify Dns Chrome Extensions Recommended ❯

2.4.8 Solving the Checkbox Misalignment Issue in ListView

Category Android Basic Beginner Tutorial

Introduction:

>

As one of the classic issues with ListView, if you've tried customizing ListView items with a checkbox, you might encounter this problem when the number of items exceeds a page. Below, we'll analyze the cause of this issue and discuss how to resolve it!


1. Causes of the Issue:

Here's a diagram found online that illustrates the ListView getView method invocation mechanism:

In the diagram, there's a Recycler. The visible items on the ListView are in memory, while the items that are not visible are stored in this Recycler. When loading items for the first time, the convertView in the current page is NULL. When an item scrolls out of the screen, the ConvertView is no longer empty, so a new item will reuse this ConvertView!

We can write a simple example and follow the logs. Here are some logs after running the example:

From the logs, we can see that starting from Position 12, ConvertView is no longer empty. What this specifically represents is unclear, and it might require looking into the source code... We know that ConvertView is cached here, and it's this caching that causes the checkbox misalignment. Therefore, the first solution is to not reuse this ConvertView, or to set the ConvertView to null every time getView is called. However, if the number of items to be displayed is huge, this method would be very cumbersome. Typically, in actual development, we use the following solution: Find something to store the current item CheckBox status, and initialize it by checking and setting whether it's selected.


2. Example Solution:

>

There are many good ways to store this Checkbox status. You can use a HashMap<Integer, Boolean>, and each time you initialize, you can retrieve the corresponding boolean value based on the position and then set the Checkbox status; My approach was to add a boolean value in the entity class for checking. Below is the code extracted from one of my projects. The code is simple, and I believe you'll understand it instantly.

Entity class: Person.java:

public class Person implements Serializable {
    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:

public class ContactListAdapter extends BaseAdapter implements CompoundButton.OnCheckedChangeListener {

    private List<Person> mData;
    private Context mContext;

    public ContactListAdapter(List<Person> data, Context context) {
        mData = data;
        mContext = context;
    }

    // Method to refresh data
    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;
    }
}

Very simple, and don't forget one thing: The checkbox listener method should be added before the code that initializes the Checkbox status!


Conclusion:

>

Well, this section has explained a classic issue with ListView, the checkbox misalignment problem, and how to solve it by simply adding a value to record the checkbox selection status and rewriting the checkbox click event with a check. Thank you!

-1.0 Android Basic Beginner Tutorial

-1.0.1 2015 Latest Android Basic Beginner Tutorial Contents

-1.1 Background and System Architecture Analysis

-1.2 Development Environment Setup

-1.2.1 Using Eclipse + ADT + SDK to Develop Android Apps

-1.2.2 Using Android Studio to Develop Android Apps

-1.3 Solving SDK Update Issues

-1.4 Genymotion Emulator Installation

-1.5.1 Git Tutorial for Basic Local Repository Operations

-1.5.2 Git: Setting Up a Remote Repository on GitHub

-1.6 How to Play with the 9-Patch Image

-1.7 Interface Prototype Design

Follow on WeChat

❮ Ubuntu Modify Dns Chrome Extensions Recommended ❯