10

Hello guys I want to highlight multiple items in a list view.

So I tried SngList.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); but it didn't help

I am using a custom adapter and extending BaseAdapter

I am using ListView and not AbsListView

I don't want to use CAB because it doesn't go well with the design of my app

I don't want to use the getView method of the adapter as well.

I don't want to use checkboxes either, I guess I will use a boolean for each item and pass it to getviews if I don't get a solution here, but that doesn't seem too elegant and neat. I believe there is a proper built-in way of doing it without using getview() of the adapter

I tried:

android:drawSelectorOnTop="false"
android:listSelector="@android:color/darker_gray"

in the xml but it is highlighting only one of the items and as soon as I click on another item, it highlights it instead...

So is there any proper way of doing it?

Here is how my app looks:

enter image description here

Ankit Srivastava
  • 853
  • 1
  • 9
  • 28

3 Answers3

3
SngList.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);

It should be enough, but you have to use getView, to differentiate the selected and unselected state.

You can use isItemChecked() method to determine weather the item is selected or not, so you don't have to introduce a boolean variable for each items.

Edit:

Something like this:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    ListView list = (ListView) parent;

    if(list.isItemChecked(position)){
        //...
    }
    else{
        //...
    }
kupsef
  • 3,357
  • 1
  • 21
  • 31
  • please elaborate..i am already using choice_mode multiple i should create a list of all the highlighted items right ? then while generating the view in the adapter i should create a check ? or what are you suggesting please elaborate – Ankit Srivastava May 04 '14 at 19:00
  • That is the essence of choice_mode_multiple. You don't have to maintaint a list, because ListView does it for you in that mode. – kupsef May 04 '14 at 19:16
  • okay understood..will i have set a different background (for the highlighted ) or is there any direct method? i am using view reusability with view holder pattern,how to handle it? will it update automatically if i uncheck it – Ankit Srivastava May 04 '14 at 19:19
  • Well, I don't really understand you, but its up to you how to differentiate the selected and unselected state. As far as I know there is no built-in design for that, so you have to do it just like in the if-else section I presented above. This state change is handled internally, so it should be fine even with the ViewHolder pattern. The important thing is to handle the isItemChanged() logic correct. – kupsef May 04 '14 at 19:26
  • just as i suspected,your solution works but not with viewholder pattern...wrong items are getting higlighted too – Ankit Srivastava May 04 '14 at 19:36
  • just like here http://stackoverflow.com/questions/4010623/android-click-on-listitem-checks-wrong-checkbox – Ankit Srivastava May 04 '14 at 19:37
  • Well, this solution works with ViewHolder pattern (I did it in the past:) In addition the linked question has nothing to do with this topic. I don't how you managed to broke it, but you don't have to maintain the checked state of the items, because the ListView does it for you:) You don't even need manipulate the checked state in setOnItemClickListener(), because ListView does that also for you. All you have to do is to implement the getView() method correct. – kupsef May 04 '14 at 20:21
3

You can make the same logic as CAB but avoid using CAB.

Your list item should have the FrameLayout at root like

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:foreground="?android:attr/activatedBackgroundIndicator">

....

Set onItemClickListener to change choice mode on long press

listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {

    @Override
    public boolean onItemLongClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
        if (mInMultiChoiceMode) {
            // if already in multi choice - do nothing
            return false;
        }

        mInMultiChoiceMode = true;
        // set checked selected item and enter multi selection mode
        final AbsListView list = (AbsListView) arg0;
        list.setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE);
        list.setItemChecked(arg2, true);

        return true;
    }
});

listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
        if (mInMultiChoiceMode) {
            //exit multi choice mode if number of selected items is 0
            if (((AbsListView) arg0).getCheckedItemCount() == 0) {
                ((AbsListView) arg0).setChoiceMode(AbsListView.CHOICE_MODE_NONE);
                mInMultiChoiceMode = false;
            }
        } else {
            // do whatever you should as in normal non-multi item click
            System.out.println("CLICK");
        }
    }
});
Yaroslav Mytkalyk
  • 16,950
  • 10
  • 72
  • 99
  • yes i have already implemented the first part but in the onitemclick i want it to be highlighted and that is the question..how to highlight it ?please read it again if you haven't – Ankit Srivastava May 04 '14 at 19:01
  • It is highlighted automatically by AbsListView when setting android:foreground="?android:attr/activatedBackgroundIndicator" on list item, and calling listView.setItemChecked(arg2, true); in CHOICE_MODE_MULTIPLE. – Yaroslav Mytkalyk May 04 '14 at 19:02
  • is the framelayout essential ? – Ankit Srivastava May 04 '14 at 19:06
  • i am using a listview instead of abslistview – Ankit Srivastava May 04 '14 at 19:07
  • i changed everything to abslistview and it crashed at line view = (ViewGroup) inflater.inflate(R.layout.l_songs, null); – Ankit Srivastava May 04 '14 at 19:09
  • @AnkitSrivastava ListView extends AbsListView (as well as GridView, so no need to cast to lower level). I uses the FrameLayout because it has foregound Drawable feature. I.e the highlighted drawable will be drawn on top of the content. But you can set it as android:background of any View as well. – Yaroslav Mytkalyk May 04 '14 at 19:09
  • @AnkitSrivastava you don't get it. The ListView is AbsListView descendant. Use the ListView in layout, but cast to AbsListView in code. Actually you can cast to ListView, it's a matter of preference to which level to cast, I always choose the highest level. – Yaroslav Mytkalyk May 04 '14 at 19:10
  • where should i put this ?? android:foreground="?android:attr/activatedBackgroundIndicator" – Ankit Srivastava May 04 '14 at 19:14
  • It should be the attribute of the root FrameLayout of the list item layout. Or oi you want to avoid FrameLayout, set it as android:background of the root view of your list item layout. – Yaroslav Mytkalyk May 04 '14 at 19:22
  • but the root item doesn't recognize it,it's linearlayout it doesn't give an error but it doesn't come up in autocomplete and it doesn't doo anything too – Ankit Srivastava May 04 '14 at 19:25
  • @AnkitSrivastava LinearLayout doesn't have android:foreground attribute, only FrameLayout has it. Use android:background for LinearLayout. I've created a test project here http://goo.gl/H7y0Ft – Yaroslav Mytkalyk May 04 '14 at 19:28
  • I am using a custom adapter ...which extends base adapter – Ankit Srivastava May 04 '14 at 19:41
  • @AnkitSrivastava so what's the difference? If your list item is not inflated from layout, but instead created by code, you can set the attribute in code as well. I mean the only thing you need is updating the layout if it's inflated in `getView()`. The highlight is done via `ListView` itself, so you don't need to handle it in `getView ()` as long as the background or foreground is `?android:attr/activatedBackgroundIndicator` – Yaroslav Mytkalyk May 04 '14 at 19:44
  • how to use arraadapter if i have more than 1 text fields? – Ankit Srivastava May 04 '14 at 19:52
  • in each item of the list – Ankit Srivastava May 04 '14 at 19:53
  • @AnkitSrivastava you don't need to change to an ArrayAdapter nor to ListActivity, just use the BaseAdapter you had. – Yaroslav Mytkalyk May 04 '14 at 19:54
  • will i have to use setListAdapter(new ArrayAdapter(this, R.layout.listitem, android.R.id.text1, items)); three times with 3different arrays and ids? – Ankit Srivastava May 04 '14 at 19:54
  • @AnkitSrivastava don't change the Adapter code. Just add the activatedBackgroundIndicator to layout, add the click listeners on ListView I posted and you should be done. – Yaroslav Mytkalyk May 04 '14 at 19:55
  • i need a frame layout right ?because i already said ,it doesn't work with linear layout right ?for using this ? android:attr/activatedBackgroundIndicator – Ankit Srivastava May 04 '14 at 19:55
  • @AnkitSrivastava in LinearLayout, set android:background="?android:attr/activatedBackgroundIndicator". – Yaroslav Mytkalyk May 04 '14 at 19:57
  • @AnkitSrivastava sure, the ListAdapter code doesn't have anything to do with this. – Yaroslav Mytkalyk May 04 '14 at 19:59
1

use SngList.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);

then manually do it in the adapter.

Billy
  • 11
  • 4