android列表選擇模式的實現


我們或許曾一次又一次的接到這樣的需求,有一堆數據需要用戶去選擇,並且以列表的方式呈現,根據需求,我們需要單選或者復選列表里面的數據,並且最終取得所選數據作下一步的操作。那么對於這個需求,我們聰明的程序員往往都能想到一些解決方案去處理。譬如我,咳咳,雖然我不是很聰明,但是我想到了。

【也許這樣實現是對的】通常需要選擇的列表數據我都會在adapter所綁定的數據實體內增加一個標記代表是否選中,在點擊的時候去遍歷並改變adapter中的實體標記,通知更新,然后根據標記在adapter的getView方法改變視圖樣式。這樣能直觀地實現我們的需求。

【探索更好的解決方案】上面那種方式,很直接,估計大家都能想到,但這樣做存在一些問題,比如遍歷的效率會低,比如我們的adapter會增加一些非功能性的代碼,讓我們的adapter變得復雜。但當我們更深入地了解listview之后,我們可以發現listview有個屬性--choicemode,英文不錯的童鞋都能翻譯:選擇模式。

【選擇模式的例子】這里我寫了個簡單的使用選擇模式中單選的例子。其中關鍵的部分便是自定義view,也許這是這種方式唯一的弱點,必須使用自定義view.

【自定義選項】自定義的列表項繼承checkable,實現checkable內的方法修改列表項的界面狀態。

 1 package com.change.selectablelistviewdemo;
 2 
 3 import android.content.Context;
 4 import android.widget.CheckBox;
 5 import android.widget.Checkable;
 6 import android.widget.LinearLayout;
 7 import android.widget.TextView;
 8 
 9 import com.change.selectablelistviewdemo.R;
10 
11 /**
12  * 自定義選項view,實現checkable。在實現的方法中修改界面狀態。
13  * @author Change
14  *
15  */
16 public class SelectItemView extends LinearLayout implements Checkable {
17     CheckBox cbx;
18     TextView name;
19     public SelectItemView(Context context){
20         super(context);
21         inflate(getContext(), R.layout.item_select, this);
22         cbx = (CheckBox)findViewById(R.id.cbx);
23         name = (TextView)findViewById(R.id.name);
24     }
25     
26     @Override
27     public boolean isChecked() {
28         return cbx.isChecked();
29     }
30 
31     @Override
32     public void setChecked(boolean arg0) {
33         cbx.setChecked(arg0);
34     }
35 
36     @Override
37     public void toggle() {
38         cbx.toggle();
39     }
40     
41     public void setName(String name){
42         this.name.setText(name);
43     }
44 
45 }

我的列表項只有一個顯示名字的textview和一個代表單選狀態的選擇框,單選框我們需要取消他自身的點擊效果,把它的狀態交由列表項的點擊去決定。所以,我們需要禁止checkbox的點擊和焦點獲取。代碼如下--》

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal"
    android:weightSum="1" >

    <TextView
        android:id="@+id/name"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight=".9" />

    <CheckBox
        android:id="@+id/cbx"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:layout_weight=".1" 
        android:clickable="false"
        android:focusable="false"
        android:focusableInTouchMode="false"
        />

</LinearLayout>

【如何使用listview】很簡單,在主頁界面xml中定義listview,並設定choiceMode,此處為single,單選模式。

 1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     xmlns:tools="http://schemas.android.com/tools"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     android:paddingBottom="@dimen/activity_vertical_margin"
 6     android:paddingLeft="@dimen/activity_horizontal_margin"
 7     android:paddingRight="@dimen/activity_horizontal_margin"
 8     android:paddingTop="@dimen/activity_vertical_margin"
 9     tools:context=".MainActivity" >
10 
11     <TextView
12         android:layout_width="wrap_content"
13         android:layout_height="wrap_content"
14         android:text="@string/hello_world" />
15     
16     <Button android:layout_width="wrap_content"
17         android:layout_height="wrap_content"
18         android:onClick="choice"
19         android:text="current"
20         android:layout_below="@+id/lv"
21         />
22     
23     <ListView android:layout_width="match_parent"
24         android:layout_height="wrap_content"
25         android:id="@+id/lv"
26         android:choiceMode="singleChoice"
27         />
28   
29 </RelativeLayout>

【在主activity中的做了什么?】activity只是把listview的數據綁定到界面。使用adapter,此處是個內部類。adapter出奇的簡單,只是設置了名字的顯示而已,剩下的選擇狀態完全交由listview的機制和我們的自定義view.是不是很簡單?快行動起來吧。

 1 package com.change.selectablelistviewdemo;
 2 
 3 import java.util.ArrayList;
 4 import java.util.List;
 5 
 6 import android.app.Activity;
 7 import android.os.Bundle;
 8 import android.view.Menu;
 9 import android.view.View;
10 import android.view.ViewGroup;
11 import android.widget.BaseAdapter;
12 import android.widget.ListView;
13 import android.widget.Toast;
14 
15 /**
16  * listview單選模式demo,
17  * @author Change
18  *
19  */
20 public class MainActivity extends Activity {
21     List<String> names = new ArrayList<String>();
22     ListView lv;
23     SelAdapter adapter = new SelAdapter();
24     @Override
25     protected void onCreate(Bundle savedInstanceState) {
26         super.onCreate(savedInstanceState);
27         setContentView(R.layout.activity_main);
28         lv = (ListView)findViewById(R.id.lv);
29         initData();
30         lv.setAdapter(adapter);
31     }
32     
33     private void initData(){
34         for(int i=0;i<10;i++){
35             names.add("name"+i);
36         }
37     }
38 
39     @Override
40     public boolean onCreateOptionsMenu(Menu menu) {
41         // Inflate the menu; this adds items to the action bar if it is present.
42         getMenuInflater().inflate(R.menu.main, menu);
43         return true;
44     }
45     
46     /**
47      * 列表適配器,只需要設置view的內容,狀態變化完全交由android機制和自定義view.是不是很簡單?
48      * @author Change
49      *
50      */
51     class SelAdapter extends BaseAdapter{
52 
53         @Override
54         public int getCount() {
55             return names.size();
56         }
57 
58         @Override
59         public Object getItem(int arg0) {
60             return names.get(arg0);
61         }
62 
63         @Override
64         public long getItemId(int arg0) {
65             return arg0;
66         }
67 
68         @Override
69         public View getView(int arg0, View arg1, ViewGroup arg2) {
70             if(null==arg1){
71                 arg1 = new SelectItemView(MainActivity.this);
72             }
73             ((SelectItemView)arg1).setName(names.get(arg0));
74             return arg1;
75         }
76         
77         
78     }
79         public void choice(View v){
80             int pos = lv.getCheckedItemPosition();
81             if(ListView.INVALID_POSITION!=pos){
82                 Toast.makeText(MainActivity.this, "current pos="+pos, Toast.LENGTH_SHORT).show();
83             }
84         }
85 }

【關鍵部分:取得當前選項】代碼中標紅的部分便可以輕松獲得當前的選項,從此媽媽再也不擔心我們不會選擇了。

【完整項目】在github中,地址:https://github.com/ChangeWu/SomePoject/tree/master/SelectableListViewDemo


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM