问题
My goal
When the user taps an item in a listview the item changes background color until the list item is no longer activated (f.e. in single choice mode, the user taps another list item).
My problem
when tapped on an item in a listview briefly, there is a small delay between the pressed state and the activated state of the listview item; this causes the listview item to flash momentarily (because it reverts to unpressed state before the activated state is set).
This only happens when the tap duration is short, when you tap it longer there is no delay between the pressed state and the activated state.
I can produce the problem (on a Samsung S3 - Android 4.3) using this simple test code:
main.xml (containing listview definition)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:cacheColorHint="@android:color/white"
android:background="@android:color/white"
android:divider="@android:color/black"
android:dividerHeight="1dp"
android:choiceMode="singleChoice"
/>
</LinearLayout>
listitem.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/rootLayout"
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="horizontal"
android:background="@drawable/selector">
</LinearLayout>
selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="@android:color/holo_blue_dark"/>
<item android:state_activated="true" android:drawable="@android:color/holo_blue_dark"/>
<item android:drawable="@android:color/white"/>
</selector>
MyActivity.java
package com.example.Test;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.*;
public class MyActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ListView listView = (ListView) findViewById(R.id.listView);
listView.setAdapter(new ListAdapter(this,
new String[] {"item 1", "item 2", "item 3", "item 4"}));
}
private class ListAdapter extends ArrayAdapter<String> {
public ListAdapter(Context context, String[] objects) {
super(context, 0, objects);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = new ListItemView(getContext());
}
return convertView;
}
}
private class ListItemView extends LinearLayout {
public ListItemView(Context context) {
super(context);
LayoutInflater.from(context).inflate(R.layout.listitem, this, true);
}
}
}
already tried
Setting the activated state manually in the OnItemClickListener. Doesn't help.
ugly hack
Adding the following code to my ListItemView class seems to work, but it also looks like an ugly hack:
@Override
public void setPressed(boolean pressed) {
if (pressed) {
super.setPressed(true);
} else {
postDelayed(new Runnable() {
@Override
public void run() {
ListItemView.super.setPressed(false);
}
}, 100);
}
}
basically, this delays setting the state to unpressed, so the activated state is always set first (that is, when the delay is long enough).
回答1:
Did you finaly find a solution ?
The best workaround I have found so far to avoid the 'flicker' is to add an exitFadeDuration
, for example in the background selector (it works also in the list selector):
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"
android:exitFadeDuration="_some_integer_value_>">
<item android:state_pressed="true" android:drawable="@android:color/holo_blue_dark"/>
<item android:state_activated="true" android:drawable="@android:color/holo_blue_dark"/>
<item android:drawable="@android:color/white"/>
</selector>
100 ms seems enough, @android:integer/config_shortAnimTime
is a bit too slow for my taste
来源:https://stackoverflow.com/questions/22422638/listview-how-to-handle-delay-between-state-pressed-and-activated