android – Force a ListView item to stay "pressed" after being clicked?-ThrowExceptions

Exception or error:

I have a ListView that opens another activity when an item row is clicked via a onItemClick listener.

I would like that row to stay in its pressed state from the time it is clicked to the time the screen switches to a new activity. I think this would be a clearer experience for the user and you see this kind of thing with most buttons that open/close dialogs or switch activities.

I tried setting view.setPressed(true) in the onItemClick() listener but it seems to get called just a moment after the press state changed back to normal because it flickers slightly.

For example:

mListView.setOnItemClickListener(new OnItemClickListener() {

   @Override
   public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
       view.setPressed(true);
       //start an activity
   }
});

That code almost works except for the flicker (User presses the list item and it turns to its pressed state, then user lets go (completing the click) and it turns back to its normal state for a split second before turning back to the pressed state from the setPressed(true) call)

Any ideas?

Thanks

Edit: I should mention that I am using an xml drawable selector to define the normal, pressed, selected, etc states for the background of the list.

How to solve:

I had the exact same problem to much frustration!

It is, however, easily solved by substituting state_pressed with state_selected. The pressed state will still change rapidly before onItemClick() is called, but since your theme does not depend on state_pressed the flicker won’t be visible. Once in onItemClick() you set state_selected and the item will stay selected without any flicker occurring.

Here’s my selector:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- Selected Item -->
    <item android:state_selected="true"
        android:drawable="@color/list_pressed" />

    <!-- Default Item -->
    <item android:state_selected="false"
        android:drawable="@android:color/list_default" />
</selector>

And my onListItemClick(…):

@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
    super.onListItemClick(l, v, position, id);
    v.setSelected(true);
    //TODO: add further actions here
}

###

The best way you can do this before Android 3.0 is to use a custom state in a custom view or to change your view’s background color from the adapter. Starting with Android 3.0 you can use the new state_activated to keep a list item selected.

###

From inside an Adapter you can reference the view you want to change the state on. Say you have a ListView with a title and a star (ie. favorite star) and you want that to stay “selected/pressed” when touched. Override your getView and do something like:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    final View view = super.getView(position, convertView, parent);
    final ImageButton favorite = (ImageButton) view.findViewById(R.id.favorite);
    favorite.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            Log.d(TAG, "Star pressed...");
            v.setSelected(!v.isSelected());
        }
    });
    return view;
}

And your ImageButton layout should reference a drawable like this:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_selected="true" android:drawable="@android:drawable/star_big_on" />
    <item android:state_pressed="true" android:drawable="@android:drawable/star_big_on" />
    <item android:drawable="@android:drawable/star_big_off" />
</selector>

###

You are using xml for selector. check whether you have correctly given the state.
While you set view.setPressed(true) it will use the drawable that is set for the state android:state_pressed="true" like

<item android:state_pressed="true"   
    android:drawable="@color/gray" />

###

Have you already tried to use unscheduleDrawable in combination with drawableStateChanged

So you could maybe listen if the state changed and then immediately unschedule and set it back to pressed.

Maybe there isn’t flickering anymore.

###

In this example the background is changed after the button is pressed in a list item.
http://androidforbeginners.blogspot.com/2010/03/clicking-buttons-in-listview-row.html

You can do a similar thing in onItemSelected() by manipulating View which has been passed to this call. Usually the view passed is a LinearLayout which contains children views such as textView.

###

Do not use the selector XML. Instead change the list item images manually. This way you will be able to control the duration of a particular image

Leave a Reply

Your email address will not be published. Required fields are marked *