1

I have gone over several SO answers now
Android listselector not visible in custom listview
ListView item background via custom selector

and even followed this to the point (currently using this approach)
http://cyrilmottier.com/2011/08/08/listview-tips-tricks-3-create-fancy-listviews/

I have even set the drawSelectorOnTop to true

However, I cannot get the listSelector to work. Basically, I am at my wit's end. I guess it has something to do with the way my list item is made? Here is the XML:

list_entry.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="wrap_content"
    android:padding="5dp">

    <ImageButton android:id="@+id/contextMenuIcon"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_action_overflow"
        android:background="@null"/>

    <TextView android:id="@+id/noteTitle"
        android:layout_alignParentLeft="true"
        android:layout_toLeftOf="@id/contextMenuIcon"
        android:layout_alignBottom="@id/contextMenuIcon"
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:layout_alignParentTop="true"
        android:textIsSelectable="false"
        android:ellipsize="end"
        android:singleLine="true"
        android:textSize="20sp"
        android:textColor="@android:color/black"/>

    <TextView android:id="@+id/noteCreationDate"
        android:layout_alignParentLeft="true"
        android:layout_alignParentBottom="true"
        android:layout_below="@id/noteTitle" 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="18sp"
        android:textColor="#808080"/>

    <TextView android:id="@+id/notePrivacy"
        android:layout_alignParentRight="true"
        android:layout_alignParentBottom="true"
        android:layout_below="@id/contextMenuIcon"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="18sp"
        android:textColor="#808080" />

</RelativeLayout>    

list_selector_pressed.xml

<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
    <gradient android:endColor="#ffc579" android:startColor="#fb9d23" android:angle="90"></gradient>
</shape>  

list_selector_focussed.xml

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

    <gradient android:endColor="#f7ddb8" android:startColor="#f5c98c" android:angle="90"></gradient>

</shape>  

list_selector.xml

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

    <item android:state_pressed="true" android:drawable="@drawable/list_selector_pressed" />
    <item android:state_focused="true" android:drawable="@drawable/list_selector_focused" />
    <item android:drawable="@android:color/transparent" />

</selector>

Please tell me how to make the list selector work!

Community
  • 1
  • 1
An SO User
  • 24,612
  • 35
  • 133
  • 221

3 Answers3

2

You are using ImageButton inside a list item. So when ever you click the item, the ImageButton will get the focus.

But in your case you set ImageButton back ground is

  android:background="@null"

It make you cannot see the focus. You can see the problem if you remove this line.

To get the focus from the list item, you can use this code in the root view of your xml.

android:descendantFocusability="blocksDescendants"   

<?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="wrap_content"
    android:descendantFocusability="blocksDescendants" 
    android:padding="5dp">

    <ImageButton android:id="@+id/contextMenuIcon"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_action_overflow"
        android:background="@null"/>

    <TextView android:id="@+id/noteTitle"
        android:layout_alignParentLeft="true"
        android:layout_toLeftOf="@id/contextMenuIcon"
        android:layout_alignBottom="@id/contextMenuIcon"
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:layout_alignParentTop="true"
        android:textIsSelectable="false"
        android:ellipsize="end"
        android:singleLine="true"
        android:textSize="20sp"
        android:textColor="@android:color/black"/>

    <TextView android:id="@+id/noteCreationDate"
        android:layout_alignParentLeft="true"
        android:layout_alignParentBottom="true"
        android:layout_below="@id/noteTitle" 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="18sp"
        android:textColor="#808080"/>

    <TextView android:id="@+id/notePrivacy"
        android:layout_alignParentRight="true"
        android:layout_alignParentBottom="true"
        android:layout_below="@id/contextMenuIcon"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="18sp"
        android:textColor="#808080" />

</RelativeLayout>  

I create a quick test with your xml and it work normal.

public class MainActivity extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if (savedInstanceState == null) {
            getSupportFragmentManager().beginTransaction().add(R.id.container, new PlaceholderFragment()).commit();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {

        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.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();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    /**
     * A placeholder fragment containing a simple view.
     */
    public class PlaceholderFragment extends Fragment {

        public PlaceholderFragment() {
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            View rootView = inflater.inflate(R.layout.fragment_main, container, false);

            ListView list = (ListView)rootView.findViewById(R.id.list);

            ArrayList<MyItem> listItem = genListItem(20);
            MyAdapter adapter = new MyAdapter(MainActivity.this, android.R.layout.simple_list_item_1, listItem);
            list.setAdapter(adapter);


            return rootView;
        }

        private ArrayList<MyItem> genListItem(int size) {
            ArrayList<MyItem> listItem = new ArrayList<MainActivity.MyItem>();
            for (int i = 0; i < size; i++) {
                MyItem item = new MyItem();
                item.setName("item " + i);
                listItem.add(item);
            }

            return listItem;
        }
    }

    public static class MyItem{
        String Name;
        /**
         * @return the name
         */
        public String getName() {
            return Name;
        }
        /**
         * @param name the name to set
         */
        public void setName(String name) {
            Name = name;
        }


    }

    public class MyAdapter extends ArrayAdapter<MyItem>{

        private LayoutInflater inflator;
        private Context mContext;
        public MyAdapter(Context context, int resource, List<MyItem> objects) {
            super(context, resource, objects);
            mContext = context;
            inflator = ((Activity) context).getLayoutInflater();
        }

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

            final ViewHolder holder;
            if (convertView == null) {
                convertView = inflator.inflate(R.layout.list_entry, null);
                holder = new ViewHolder();
                holder.Name = (TextView) convertView.findViewById(R.id.noteTitle);
                convertView.setTag(holder);
            } else {
                holder = (ViewHolder) convertView.getTag();
            }

            MyItem item = getItem(position);
            holder.Name.setText(item.getName());


            return convertView;
        }

        class ViewHolder {
            public TextView Name;
        }


    }

}
Hinte
  • 111
  • 5
  • so if I remove the `@null` background and add that `descendantFocusability` line, it will work?> – An SO User Jun 23 '14 at 03:46
  • no need to remove the @null background if you dont want to see the focus in the ImageButton – Hinte Jun 23 '14 at 03:50
  • Still does not work. Can you make it work and post a screenshot? :) I have spent 8 hours on this already :) – An SO User Jun 23 '14 at 03:53
  • I understood that. The whole point is that the selector does not appear :) – An SO User Jun 23 '14 at 03:57
  • In the listitem_selector.xml you use '' but the name must be 'list_selector_focussed.xml' ( with 2 "s" ). Can you check if this is a problem or not? – Hinte Jun 23 '14 at 04:25
  • The fu**kin problem is/was that the app was in full screen mode. The moment I changed the theme back to default, the problem went away. How and why, I dunno? – An SO User Jun 23 '14 at 04:43
0

According to my experience, For a listSelector to work, you have to use CheckedTextView as the root element of your List Item.

<?xml version="1.0" encoding="utf-8"?>
<!-- Added this view purposefully -->
<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/text"
    android:layout_width="match_parent"
    android:layout_height="@dimen/_48dp"
    android:layout_centerVertical="true"
    android:background="@drawable/selector_liquidation"
    android:gravity="center_vertical|left"
    android:paddingBottom="@dimen/_15dp"
    android:paddingLeft="@dimen/_40dp"
    android:paddingRight="@dimen/_10dp"
    android:paddingTop="@dimen/_15dp"
    android:singleLine="true"
    android:textColor="@color/gray_999999"
    android:textSize="@dimen/font_18sp" />

I would suggest you to try using a single CheckedTextView at first, then if it works, use the selector on the Dummy Button in your list item and set the state of the button to be selected in the getView.

UPDATE

list item

<?xml version="1.0" encoding="utf-8"?>
<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"
    tools:context=".ui.video.VideoPlayerActivity" >

    <RelativeLayout
        android:id="@+id/dummy"
        android:layout_width="match_parent"
        android:layout_height="@dimen/_100dp"
        android:gravity="center_vertical" >

        <Button
            android:id="@+id/bg_selector"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@drawable/selector_item"
            android:clickable="false"
            android:focusable="false" />

        <ImageButton
            android:id="@+id/contextMenuIcon"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_alignParentTop="true"
            android:background="@null"
            android:src="@drawable/ic_action_overflow" />

        <TextView
            android:id="@+id/noteTitle"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignBottom="@id/contextMenuIcon"
            android:layout_alignParentLeft="true"
            android:layout_alignParentTop="true"
            android:layout_toLeftOf="@id/contextMenuIcon"
            android:ellipsize="end"
            android:singleLine="true"
            android:textColor="@android:color/black"
            android:textIsSelectable="false"
            android:textSize="20sp" />

        <TextView
            android:id="@+id/noteCreationDate"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_alignParentLeft="true"
            android:layout_below="@id/noteTitle"
            android:textColor="#808080"
            android:textSize="18sp" />

        <TextView
            android:id="@+id/notePrivacy"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_alignParentRight="true"
            android:layout_below="@id/contextMenuIcon"
            android:textColor="#808080"
            android:textSize="18sp" />
    </RelativeLayout>

</RelativeLayout>

selector goes like this

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_selected="true" android:drawable="@drawable/list_selector_pressed" />
    <item android:state_pressed="true" android:drawable="@drawable/list_selector_pressed" />
    <item android:state_focused="true" android:drawable="@drawable/list_selector_focused" />
    <item android:drawable="@android:color/transparent" />

</selector>

In getView add this code.

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

            if (convertView == null) {
        ...

                convertView.setTag(viewHolder);
            }
            else {
                viewHolder = (ViewHolder) convertView.getTag();
            }

            if (mSelectedIndex == position) {
                viewHolder.bgSelector.setSelected(true);
            }
            else {
                viewHolder.bgSelector.setSelected(false);
            }


        ...

            return convertView;
        }

mSelectedIndex is a int that keeps track of the selected position. It will always have the selected index.

Hardik4560
  • 3,202
  • 1
  • 20
  • 31
  • How about the positioning? The `CheckedTextView` would contain the `RelativeLayout` ? I am sorry but I am unable to grasp what you are saying – An SO User Jun 23 '14 at 02:56
0

I have no clue why but a random trial and error led me to this:

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

    <item android:state_pressed="true" android:drawable="@color/translucent_50_grey" />
    <item android:state_pressed="false" android:drawable="@android:color/transparent" />

    <item android:state_focused="true" android:drawable="@android:color/transparent" />
    <item android:state_focused="false" android:drawable="@android:color/transparent" />

    <item android:drawable="@android:color/transparent" />
</selector> 

et voila! It is working. Both in full screen and title bar theme.

An SO User
  • 24,612
  • 35
  • 133
  • 221