如何在触摸模式(Touch Mode)下高亮显示ListView选中行

这应该是大部分Android开发者在使用ListView时会碰到问题,在解决这个问题前,须要先了解什么叫触摸模式。html

触摸模式(Touch Mode),在Android SDK的官方文档中有详细解释(http://developer.android.com/resources/articles/touch-mode.html),其大概内容以下:java

  • 用户经过触摸屏操做设备时,设备将自动进入触摸模式,相对的,使用键盘、轨迹球等其余设备时,设备处于非触摸模式
  • 进入触摸模式后,View将失去焦点(Focus)和选择(Selection)状态(文本输入框是例外),缘由是Android的设计者没有好的办法解决同时操做触摸屏和轨迹球、键盘等外部设备所带来的混乱状态
  • Android的设计者认为进入触摸模式后,View失去焦点和选择状态不是一个须要修正的问题,开发者也不该该在触摸模式中试图保持View的焦点或选择状态,可使用CheckBox或RadioButton等控件来标识选择状态
这种设计策略能够说彻底是从工程师的思惟而不是从用户的需求去考虑问题,新的手机的性能愈来愈强,屏幕分辨率愈来愈高,应用程序界面设计趋向复杂,使用触摸屏操做时竟然连个高亮显示都没法作到,真是件十足坑爹的事。
考察了几种不一样的实现后,评估其性能代价和解决方式的优雅程度,我决定用checked状态来模拟选择选择selection来实现ListView的选中行的高亮显示:
  1. 将ListView设为CHOICE_MODE_SINGLE或CHOICE_MODE_MULTIPLE,使ListView支持checked/unchecked状态
  2. 在ListView的适配器中,返回的View实现Checkable接口,跟随选中状态的改变而改变自身背景
下面是个人测试代码:
package org.noodies;  
  
import android.app.Activity;  
import android.content.Context;  
import android.graphics.drawable.Drawable;  
import android.graphics.drawable.StateListDrawable;  
import android.os.Bundle;  
import android.view.View;  
import android.view.ViewGroup;  
import android.widget.BaseAdapter;  
import android.widget.Checkable;  
import android.widget.ListView;  
import android.widget.TextView;  
  
public class TestListActivity extends Activity {  
  
    private ListView mListView;  
  
    @Override  
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.main);  
  
        mListView = (ListView) findViewById(R.id.listView1);  
  
        // 设为单选,容许列表项切换checked/unchecked状态  
        mListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);  
        // 列表的选择效果设为透明,由列表项自行维护各状态显示  
        mListView.setSelector(android.R.color.transparent);  
  
        mListView.setAdapter(new TestAdapter());  
    }  
  
    private class MyView extends TextView implements Checkable {  
  
        private final int[] STATE_CHECKED = { android.R.attr.state_checked };  
  
        private int[] mSavedState;  
        private boolean mChecked = false;  
  
        public MyView(Context context) {  
            super(context);  
        }  
  
        public void setChecked(boolean checked) {  
            if (mChecked != checked) {  
                mChecked = checked;  
                updateBackground();  
            }  
        }  
  
        public boolean isChecked() {  
            return mChecked;  
        }  
  
        public void toggle() {  
            setChecked(!mChecked);  
        }  
  
        private void updateBackground() {  
            Drawable bg = this.getBackground();  
  
            // 在这里切换checked/unchecked状态  
            if (bg.getClass().equals(StateListDrawable.class)) {  
                if (isChecked()) {  
                    mSavedState = bg.getState();  
                    bg.setState(STATE_CHECKED);  
                } else if (mSavedState != null) {  
                    bg.setState(mSavedState);  
                }  
            }  
        }  
    }  
  
    private class TestAdapter extends BaseAdapter {  
  
        private String[] testData = { "test1", "test2", "abcd", "abcdefg" };  
  
        public int getCount() {  
            return testData.length;  
        }  
  
        public Object getItem(int position) {  
            return testData[position];  
        }  
  
        public long getItemId(int position) {  
            return 0;  
        }  
  
        public View getView(int position, View convertView, ViewGroup parent) {  
            TextView v;  
  
            if (convertView == null) {  
                v = new MyView(TestListActivity.this);  
                v.setBackgroundResource(R.drawable.list_item_bg);  
            } else {  
                v = (TextView) convertView;  
            }  
  
            v.setText(testData[position]);  
  
            return v;  
        }  
  
    }  
}

须要创建一个selector做为View的背景,包含选中状态的图像:
<?xml version="1.0" encoding="utf-8"?>  
<selector xmlns:android="http://schemas.android.com/apk/res/android">  
  
    <item android:drawable="@drawable/list_item_bg_checked" android:state_checked="true"/>  
    <item android:drawable="@drawable/list_item_bg_normal" android:state_pressed="false"/>  
    <item android:drawable="@drawable/list_item_bg_pressed" android:state_pressed="true"/>  
  
</selector>

这里是测试工程的下载地址: http://115.com/file/e6ay93l3#
相关文章
相关标签/搜索