Selecting/highlighting multiple items in listview with custom adapter - Android

12,910
  1. The root View of each item you will display in list must implement Checkable. When implementing this interface also update the drawable state of View. See this answer for how to do that.

  2. Set a <selector> drawable as background for this root View. Which different color/drawables for checked state and normal states.

  3. Set ListView's choice mode to single choice or multi-choice.

  4. In list adapter, provide item views with above created View as parent layout.

Now, ListView will take care of setting checked/unchecked state on its item views. Also you can call getCheckedItemIds() or getCheckedItemPositions() on ListView to get currently selected items.

Share:
12,910
Willis
Author by

Willis

Hardware/Software development for an aerospace company.

Updated on July 25, 2022

Comments

  • Willis
    Willis almost 2 years

    I followed a good tutorial, with some changes, to create a custom ListView that will allow me to display multiple images for each row in my ListView. What I would like to do is highlight by selecting multiple items in the list and then perform some sort of action to all of those list items by selecting an option on my Options Menu. However, the problem I seem to be running into is that I cannot select multiple items, even though I have added android:choiceMode="multipleChoice" to the ListView in the .xml file. I realize that this can be done using check boxes or radio buttons, but I would prefer to avoid that. I have attached my source code below. Any help would be appreciated. Lastly, thanks to http://custom-android-dn.blogspot.com/ for a great tutorial. Thanks.

    CustomlistviewActivity.java

    package DucNguyen.example.customlistview;
    
    public class CustomlistviewActivity extends Activity {
    
        private ListView listViewFootballLegend;
        private Context ctx;
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_customlistview);        
            ctx=this;   
            List<FootballLegend> legendList= new ArrayList<FootballLegend>();
            legendList.add(new FootballLegend("Pele","October 23, 1940 (age 72)","pele","brazil"));
            legendList.add(new FootballLegend("Diego Maradona","October 30, 1960 (age 52)","maradona","argentina"));
            legendList.add(new FootballLegend("Johan Cruyff","April 25, 1947 (age 65)","cruyff","netherlands"));
            legendList.add(new FootballLegend("Franz Beckenbauer","September 11, 1945 (age 67)","beckenbauer","germany"));
            legendList.add(new FootballLegend("Michel Platini","June 21, 1955 (age 57)","platini","france"));
            legendList.add(new FootballLegend("Ronaldo De Lima","September 22, 1976 (age 36)","ronaldo","brazil"));
    
            listViewFootballLegend = ( ListView ) findViewById( R.id.FootballLegend_list);
            listViewFootballLegend.setAdapter( new FootballLegendListAdapter(ctx, R.layout.legend_row_item, legendList ) );
    
            // Click event for single list row
            listViewFootballLegend.setOnItemClickListener(new OnItemClickListener() {
    
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                    FootballLegend o = (FootballLegend) parent.getItemAtPosition(position);  
                    Toast.makeText(CustomlistviewActivity.this, o.getName().toString(), Toast.LENGTH_SHORT).show();
                }
            });     
        } 
    }
    

    FootballLegendListAdapter.java

    package DucNguyen.example.customlistview;
    
    public class FootballLegendListAdapter extends ArrayAdapter<FootballLegend> {
        private int             resource;
        private LayoutInflater  inflater;
        private Context         context;
        public FootballLegendListAdapter ( Context ctx, int resourceId, List<FootballLegend> objects) {
            super( ctx, resourceId, objects );
            resource = resourceId;
            inflater = LayoutInflater.from( ctx );
            context=ctx;
        }
        @Override
        public View getView ( int position, View convertView, ViewGroup parent ) { 
            convertView = ( RelativeLayout ) inflater.inflate( resource, null ); 
            FootballLegend Legend = getItem( position );
                    TextView legendName = (TextView) convertView.findViewById(R.id.legendName);
            legendName.setText(Legend.getName());
    
            TextView legendBorn = (TextView) convertView.findViewById(R.id.legendBorn);
            legendBorn.setText(Legend.getNick());
    
            ImageView legendImage = (ImageView) convertView.findViewById(R.id.legendImage);
            String uri = "drawable/" + Legend.getImage();
            int imageResource = context.getResources().getIdentifier(uri, null, context.getPackageName());
            Drawable image = context.getResources().getDrawable(imageResource);
            legendImage.setImageDrawable(image);
    
            ImageView NationImage = (ImageView) convertView.findViewById(R.id.Nation);
            uri = "drawable/" + Legend.getNation();
            imageResource = context.getResources().getIdentifier(uri, null, context.getPackageName());
            image = context.getResources().getDrawable(imageResource);
            NationImage.setImageDrawable(image);
    
            return convertView;
        }
    }
    

    FootballLegend.java

    package DucNguyen.example.customlistview;
    public class FootballLegend {
        public FootballLegend(String name, String born, String image, String nation) {
            super();
            this.name = name;
            this.born = born;
            this.image = image;
            this.nation = nation;
        }
        private String name;
        private String born;
        private String image;
        private String nation;
    
        public String getName() {
            return name;
        }
        public void setName(String nameText) {
            name = nameText;
        }
        public String getNick() {
            return born;
        }
        public void setNick(String born) {
            this.born = born;
        }
        public String getImage() {
            return image;
        }
        public void setImage(String image) {
            this.image = image;
        }
            public String getNation() {
            return nation;
        }
        public void setNation(String image) {
            this.image = nation;
        }
    }
    

    legend_row_item.xml

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:padding="5dip" >
    
        <!--  ListRow Left side Thumbnail image -->
        <LinearLayout android:id="@+id/thumbnail"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="3dip"
            android:layout_alignParentLeft="true"
            android:layout_marginRight="5dip"> 
            <ImageView
                android:id="@+id/legendImage"
                android:layout_width="50dip"
                android:layout_height="50dip" /> 
        </LinearLayout>
    
        <TextView
            android:id="@+id/legendName"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignTop="@+id/thumbnail"
            android:layout_toRightOf="@+id/thumbnail"
            android:textColor="#040404"
            android:typeface="sans"
            android:textSize="15dip"
            android:textStyle="bold"/>
    
        <TextView
            android:id="@+id/legendBorn"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_below="@id/legendName"
            android:textColor="#343434"
            android:textSize="10dip"
            android:layout_marginTop="1dip"
            android:layout_toRightOf="@+id/thumbnail"  />
    
        <ImageView
            android:id="@+id/Nation"
            android:layout_width="45dp"
            android:layout_height="30dp"
            android:layout_alignParentRight="true"
            android:layout_marginRight="5dp"
            android:layout_centerVertical="true" />
    
    </RelativeLayout>
    

    activity_customlistview.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical" >
    
        <ListView
            android:id="@+id/FootballLegend_list"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:paddingTop="5dp"
            android:choiceMode="multipleChoice" >
        </ListView>
    
    </LinearLayout>
    
  • Willis
    Willis over 9 years
    If I implement checkable for my list, will the list not have checkboxes? That is what I am trying to avoid. Thanks
  • S.D.
    S.D. over 9 years
    @Willis No. Checkable is a Java Interface. Whatever implements it, promises to have setChecked(boolean) and toggle() methods. Its entirely up to you what you want to show in the View.
  • Willis
    Willis over 9 years
    Thank you. I believe this is what I needed.