Android學習系列(15)–App列表之遊標ListView(索引ListView)

來源:互聯網
上載者:User

      遊標ListView,提供索引標籤,使使用者能夠快速定位清單項目。
      也可以叫索引ListView,有的人稱也為Tweaked ListView,可能更形象些吧。
      一看圖啥都懂了:

1.遊標(Fast scroll thumb)
      就是右邊的那個拖動的方塊,這個非常的簡單:

    <ListView        android:id="@+id/tweaked_list"        android:layout_width="fill_parent"         android:layout_height="wrap_content"         android:fastScrollEnabled="true"/>

  也可以用在java後台書寫:

tweakedListView.setFastScrollEnabled(true);

  在資料量有一定大的時候,滑動列表,就會出現右邊的所謂的"遊標"了。
      簡單,這也是我為什麼私下裡喜歡自己寫控制項,但是工作中卻喜歡用通用控制項。
      我們看下原始碼,其實就是啟用FastScroller對象: 

    //啟用FastScroller對象    public void setFastScrollEnabled(boolean enabled) {        mFastScrollEnabled = enabled;        if (enabled) {            if (mFastScroller == null) {                mFastScroller = new FastScroller(getContext(), this);            }        } else {            if (mFastScroller != null) {                mFastScroller.stop();                mFastScroller = null;            }        }    }

2.字母索引
     在Android學習系列(10)--App列表之拖拽ListView(上)中我們使用了一種WindowManager在ListView中添加一些自訂影像,這種方法我覺得一定是可行的。
   但是,android系統給我們提供了一個更簡單的方法:使用AlphabetIndexer。
   AlphabetIndexer,實現了SectionIndexer介面,是adapter的一個輔助類,輔助實現在快滑時,顯示索引字母。
   使用字母索引的話,必須保證資料列表是按字母順序排序,以便AlphabetIndexerh採用二分尋找法快速定位。

/*** Cursor表示資料遊標* sortedColumnIndex資料集合中的第幾列* alphabet字母列表,用的最多的是"ABCDEFGHIJKLMNOPQRSTUVWXYZ"**/public AlphabetIndexer(Cursor cursor, int sortedColumnIndex, CharSequence alphabet) {}

  用到3個方法:

//這三個方法,實現了索引資料和列表資料的對應和定位public int getPositionForSection(int section) {}public int getSectionForPosition(int position) {}public Object[] getSections() {}

3.遊標Cursor的實現
     Cursor介面的實現,有兩種選擇:
     (1).直接使用資料庫查詢返回的cursor
     (2).自訂實現Cursor介面的新類
     第一種方式很簡單,查詢一下資料庫返回Cursor即可。
     這裡我們以第二種方式實踐,偽裝一個Cursor,主要是實現3個方法:
     (1).getCount()
     (2). moveToPosition()
     (3). getString()

 /**     * 偽裝一個Cursor供AlphabetIndexer作資料索引源     */    private class IndexCursor implements Cursor{                private ListAdapter adapter;        private int position;        private Map<String, String> map;                public IndexCursor(ListAdapter adapter){            this.adapter = adapter;        }        @Override        public int getCount() {return this.adapter.getCount();}                /**         * 取得索引字母,這個方法非常重要,根據實際情況具體處理         */        @SuppressWarnings("unchecked")        @Override        public String getString(int columnIndex) {            map = (HashMap<String, String>)adapter.getItem(position);            return map.get(key).substring(0,1);        }                @Override        public boolean moveToPosition(int position) {            if(position<-1||position>getCount()){                return false;            }                        this.position = position;            //如果不滿意位置有點向上偏的話,下面這幾行代碼是修複定位索引值為頂部項值的問題            //if(position+2>getCount()){                            //    this.position = position;            //}else{            //   this.position = position + 2;            //}            return true;        }                @Override        public void close() {}        @Override        public void copyStringToBuffer(int arg0, CharArrayBuffer arg1) {}        @Override        public void deactivate() {}        @Override        public byte[] getBlob(int arg0) {return null;}        @Override        public int getColumnCount() {return 0;}        @Override        public int getColumnIndex(String columnName) {return 0;}        @Override        public int getColumnIndexOrThrow(String columnName) throws IllegalArgumentException {return 0;}        @Override        public String getColumnName(int columnIndex) {return null;}        @Override        public String[] getColumnNames() {return null;}        @Override        public double getDouble(int columnIndex) {return 0;}        @Override        public Bundle getExtras() {return null;}        @Override        public float getFloat(int columnIndex) {return 0;}        @Override        public int getInt(int columnIndex) {return 0;}        @Override        public long getLong(int columnIndex) {return 0;}        @Override        public int getPosition() {return position;}        @Override        public short getShort(int columnIndex) {return 0;}        @Override        public boolean getWantsAllOnMoveCalls() {return false;}        @Override        public boolean isAfterLast() {return false;}        @Override        public boolean isBeforeFirst() {return false;}        @Override        public boolean isClosed() {return false;}        @Override        public boolean isFirst() {return false;}        @Override        public boolean isLast() {return false;}        @Override        public boolean isNull(int columnIndex) {return false;}        @Override        public boolean move(int offset) {return false;}        @Override        public boolean moveToFirst() {return false;}        @Override        public boolean moveToLast() {return false;}        @Override        public boolean moveToNext() {return false;}        @Override        public boolean moveToPrevious() {return false;}        @Override        public void registerContentObserver(ContentObserver observer) {}        @Override        public void registerDataSetObserver(DataSetObserver observer) {}        @Override        public boolean requery() {return false;}        @Override        public Bundle respond(Bundle extras) {return null;}        @Override        public void setNotificationUri(ContentResolver cr, Uri uri) {}        @Override        public void unregisterContentObserver(ContentObserver observer) {}        @Override        public void unregisterDataSetObserver(DataSetObserver observer) {}            }

  這個類的執行個體就可作為AlphaIndexer的建構函式第一個參數資料遊標。

4.自訂Adapter的實現
      使用前面介紹的東西,我們來實現最終的IndexAdapter:

    class IndexAdapter extends SimpleAdapter implements SectionIndexer{                private AlphabetIndexer alphabetIndexer;                public IndexAdapter(Context context,List<? extends Map<String, ?>> data, int resource,String[] from, int[] to) {            super(context, data, resource, from, to);            //設定資料遊標            //設定索引字母列表            alphabetIndexer = new AlphabetIndexer(new IndexCursor(this), 0, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");        }        @Override        public Object[] getSections() {            return alphabetIndexer.getSections();        }        @Override        public int getPositionForSection(int section) {            return alphabetIndexer.getPositionForSection(section);        }        @Override        public int getSectionForPosition(int position) {            return alphabetIndexer.getSectionForPosition(position);        }    }

5.跑起來
     提供樣本資料如下:

    public List<Map<String, String>> getData(){        List<Map<String, String>> itemList = new ArrayList<Map<String, String>>();        String alphas = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";                Map<String, String> map = null;        for(char c:alphas.toCharArray()){            for(int i=0; i<10; i++){                                map = new HashMap<String, String>();                map.put("itemText", ""+c+i);                itemList.add(map);            }        }        return itemList;    }

  子項的布局檔案:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="vertical"    android:layout_width="fill_parent"    android:layout_height="50dip"    android:gravity="center_vertical"    >    <TextView         android:id="@+id/tweaked_item_text"        android:layout_width="fill_parent"         android:layout_height="wrap_content" /></LinearLayout>

  使用並運行:

    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.tweake_list);                tweakedListView = (ListView)findViewById(R.id.tweaked_list);                //擷取資料        List<Map<String, String>> itemList = getData();        ListAdapter adapter = new IndexAdapter(this, itemList, R.layout.tweake_list_item, new String[]{"itemText"}, new int[]{R.id.tweaked_item_text});        tweakedListView.setAdapter(adapter);    }

  效果如下:

6.小結
      這種索引效果,在大資料量列表顯示中非常的實用,是android開發必備常識。
      本文只是一個簡單的sample,實際工作中肯定會需要進一步擴充定義:
      (1).對於複雜類型的處理,可根據Map<String,?>擴充自訂實體類,再通過adapter轉換使用即可。
      (2).對於索引字母列表,可動態設定,舉個例子,你的列表只有ABCD四個字母,如果索引字母列表還是設定“ABCDEFGHIJKLMNOPQRSTUVWXYZ”就不合適了,會有個索引偏位的問題。
      (3).對於複雜介面的顯示,可重寫adapter的getView方法自訂視圖。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.