Ayushi Jha
Ayushi Jha

Reputation: 4023

Android: Check multiple items ListView

I am trying to implement multiple items selection in a ListView. The List is managed using the CursoAdapter. I was following the tutorials at http://developer.android.com/guide/topics/ui/menus.html#CAB. However, when I run the app, only 1 item is selected (highlighted). Can you point out, What am I doing wrong?

MainActivity.java

public class MainActivity extends ActionBarActivity {
DbHelper db;
ListView myList;
ActionMode mActionMode;
int checkedCount;
private static final String[] GENRES = new String[] {
        "Action", "Adventure", "Animation", "Children", "Comedy", "Documentary", "Drama",
        "Foreign", "History", "Independent", "Romance", "Sci-Fi", "Television", "Thriller"
};

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    db = new DbHelper(this);
    myList = (ListView) findViewById(R.id.newList);
    ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
            android.R.layout.simple_list_item_activated_1, GENRES);
    myList.setAdapter(adapter);

    loadData();

    myList.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
    myList.setItemsCanFocus(false);
    myList.setOnLongClickListener(new View.OnLongClickListener() {
        // Called when the user long-clicks on someView
        public boolean onLongClick(View view) {
            if (mActionMode != null) {

                return false;

            }

            // Start the CAB using the ActionMode.Callback defined above
        //    mActionMode = getActivity().startActionMode(mActionMode.Callback);

            view.setSelected(true);
            view.setBackgroundColor(25);
            return true;
        }
    });
    myList.setMultiChoiceModeListener(new AbsListView.MultiChoiceModeListener() {

        @Override
        public void onItemCheckedStateChanged(ActionMode mode, int position,
                                              long id, boolean checked) {
            // Here you can do something when items are selected/de-selected,
            // such as update the title in the CAB
         //   Log.v(ListView.getCheckedItemPositions());
            if(checked)
            {
                checkedCount++;
            }
            else checkedCount--;
            mode.setTitle(checkedCount+" selected");
        }

        @Override
        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
            // Respond to clicks on the actions in the CAB
            switch (item.getItemId()) {
                case R.id.menu_delete:
                    //   deleteSelectedItems();
                    mode.finish(); // Action picked, so close the CAB
                    return true;
                default:
                    return false;
            }
        }

        @Override
        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
            // Inflate the menu for the CAB
            menu.clear();
            checkedCount=0;
            MenuInflater inflater = mode.getMenuInflater();
            inflater.inflate(R.menu.context_main, menu);
            return true;
        }


        public void onDestroyActionMode(ActionMode mode) {
            // Here you can make any necessary updates to the activity when
            // the CAB is removed. By default, selected items are deselected/unchecked.
        }


        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
            // Here you can perform updates to the CAB due to
            // an invalidate() request
            return false;
        }
    });
}

public void onResume()
{
    super.onResume();
    loadData();
}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    menu.clear();
    getMenuInflater().inflate(R.menu.menu_main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}
public void loadData()
{
    Cursor cursor = null;
    try {
        cursor = db.fetchData();
    }
    catch(NullPointerException e)
    {
        e.printStackTrace();
    }
    ListAdapter myAdapter = new SimpleCursorAdapter(this, R.layout.tasks,
            cursor,
            new String[]{db._ID, db.COLUMN_1, db.COLUMN_2},
            new int[]{R.id.idnum, R.id.c1, R.id.c2}, 0);
    myList.setAdapter(myAdapter);


}
public void addNew(View v)
{
    Intent intent = new Intent(this,AddActivity.class);
    startActivity(intent);

}
}

activity_main.xml

<RelativeLayout 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:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">

<TextView android:text="@string/welcome"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:textSize="20sp"
    android:id="@+id/topic"
/>
<ListView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:id="@+id/newList"
    android:layout_below="@+id/topic"
    android:layout_above="@+id/MainButtons"
    android:choiceMode="multipleChoice"
    android:listSelector="@color/background_material_dark"

    ></ListView>
<LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:id="@+id/MainButtons"
>
<Button
    android:layout_width="wrap_content"
    android:layout_height="fill_parent"
    android:layout_weight="1"
    android:text="@string/add"
    android:id="@+id/addButton"
    android:onClick="addNew"
/>
<Button
    android:layout_width="wrap_content"
    android:layout_height="fill_parent"
    android:layout_weight="1"
    android:text="@string/edit"
    android:id="@+id/editButton"
/>
<Button
    android:layout_width="wrap_content"
    android:layout_height="fill_parent"
    android:layout_weight="1"
    android:text="@string/del"
    android:id="@+id/deleteButton"
/>
</LinearLayout>

</RelativeLayout>

tasks.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent">
<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/idnum"
    android:paddingRight="20dp"

    />
<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/c1"
    android:layout_toRightOf="@+id/idnum"
    android:paddingRight="20dp"
   />
<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/c2"
    android:layout_toRightOf="@+id/c1"
    />
</RelativeLayout>

menu_main.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" tools:context=".MainActivity">
<item android:id="@+id/action_settings" android:title="@string/action_settings"
    android:orderInCategory="100" app:showAsAction="always"
   />

</menu>

Please comment if I need to add more details.

Edit: I looked at the duplicate question. However, majority of answers suggested using an ArrayAdapter, whereas items in my list are managed using SQLite, and each item consists of 3 separate items (no, text1, text2). How can I make use of an ArrayAdapter here? Also, one highly voted answer says to use CheckedTextView. So shall I use CheckedTextView for all the 3 parts of a list item?

Upvotes: 4

Views: 2818

Answers (2)

Ayushi Jha
Ayushi Jha

Reputation: 4023

I finally solved this by using a selector. Here is the selector.xml file:

<?xml version="1.0" encoding="utf-8"?>

<selector xmlns:android="http://schemas.android.com/apk/res/android">

<item android:state_checked="true"
    android:drawable="@color/link_text_material_dark"

    />
<item android:state_active="true"
android:drawable="@color/primary_dark_material_dark"
/>
<item android:state_selected="true"
    android:drawable="@color/highlighted_text_material_dark"
    />

<item android:state_activated="true" android:drawable="@android:color/white" />

</selector> 

The most important one is the state_activated item. It is used to highlight all those items which are selected.

Also, in order to use this selector, add the following line to tasks.xml or wherever you have defined each row (item):

android:background="@drawable/selector"

Upvotes: 1

Vishnu Prabhu
Vishnu Prabhu

Reputation: 459

I have modified you code, added little changes. If you still have issues, please follow the sample in you sdk samples folder it will be in the following location.

sdks\samples\android-14\ApiDemos\src\com\example\android\apis\view\List16.java

        public class MainActivity extends ActionBarActivity {

            private static final String[] GENRES = new String[] {
                    "Action", "Adventure", "Animation", "Children", "Comedy", "Documentary", "Drama",![enter image description here][2]
                    "Foreign", "History", "Independent", "Romance", "Sci-Fi", "Television", "Thriller"
            };


            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
                ListView myList = (ListView) findViewById(R.id.newList);

    /**
     * the use of CHOICE_MODE_MULTIPLE_MODAL, a.k.a. selection mode on ListView
     * couple with the new simple_list_item_activated_1 which uses a highlighted    border for selected
     * items.
     */
                ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
                        android.R.layout.simple_list_item_activated_1, GENRES);
                myList.setAdapter(adapter);
                myList.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
                myList.setMultiChoiceModeListener(new AbsListView.MultiChoiceModeListener() {

                    @Override
                    public void onItemCheckedStateChanged(ActionMode mode, int position,
                            long id, boolean checked) {
                        // Here you can do something when items are selected/de-selected,
                        // such as update the title in the CAB
                    }

                    @Override
                    public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
                        // Respond to clicks on the actions in the CAB
                        switch (item.getItemId()) {
                            case R.id.action_settings:
                                //   deleteSelectedItems();
                                mode.finish(); // Action picked, so close the CAB
                                return true;
                            default:
                                return false;
                        }
                    }

                    @Override
                    public boolean onCreateActionMode(ActionMode mode, Menu menu) {
                        // Inflate the menu for the CAB
                        MenuInflater inflater = mode.getMenuInflater();
                        inflater.inflate(R.menu.menu_main, menu);
                        return true;
                    }


                    public void onDestroyActionMode(ActionMode mode) {
                        // Here you can make any necessary updates to the activity when
                        // the CAB is removed. By default, selected items are deselected/unchecked.
                    }


                    public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
                        // Here you can perform updates to the CAB due to
                        // an invalidate() request
                        return false;
                    }
                });

            }
        }

![enter image description here][1]


menu_main.xml

    <menu xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools" tools:context=".MainActivity">
        <item android:id="@+id/action_settings" android:title="@string/action_settings"
            android:orderInCategory="100" app:showAsAction="always" android:icon="@drawable/ic_launcher" />
    </menu>


activity_main.xml is same as your layout.

enter image description here

Upvotes: 0

Related Questions