首页 > 代码库 > android列表选择模式的实现
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 Change14 *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 @Override27 public boolean isChecked() {28 return cbx.isChecked();29 }30 31 @Override32 public void setChecked(boolean arg0) {33 cbx.setChecked(arg0);34 }35 36 @Override37 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 <TextView12 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 Change18 *19 */20 public class MainActivity extends Activity {21 List<String> names = new ArrayList<String>();22 ListView lv;23 SelAdapter adapter = new SelAdapter();24 @Override25 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 @Override40 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 Change49 *50 */51 class SelAdapter extends BaseAdapter{52 53 @Override54 public int getCount() {55 return names.size();56 }57 58 @Override59 public Object getItem(int arg0) {60 return names.get(arg0);61 }62 63 @Override64 public long getItemId(int arg0) {65 return arg0;66 }67 68 @Override69 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