[Android]实现ListView的删除功能

时间:2021-01-09 19:43:27

这里实现一个安卓开发中经常要开发的功能——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作为成员变量即可。


好了,这个功能就这样实现啦,希望对你有帮助!