0

I'm trying to highlight (change the background color) of a row in a ListView when a user presses and releases it (after release, the highlight persists). I have read dozens of postings and for two days, I've tried everything, but can't get it to work. I've read postings that say it depends on if you're using a mouse or touchscreen. Some say it can't be done. My questions are: can this be done on this OS and with a touchscreen? And, if so, how (or what am I doing wrong)?

I'm running on an old phone (2.2.3 OS version). I read about this bug. I also am extending ArrayAdapter so each row can have an image (icon) along with text.

The following snippet is from the Activity xml for the ListView. Please note the choiceMode and listSelector:

    <ListView
    android:layout_width="match_parent"
    android:layout_height="178dp"
    android:id="@+id/listView"
    android:layout_gravity="center_horizontal"
    android:layout_weight="0.95"
    android:choiceMode="singleChoice"
    android:longClickable="false"
    android:clickable="false"
    android:listSelector="@drawable/list_view_selector"/>

Because of the bug in this old OS, I created several drawable xml files for rectangle shapes of various colors for test and debug of my attempts. Here is one for list_selector_green.xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
   android:shape="rectangle">

    <solid android:color="#00ff00" />

</shape>

My list_view_selector.xml file is:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
    android:state_selected="false"
    android:state_pressed="false"
    android:drawable="@drawable/list_selector_red" />
<item
    android:state_selected="false"
    android:state_pressed="true"
    android:drawable="@drawable/list_selector_purple" />
<item
    android:state_selected="true"
    android:state_pressed="false"
    android:drawable="@drawable/list_selector_green" />
<item
    android:state_selected="true"
    android:state_pressed="true"
    android:drawable="@drawable/list_selector_orange" />
</selector>

I created a listener for click events. I tried various things here (they're commented out).

        myListView.setOnItemClickListener(new AdapterView.OnItemClickListener()
    {

        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long arg3)
        {
            view.setSelected(true);
            //myListView.setSelection(position);
            //parent.requestFocusFromTouch(); // nothing gets selected
            //parent.setSelected(true); // something (ListView?) gets selected
            ///parent.setBackgroundColor(Color.GREEN); // makes whole listview background green
            //view.setBackgroundColor(Color.GREEN); // does nothing
            //parent.setSelection(position); // does nothing
        }
    });

So, when I press an item, the background does change color, but when I release, it goes back to "normal" which I believe is transparent. I think it's acting like nothing is getting selected. The closest I came so far was calling parent.setSelected(true) which I think selected the entire ListView. When I did this, the first press was purple and the second was orange, so the system did appear to detect something was selected. It just didn't persist.

One more thing that may be relevant. Note in my list_view_selector.xml file that if state_selected and state_pressed are false, the color is red. Thus, I was expecting the initial background to be red, but it's not--it's the default (transparent?).

Community
  • 1
  • 1

1 Answers1

0

Forget about the setSelected andlet me offer my way:

Create an array of ints, in the onClick method check if the array contains the position and if not add it.

Now all you have to do is to check in the getView method in the adapter if the position is in the array, if it is - cheange the background.

Here is some code for you:

 if(!selected_messages.contains(position))
        {
            selected_messages.add(position);             

            getViewByPosition(position, conversation_list).findViewById(R.id.messageParent).setBackgroundColor(ContextCompat.getColor(context, R.color.background_selected_message));

        }


        /// CONTAINS

        else
        {
            selected_messages.remove(selected_messages.indexOf(position));


            getViewByPosition(position, conversation_list).findViewById(R.id.messageParent).setBackgroundColor(ContextCompat.getColor(context, android.R.color.transparent));
        }

getViewByPosition method:

   public static View getViewByPosition(int pos, ListView listView)
{
    final int firstListItemPosition = listView.getFirstVisiblePosition();
    final int lastListItemPosition = firstListItemPosition + listView.getChildCount() - 1;

    if (pos < firstListItemPosition || pos > lastListItemPosition )
    {
        return listView.getAdapter().getView(pos, null, listView);
    }


    else
    {
        final int childIndex = pos - firstListItemPosition;
        return listView.getChildAt(childIndex);
    }
}

and in the adapter:

  if(selected_messages.contains(position))
            {
                convertView.findViewById(R.id.background).setBackgroundColor(ContextCompat.getColor(chat, R.color.background_selected_message));
            }

            else
            {
convertView.findViewById(R.id.background).setBackgroundColor(ContextCompat.getColor(chat, android.R.color.transparent));
            }

Finally, here is the class I use for the array since to regular one doesn't have the "contains" method.

 public static class Countable_arrayList_int extends ArrayList<Integer>
{

    @Override
    public boolean contains(Object o)
    {
        return indexOf(o) >= 0;
    }


}
Amir Horev
  • 287
  • 2
  • 3
  • So, apparently my approach won't work for the OS version. I understand your solution: you keep track of the selected item and in the custom adapter, you look for it when it gets asked for the view to display and then change the background color. It works fine. Thank you. – Jim LastName Feb 21 '16 at 00:09
  • Yes you got it, glad to help. – Amir Horev Feb 21 '16 at 17:10