自定义BaseAdapter完成ListView列表单选功能

来源:互联网 发布:文字录入赚钱软件 编辑:程序博客网 时间:2024/05/01 21:56

今天在公司写项目的时候自定义了一个baseAdapter实现listview的单选功能。本人也一直想着写技术博客,就以此开头吧。所以一回到家就开始写Demo分享给大家。

这里有几个需要解决的问题,一是要保留对listview的优化,二是只能有一个打钩,没选择的不能打,之前打好钩的要去掉。三实用性要强,根据原理,进行简单修改就可以应用的五花八门。
先贴item的布局吧:

<?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:gravity="center_vertical" >    <TextView        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:id="@+id/lv_tv"        android:padding="10dp"        android:textColor="#555555"        android:layout_marginLeft="5dp"/>    <View        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_weight="1"        />    <ImageView        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:src="@drawable/checked"        android:id="@+id/lv_checked"        android:visibility="gone"        /></LinearLayout>

就是左边一个textview,右边一个src为打钩图片的imageview,imageview默认为隐藏。
再贴BaseAdapter代码吧。

public class ItemCheckedAdapter extends BaseAdapter {    private Context context;    private List<String> data;    private LayoutInflater inflater;    private int checked = -1;//初始选择为-1,position没有-1嘛,那就是谁都不选咯    public ItemCheckedAdapter(Context context,List<String> data){        this.context = context;        this.data = data;        this.inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);    }    public void setChecked(int checked){//设定一个选中的标志位,在activity中传入值。        this.checked = checked;    }    @Override    public int getCount() {        // TODO Auto-generated method stub        return data.size();    }    @Override    public Object getItem(int position) {        // TODO Auto-generated method stub        return data.get(position);    }    @Override    public long getItemId(int position) {        // TODO Auto-generated method stub        return position;    }    @Override    public View getView(int position, View convertView, ViewGroup parent) {        // TODO Auto-generated method stub        ViewHolder holder;        if(convertView==null){//用于优化,不多说            holder = new ViewHolder();            convertView = inflater.inflate(R.layout.item_lv, null);            holder.tv = (TextView) convertView.findViewById(R.id.lv_tv);            holder.iv = (ImageView) convertView.findViewById(R.id.lv_checked);            convertView.setTag(holder);        }else{            holder = (ViewHolder) convertView.getTag();        }            holder.tv.setText(data.get(position));            if(checked == position){                holder.iv.setVisibility(View.VISIBLE);            }else{                holder.iv.setVisibility(View.GONE);            }//这个else很重要噢,详细解读在下面        return convertView;    }    class ViewHolder{//用于listview的优化,不多说        public TextView tv;        public ImageView iv;    }}

以上代码为了优化listview所以重用了convertView。

if(checked == position){        holder.iv.setVisibility(View.VISIBLE);}else{        holder.iv.setVisibility(View.GONE);    }

这里通过标志checked规定了哪个position的item显示打钩的imageview,其余都不打钩,完成了唯一性。如果这样写:

if(checked == position){        holder.iv.setVisibility(View.VISIBLE);}

不加else选项,由于convertView的重用,在内存里存着的那个holder里的holder.iv已经被设置成显示,所以我们会看到明明只选择了一个,却有多个被打钩的情况,故而要加上else,数学上应该叫有且仅有这个位置的显示。

再来看activity:

public class MainActivity extends Activity {    private TextView tv;    private ListView lv;    private List<String> data;    private ItemCheckedAdapter adapter;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        tv = (TextView) findViewById(R.id.tv);        lv = (ListView) findViewById(R.id.lv);        this.data = new ArrayList<String>();        for(int i = 0;i<40;i++){            data.add("测试"+i);        }               adapter = new ItemCheckedAdapter(this, data);        lv.setAdapter(adapter);        lv.setOnItemClickListener(new OnItemClickListener() {            @Override            public void onItemClick(AdapterView<?> parent, View view,                    int position, long id) {                // TODO Auto-generated method stub                adapter.setChecked(position);//传入现在选择的position                adapter.notifyDataSetInvalidated();//重绘            }        });    }

大家可以看到在onItemClick()的方法里面我先往adapter内传入一个我已经选择的item的position,之后调用notifyDataSetInvalidated()方法进行重绘,这样必然调用getview()方法,在绘到checked == position时就会将钩打上,其余的Item就会隐藏掉。之前选择的项也会隐藏了。这样就解决了一开始提出的没选择的不能打,之前打好钩的要去掉的效果,虽然逻辑我没有分别针对二者进行处理,用了只要不是我选择的全都干掉的思路,就是这么任性。大家可以稍微改变item的布局差不多就可以运用到自己项目中去了吧…

效果图如下:
虚拟机测试

以上,谢谢!
其实源码基本贴上了,还需要的可以留邮箱。

0 0
原创粉丝点击