如何在觸摸模式(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#
相關文章
相關標籤/搜索