这里实现一个安卓开发中经常要开发的功能——ListView的删除功能。
实现说明:通过长按列表或者点击“编辑”按钮,显示每个列表项右边的复选框,选择复选框,点击“删除”按钮删除选中的列表项。
实现:
①主Activity的布局文件activity_main.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" > <ListView android:id="@+id/listview" android:layout_width="fill_parent" android:layout_height="fill_parent" > </ListView> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:layout_alignParentBottom="true" > <Button android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="编辑" android:onClick="click_editButton" /> <Button android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="删除" android:onClick="click_deleteButton" /> <Button android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="取消" android:onClick="click_cancelButton" /> </LinearLayout> </RelativeLayout>②listview中item的布局文件list_item.xml:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="70dp" android:padding="5dp" android:background="#ffff00" > <TextView android:id="@+id/textview" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="20sp" android:textColor="#000000" android:layout_centerVertical="true" /> <CheckBox android:id="@+id/checkbox" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_centerVertical="true" android:visibility="invisible" /> </RelativeLayout>两个布局文件都很简单,样式都是随便定义的,大家瞄一眼就好。
③主Activity:
package com.example.listdelete; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.AdapterView.OnItemLongClickListener; import android.widget.BaseAdapter; import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.CompoundButton.OnCheckedChangeListener; import android.widget.ListView; import android.widget.TextView; public class MainActivity extends Activity { private ListView listview; private MyAdapter myAdapter; /**列表的数据源*/ private List<String> listData; /**记录选中item的下标*/ private List<Integer> checkedIndexList; /**保存每个item中的checkbox*/ private List<CheckBox> checkBoxList; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initListData(); initView(); } /**初始化列表的数据源*/ public void initListData() { //静态赋值 listData = new ArrayList<String>(); for(int i=0;i<6;i++){ listData.add("item" + i); } } /**初始化控件*/ public void initView(){ listview = (ListView) findViewById(R.id.listview); myAdapter = new MyAdapter(getApplicationContext(), listData); listview.setAdapter(myAdapter); //监听listview的长按事件 listview.setOnItemLongClickListener(new OnItemLongClickListener() { @Override public boolean onItemLongClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) { //将checkbox设置为可见 for(int i=0;i<checkBoxList.size();i++){ checkBoxList.get(i).setVisibility(View.VISIBLE); } return false; } }); checkedIndexList = new ArrayList<Integer>(); checkBoxList = new ArrayList<CheckBox>(); } /**自定义listview的适配器*/ class MyAdapter extends BaseAdapter{ private List<String> listData; private LayoutInflater inflater; public MyAdapter(Context context, List<String> listData){ this.listData = listData; inflater = LayoutInflater.from(context); } @Override public int getCount() { return listData.size(); } @Override public Object getItem(int arg0) { return listData.get(arg0); } @Override public long getItemId(int arg0) { return arg0; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder viewHolder; if(convertView == null){ viewHolder = new ViewHolder(); convertView = inflater.inflate(R.layout.list_item, null); viewHolder.tv = (TextView) convertView.findViewById(R.id.textview); viewHolder.checkbox = (CheckBox) convertView.findViewById(R.id.checkbox); //将item中的checkbox放到checkBoxList中 checkBoxList.add(viewHolder.checkbox); convertView.setTag(viewHolder); }else{ viewHolder = (ViewHolder) convertView.getTag(); } viewHolder.tv.setText(listData.get(position)); viewHolder.checkbox.setOnCheckedChangeListener(new CheckBoxListener(position)); return convertView; } class ViewHolder{ TextView tv; CheckBox checkbox; } } /**checkbox的监听器*/ class CheckBoxListener implements OnCheckedChangeListener{ /**列表item的下标位置*/ int position; public CheckBoxListener(int position){ this.position = position; } @Override public void onCheckedChanged(CompoundButton arg0, boolean isChecked) { if(isChecked){ checkedIndexList.add(position); }else{ checkedIndexList.remove((Integer)position); } } } /**编辑按钮的点击事件*/ public void click_editButton(View v){ //将checkbox设置为可见 for(int i=0;i<checkBoxList.size();i++){ checkBoxList.get(i).setVisibility(View.VISIBLE); } } /**删除按钮的点击事件*/ public void click_deleteButton(View v){ //先将checkedIndexList中的元素从大到小排列,否则可能会出现错位删除或下标溢出的错误 checkedIndexList = sortCheckedIndexList(checkedIndexList); for(int i=0;i<checkedIndexList.size();i++){ //需要强转为int,才会删除对应下标的数据,否则默认删除与括号中对象相同的数据 listData.remove((int)checkedIndexList.get(i)); checkBoxList.remove(checkedIndexList.get(i)); } for(int i=0;i<checkBoxList.size();i++){ //将已选的设置成未选状态 checkBoxList.get(i).setChecked(false); //将checkbox设置为不可见 checkBoxList.get(i).setVisibility(View.INVISIBLE); } //更新数据源 myAdapter.notifyDataSetChanged(); //清空checkedIndexList,避免影响下一次删除 checkedIndexList.clear(); } /**取消按钮的点击事件*/ public void click_cancelButton(View v){ for(int i=0;i<checkBoxList.size();i++){ //将已选的设置成未选状态 checkBoxList.get(i).setChecked(false); //将checkbox设置为不可见 checkBoxList.get(i).setVisibility(View.INVISIBLE); } } /**对checkedIndexList中的数据进行从大到小排序*/ public List<Integer> sortCheckedIndexList(List<Integer> list){ int[] ass = new int[list.size()];//辅助数组 for(int i=0;i<list.size();i++){ ass[i] = list.get(i); } Arrays.sort(ass); list.clear(); for(int i=ass.length-1;i>=0;i--){ list.add(ass[i]); } return list; } }
讲解:
好,因为注释很详细,大家应该能看懂,接下来主要来讲解主Activity中的一些知识点:
1)首先是自定义适配器,继承自BaseAdapter,来作为listview 的适配器,这里涉及到BaseAdapter的最佳实现方式,即文艺式,大家可自行百度。
2)其次,我定义了List<Integer> checkedIndexList来记录选中的item的下标,以及List<CheckBox> checkBoxList来存放每个item的复选框,这在删除过程中都会用到。
3)删除的时候,要特别注意需将要删除的下标进行从大到小排列,否则会出现错位删除或下标溢出的情况,大家可自行调试。所以,在实际项目中,删除的时候我们可能还需要对数据源作相应的操作。
4)同时,还要特别注意删除数据源listData中数据的时候,我们是按照下标来删除相应的数据,但是checkedIndexList.get(i)得到的是Object对象,所以要强转为int类型。
优化:
最后再说一下该代码段中可以优化的一个地方吧:在MyAdapter中,每个checkbox设置监听器的时候都new了一个CheckBoxListener对象,这样如果列表项很多的话,new出这么多对象对内存也造成了很大的压力,而且这些对象都是实现同样的功能,所以可以用单例模式来做优化。但是有时候我们需要将不同列表项的position传到监听器中,根据position来做处理,这时可以重构需要设置监听器的控件,比如这个代码段中的CheckBox,将position作为成员变量即可。
好了,这个功能就这样实现啦,希望对你有帮助!