2

I've got an activity which has a ListView and I've created a custom Adapter based on BaseAdapter.

The GetView method of the custom adapter uses a custom layout:

view = context.LayoutInflater.Inflate(Resource.Layout.BluetoothDeviceListItem, null);

The layout looks like this:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="@drawable/BluetoothDeviceListSelector">  
  <TextView android:id="@+id/txtBluetoothDeviceName"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="5dp"
            style="@android:style/TextAppearance.Large"/>
  <TextView android:id="@+id/txtBluetoothDeviceAddress"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="5dp"
            style="@android:style/TextAppearance.Medium"/>
</LinearLayout>

Basically I display the name of the Bluetooth device and it's address underneath.
But I'd like the user to be able to select an item in the ListView and that item should remain highlighted (at the very least) or I might want to add an icon to it or whatever.

As I understand it, since I'm using a custom layout, I lose the default selection indicator and have to use my own selector. I found something like this in an online tutorial:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:state_pressed="true" >
    <shape>
      <gradient
       android:startColor="#E77A26"
         android:endColor="#1DB38B"
         android:angle="270" />
    </shape>
  </item>
  <item android:state_selected="true">
    <shape>
      <gradient
       android:startColor="#E77A26"
         android:endColor="#2B37AE"
         android:angle="270" />
    </shape>
  </item>
  <item android:state_focused="true">
    <shape>
      <gradient
       android:startColor="#E77A26"
         android:endColor="#EEFFEE"
         android:angle="270" />
    </shape>
  </item>
</selector>

But the only thing that does is change the color as long as the user presses and holds an item in the ListView. As soon as he lets go, nothing is highlighted anymore.

Now I can't figure out what's really causing the problem.

  • Did my ListView lose selection support somewhere along the way
  • Is the XML for the Selector simply wrong
  • Should I add selection support to the Adapter (which seems strange as it should be independent of the view)

Disclaimer: I've seen a few related questions, but they do not really help me.
also, I'm currently unable to get to most of the online documentation due to the great wall

TimothyP
  • 21,178
  • 26
  • 94
  • 142
  • 1
    If you are on Android 3.0+, use the `activated` state for this: http://stackoverflow.com/questions/9729517/showing-the-current-selection-in-a-listview – CommonsWare Feb 25 '13 at 14:57
  • Ok that worked like a charm. I'd like to mark your comment as the answer, but that doesn't work. Will you post it as an answer so I can mark it (as I think it might be useful for others as well) or should I delete the question as it's more or less a duplicate, although different enough in my opinion? – TimothyP Feb 25 '13 at 15:10
  • If you took a sufficiently different approach than my answer on that other question, you probably should write your own answer, outlining what you did. Similarly, if you want to provide more details than my nutshell recipe, your own answer would be awesome! – CommonsWare Feb 25 '13 at 20:53

2 Answers2

3

In the end, based on @CommonsWare comments I simply used the activated state:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:state_pressed="true" >
    <shape>
      <gradient
       android:startColor="#E77A26"
         android:endColor="#1DB38B"
         android:angle="270" />
    </shape>
  </item>
  <item android:state_activated="true">
    <shape>
      <gradient
       android:startColor="#E77A26"
         android:endColor="#EEFFEE"
         android:angle="270" />
    </shape>
  </item>
</selector>

That said, I have now moved away from displaying the selected item and I simply navigate to a new Activity directly upon clicking an item in order to comply with Android design guidelines.

TimothyP
  • 21,178
  • 26
  • 94
  • 142
1

You could keep the selected position in memory. In your adapter, add a variable to store the selected item. Then inside your getView() method, if the current position equals your selected item, do something different. If you want to highlight your item, setBackgroundColor().

Here is an example

 @Override public View getView(int position, View convertView,
    ViewGroup parent) {

        View row = convertView;

        if (row == null) {      
            LayoutInflater inflater = (LayoutInflater) this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);         
             row = inflater.inflate(R.layout.my_xml_file, parent,false);    }
        if(position==selectedPosition){            
             row.setBackgroundColor(Color.parseColor("#800ff000"));     }   
        else{       
             row.setBackgroundColor(Color.TRANSPARENT);     }

       return row; }
Gordak
  • 2,060
  • 22
  • 32
  • The problem with this is that is violates separation of concerns. – TimothyP Feb 25 '13 at 16:20
  • "that item should remain highlighted (at the very least) or I might want to add an icon to it or whatever." That would enable the customization of the view of the item a bit more ;) – Gordak Feb 25 '13 at 17:00
  • I'll look into your solution as well. Meanwhile I've used the activated state. But that might not allow me to add the icon, your solution might. – TimothyP Feb 25 '13 at 17:12
  • You would also need to use the method 'notifydatasetchanged()' when you click on an item of your list in order to rebuild the view. – Gordak Feb 27 '13 at 14:23
  • Ah yes, that part I figured out – TimothyP Feb 27 '13 at 14:28