Monday, November 12, 2012

Implement custom multi select ListView with custom ArrayAdapter

The post "Multi Choice ListView" demonstrate how to implement multi select ListView with build-in layout with simple TextView. This exercise demonstrate how to implement multi select ListView with custom layout, using custom ArrayAdapter.

custom multi select ListView


Create /res/layout/row.xml to define the layout of rows in our custom ListView.
<?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="wrap_content"
    android:orientation="horizontal">
    
    <ImageView 
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:src="@drawable/ic_launcher"/>
    <CheckedTextView
        android:id="@+id/text1"
        android:layout_width="match_parent"
        android:layout_height="?android:attr/listPreferredItemHeightSmall"
        android:textAppearance="?android:attr/textAppearanceListItemSmall"
        android:gravity="center_vertical"
        android:checkMark="?android:attr/listChoiceIndicatorMultiple"
        android:paddingLeft="?android:attr/listPreferredItemPaddingLeft"
        android:paddingRight="?android:attr/listPreferredItemPaddingRight"/>
</LinearLayout>


Layout of our example.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <Button
        android:id="@+id/getresult"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Get Result"/>
    <ListView
        android:id="@+id/list"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>


Main Java code.
package com.example.androidmultichoicelist;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckedTextView;
import android.widget.ListView;
import android.widget.Toast;

public class MainActivity extends Activity {
 
 ListView myListView;
 Button getResult;
 
 private ArrayList<String> dayOfWeekList = new ArrayList<String>();

 private void initDayOfWeekList(){
  dayOfWeekList.add("Sunday");
  dayOfWeekList.add("Monday");
  dayOfWeekList.add("Tuesday");
  dayOfWeekList.add("Wednesday");
  dayOfWeekList.add("Thursday");
  dayOfWeekList.add("Friday");
  dayOfWeekList.add("Saturday");
  
 }
 
 MyArrayAdapter myArrayAdapter;
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initDayOfWeekList();
        setContentView(R.layout.activity_main);
        
        myListView = (ListView)findViewById(R.id.list);

        myArrayAdapter = new MyArrayAdapter(
          this,
          R.layout.row,
          android.R.id.text1,
          dayOfWeekList
          );
        
        myListView.setAdapter(myArrayAdapter);
        myListView.setOnItemClickListener(myOnItemClickListener);
        
        getResult = (Button)findViewById(R.id.getresult);
        getResult.setOnClickListener(new OnClickListener(){

   @Override
   public void onClick(View v) {
    String result = "";
    
    /*
    //getCheckedItemPositions
    List<Integer> resultList = myArrayAdapter.getCheckedItemPositions();
    for(int i = 0; i < resultList.size(); i++){
     result += String.valueOf(resultList.get(i)) + " ";
    }
    */
    
    //getCheckedItems
    List<String> resultList = myArrayAdapter.getCheckedItems();
    for(int i = 0; i < resultList.size(); i++){
     result += String.valueOf(resultList.get(i)) + "\n";
    }
    
    myArrayAdapter.getCheckedItemPositions().toString();
    Toast.makeText(
      getApplicationContext(), 
      result, 
      Toast.LENGTH_LONG).show();
   }});
        
    }
    
    OnItemClickListener myOnItemClickListener
    = new OnItemClickListener(){

  @Override
  public void onItemClick(AdapterView<?> parent, View view, int position,
    long id) {
   myArrayAdapter.toggleChecked(position);
   
  }};
    
    private class MyArrayAdapter extends ArrayAdapter<String>{
     
     private HashMap<Integer, Boolean> myChecked = new HashMap<Integer, Boolean>();

  public MyArrayAdapter(Context context, int resource,
    int textViewResourceId, List<String> objects) {
   super(context, resource, textViewResourceId, objects);
   
   for(int i = 0; i < objects.size(); i++){
    myChecked.put(i, false);
   }
  }
     
  public void toggleChecked(int position){
   if(myChecked.get(position)){
    myChecked.put(position, false);
   }else{
    myChecked.put(position, true);
   }
   
   notifyDataSetChanged();
  }
  
  public List<Integer> getCheckedItemPositions(){
   List<Integer> checkedItemPositions = new ArrayList<Integer>();
   
   for(int i = 0; i < myChecked.size(); i++){
    if (myChecked.get(i)){
     (checkedItemPositions).add(i);
    }
   }
   
   return checkedItemPositions;
  }
  
  public List<String> getCheckedItems(){
   List<String> checkedItems = new ArrayList<String>();
   
   for(int i = 0; i < myChecked.size(); i++){
    if (myChecked.get(i)){
     (checkedItems).add(dayOfWeekList.get(i));
    }
   }
   
   return checkedItems;
  }

  @Override
  public View getView(int position, View convertView, ViewGroup parent) {
   View row = convertView;
   
   if(row==null){
    LayoutInflater inflater=getLayoutInflater();
    row=inflater.inflate(R.layout.row, parent, false);  
   }
   
   CheckedTextView checkedTextView = (CheckedTextView)row.findViewById(R.id.text1);
   checkedTextView.setText(dayOfWeekList.get(position));
   
   Boolean checked = myChecked.get(position);
   if (checked != null) {
    checkedTextView.setChecked(checked);
            }
   
   return row;
  }
  
    }

}


download filesDownload the files.

8 comments:

Unknown said...

I was searching for this from last three days but wasn't able to get anything as according to my need. Thanks for such a wonderful example, keep up the good work. Really, Thanks again.

Unknown said...

i tried but i'm getting blank listview

Unknown said...

Hi, how to change textcolor and text size

Erik said...

Edit CheckedTextView in xml, i think.

Hank said...

I have been looking for a sample that I could use with my cursor adaptor and finally stumbled upon this.

With some tweaking I think my problems are solved.

Thanks

Juan said...

Hi there! nice tutorial, quick question, what about if images on the right are different for each item? any advice?

Unknown said...

Can we add search funtionality to this?

Anonymous said...

Thanks.It's make my day.Thank you very much