4

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?

Ayushi Jha
  • 4,003
  • 3
  • 26
  • 43
  • possible duplicate of [Selecting multiple items in ListView](http://stackoverflow.com/questions/1362602/selecting-multiple-items-in-listview) – Lamorak Apr 22 '15 at 13:35
  • @Lamorak: Following the link you provided gave me a bunch of new errors. :( Please see the edited question as well. – Ayushi Jha Apr 22 '15 at 13:46
  • What happens when you click to next item? New one is selected? Nothing happens? – skywall Apr 22 '15 at 13:56
  • @skywall: No new one is not selected, only the one which I clicked first remains selected till I click it again. – Ayushi Jha Apr 22 '15 at 13:57
  • @Lamorak: I tried the list Adapter method too, the logcat gave me NullPointerException – Ayushi Jha Apr 22 '15 at 14:00
  • replace myList.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL); using myList.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); Modal is for ContexualActionBar Menu. means when you long press an item it will show you a list of menus. For normal list view dont use modal – Vishnu Prabhu Apr 22 '15 at 14:06
  • @VishnuPrabhu: Tried that too, now not even one item is selected. – Ayushi Jha Apr 22 '15 at 14:08
  • please add this, listView.setItemsCanFocus(false); and listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); – Vishnu Prabhu Apr 22 '15 at 14:11
  • @VishnuPrabhu: But I do want to use the CAB menu :( Actually I want to select multiple items so that I can delete them together. I can't even get good tutorials ( up-to-date ones) for deleting multiple items from SQLite database. – Ayushi Jha Apr 22 '15 at 14:11
  • @VishnuPrabhu: Did that too, still nothing happens – Ayushi Jha Apr 22 '15 at 14:15
  • @karma_geek I think you're assuming that a checked item will be highlighted. Have you tried logging? – Sufian Apr 22 '15 at 14:24
  • @Sufian: Yeah, I assumed that. How do I go about logging? – Ayushi Jha Apr 22 '15 at 14:26
  • Please add LongClickListener and call startActionMode like in the answer I posted. It might help you. – Vishnu Prabhu Apr 22 '15 at 14:29
  • @karma_geek try printing (but with `Log.v()`) the values of [ListView.getCheckedItemPositions()](http://developer.android.com/reference/android/widget/AbsListView.html#getCheckedItemPositions%28%29) – Sufian Apr 22 '15 at 14:33
  • @Sufian: I did not do the Log.v() (did not know how to do that), but instead I used a counter to print number of selected items in the CAB. It does print the no. of items I select, but those items are not selected. – Ayushi Jha Apr 22 '15 at 15:56
  • @karma_geek google is your friend :) – Sufian Apr 23 '15 at 05:27
  • @Sufian: Yeah, my only hope now :) – Ayushi Jha Apr 23 '15 at 11:02

2 Answers2

1

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"
Ayushi Jha
  • 4,003
  • 3
  • 26
  • 43
0

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

Vishnu Prabhu
  • 449
  • 1
  • 5
  • 19
  • What is `mActionMode`? – Ayushi Jha Apr 22 '15 at 14:30
  • Create a reference object for new AbsListView.MultiChoiceModeListener() assigned to the ListView. mActionMode is nothing but the object of ActionMode.Callback class. MultiChoiceModeListener() extends the ActionMode.CallBack. Set an object refer to your MultiChoiceModeListnener. OnLongPress call that object's startActionMode(multichoiceListnener object) – Vishnu Prabhu Apr 22 '15 at 14:35
  • It shows cannot resolve symbol getActivity() and mActionModeCallback – Ayushi Jha Apr 22 '15 at 14:37
  • You have implemented multichoice listener twice once as an anonymous class and one by the activity itself. Please check with above. – Vishnu Prabhu Apr 22 '15 at 15:00
  • I got your second point about implementing multichoice listener twice, however, still nothing happens when another item is clicked. – Ayushi Jha Apr 22 '15 at 15:41
  • Okay, I can select the items but how to highlight them? – Ayushi Jha Apr 22 '15 at 16:11
  • You have the check box to indicate the item selected, why you want to highlight the item. If your requirement is to no to show checkbox and hightlight the selected item, use as it says in the example I provided in the above sample path.From the sample /** * This demo illustrates 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. */setListAdapter(new ArrayAdapter(this, android.R.layout.simple_list_item_activated_1, Cheeses.sCheeseStrings)); – Vishnu Prabhu Apr 23 '15 at 04:50
  • To hightlight your background by default use the android.R.layout.simple_list_item_activated_1 instead of android.R.layout.simple_list_item_multiple_choice in the above code.,.If you have a custom layout for your list item, add background as a Selector to your item, and in that selector use android:selected = true case to show your own hightlighted color. – Vishnu Prabhu Apr 23 '15 at 04:56
  • Not yet, still trying to understand the Selector you mentioned. – Ayushi Jha Apr 23 '15 at 11:38
  • If you can send me your files for R.layout.tasks, drawables and pojo classed to vishnu.prokarma@gmail.com I can see what the issue is. – Vishnu Prabhu Apr 23 '15 at 11:42
  • Did you try changing the layout resource id passed to the ArrayAdapter, as android.R.layout.simple_list_item_activated_1. – Vishnu Prabhu Apr 23 '15 at 11:44
  • Yes, I have changed that. The only problem I am facing is that once I select an item, it gets into checked state perfectly, but when I select another item, both are checked, but the previous one is not highlighted any more. – Ayushi Jha Apr 23 '15 at 11:51
  • Edited the question. What else should I add? – Ayushi Jha Apr 23 '15 at 13:46
  • Thanks for guiding! I got my answer through your comments, I finally know how to use selectors. – Ayushi Jha Apr 25 '15 at 13:54