ListView with CheckBox - Single row selection in Android

    In my previous post about ListView with CheckBox, users can select many ListView items (rows) by checking CheckBox. It's will use to save or put data to other Activity. But what about single row can be checked (selected) in a list? Sometimes, this requiment still happens when the aim is you can select only one case! For this, we can also use CheckBox-ListView design. Through this tip, I provide a solution can resolved it through handling CheckBox on click event and update adapter immediately!
    DEMO VIDEO:

    First, define a simple activity layout file (xml), only includes a ListView:
    The most important work will be done in ListView adapter class (extends from ArrayAdapter class). In this, define a int variable called selectedPosition by defaul value is -1. When we checked at each CheckBox, it's value will be changed to row's postion and restore to the default values when unchecked. So, we have this method:
private View.OnClickListener onStateChangedListener(final CheckBox checkBox, final int position) {
        return new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (checkBox.isChecked()) {
                    selectedPosition = position;
                } else {
                    selectedPosition = -1;
                }
                notifyDataSetChanged(); // update adapter after changed
            }
        };
    }
    In getView() method (override from parent class), set event for CheckBox through call:
holder.checkBox.setOnClickListener(onStateChangedListener(holder.checkBox, position));
    Important Note: Always use setOnClickListener() for CheckBox instead of setOnCheckedChangeListener() because of recycling feature of ListView, the first rows cannot be checked!
    Provide a ViewHolder class to get scroll smoother, we have full code for this adapter class:
package info.devexchanges.singlchecklistview;

import android.app.Activity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.TextView;

import java.util.List;

public class ListViewAdapter extends ArrayAdapter<Friend> {

    private List<Friend> myFriends;
    private Activity activity;
    private int selectedPosition = -1;

    public ListViewAdapter(Activity context, int resource, List<Friend> objects) {
        super(context, resource, objects);

        this.activity = context;
        this.myFriends = objects;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        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.friendName.setText(getItem(position).getName());
        if (position == selectedPosition) {
            holder.checkBox.setChecked(true);
        } else holder.checkBox.setChecked(false);

        holder.checkBox.setOnClickListener(onStateChangedListener(holder.checkBox, position));

        return convertView;
    }

    private View.OnClickListener onStateChangedListener(final CheckBox checkBox, final int position) {
        return new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (checkBox.isChecked()) {
                    selectedPosition = position;
                } else {
                    selectedPosition = -1;
                }
                notifyDataSetChanged();
            }
        };
    }

    private static class ViewHolder {
        private TextView friendName;
        private CheckBox checkBox;

        public ViewHolder(View v) {
            checkBox = (CheckBox) v.findViewById(R.id.check);
            friendName = (TextView) v.findViewById(R.id.name);
        }
    }
}
    In activity, I get a dummy data set from text file in Assests to create a List object use for ListView then. Set header for our ListView, handling each item click event,...we have full code:
package info.devexchanges.singlchecklistview;

import android.app.Dialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.method.CharacterPickerDialog;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

    private ArrayList<Friend> friendArrayList;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        friendArrayList = new ArrayList<>();

        ListView listView = (ListView) findViewById(R.id.list_item);

        //set ListView header
        LayoutInflater inflater = getLayoutInflater();
        View header = inflater.inflate(R.layout.header_listview, listView, false);
        listView.addHeaderView(header, null, false);

        readDataFromAssets();

        ListViewAdapter adapter = new ListViewAdapter(this, R.layout.item_listview, friendArrayList);
        listView.setAdapter(adapter);

        listView.setOnItemClickListener(onItemClickListener());
    }

    private AdapterView.OnItemClickListener onItemClickListener() {
        return new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView parent, View view, int position, long id) {
                final Dialog dialog = new Dialog(MainActivity.this);
                dialog.setContentView(R.layout.layout_dialog);
                dialog.setTitle("Friend Details");
                dialog.setCancelable(true);

                TextView friendID = (TextView) dialog.findViewById(R.id.position);
                TextView friendName = (TextView) dialog.findViewById(R.id.name);

                friendID.setText("Position: " + (position + 1));
                friendName.setText("Name: " + ((Friend) parent.getItemAtPosition(position)).getName());

                dialog.show();
            }
        };
    }

    private void readDataFromAssets() {
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new InputStreamReader(getAssets().open("friend.txt")));

            // do reading, usually loop until end of file reading
            String line;
            while ((line = reader.readLine()) != null) {
                friendArrayList.add(new Friend(line));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
     Output when app running:
    Finally, there are some necessary files to complete this project:
- A layout for each ListView item, contains a CheckBox and a TextView:
Note: Always set android:focusable="false" property to CheckBox if you want ListView row clickable!
- A Dialog layout (show on each item clicked):
Output:
- In activity code, we added a header layout for ListView, so this is it xml file:
Conclusions: There are a lot of ways to make this trick in ListView with CheckBox, my solution is just only one of them. By searching on Internet, you'll find out another quickly. Hoping my simple project in this tip is helpful!


Share


Previous post
« Prev Post
Next post
Next Post »