本篇博客(实例代码)讲ListView自定义Adapter的用法,重点为使用convertView优化程序,并对使用CheckBox产生的问题予以解决
MyListViewActivity
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ListView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
public class MyListViewActivity extends AppCompatActivity implements View.OnClickListener {
List<Fruit> fruitList = new ArrayList<>();
private MyFruitAdapter adapter;
private Button selectAll;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_mylistview);
prepareFruits();
selectAll = findViewById(R.id.btn_selectAll);
selectAll.setOnClickListener(this);
Button deleteSelected = findViewById(R.id.btn_deleteSelected);
deleteSelected.setOnClickListener(this);
adapter = new MyFruitAdapter(MyListViewActivity.this, R.layout.myfruititem, fruitList);
ListView listView = this.findViewById(R.id.lv_fruits);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(MyListViewActivity.this, adapter.getItem(position).getName(), Toast.LENGTH_LONG).show();
}
});
}
public void onClick(View view) {
int id = view.getId();
switch (id) {
case R.id.btn_selectAll:
Button btn = (Button) view;
if (btn.getText().equals("SelectAll")) {
btn.setText("SelectNone");
adapter.selectAll();
} else {
btn.setText("SelectAll");
adapter.selectNone();
}
break;
case R.id.btn_deleteSelected:
adapter.deleteSelected();
break;
default:
break;
}
}
public void prepareFruits() {
for (int i = 0; i < 20; i++) {
fruitList.add(new Fruit("Apple" + String.valueOf(i), R.drawable.apple_pic));
fruitList.add(new Fruit("Banana" + String.valueOf(i), R.drawable.banana_pic));
fruitList.add(new Fruit("Orange" + String.valueOf(i), R.drawable.orange_pic));
fruitList.add(new Fruit("Watermelon" + String.valueOf(i), R.drawable.watermelon_pic));
fruitList.add(new Fruit("Pear" + String.valueOf(i), R.drawable.pear_pic));
fruitList.add(new Fruit("Grape" + String.valueOf(i), R.drawable.grape_pic));
fruitList.add(new Fruit("Pineapple" + String.valueOf(i), R.drawable.pineapple_pic));
fruitList.add(new Fruit("Strawberry" + String.valueOf(i), R.drawable.strawberry_pic));
fruitList.add(new Fruit("Cherry" + String.valueOf(i), R.drawable.cherry_pic));
fruitList.add(new Fruit("Mango" + String.valueOf(i), R.drawable.mango_pic));
}
}
}
MyFruitAdapter
import android.content.Context;
import android.graphics.Color;
import android.support.annotation.NonNull;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class MyFruitAdapter extends ArrayAdapter<Fruit> {
private Context context;
private int resource;
private FruitManager fruitManager;
private Map<String, Boolean> map = new HashMap();
MyFruitAdapter(Context context, int resource, List<Fruit> objects) {
super(context, resource, objects);
this.context = context;
this.resource = resource;
fruitManager = new FruitManager(objects);
for (int i = 0; i < objects.size(); i++) {
map.put(objects.get(i).getName(), false);
}
}
private class ViewHolder {
private LinearLayout ll;
private ImageView iv;
private TextView tv;
private CheckBox cb;
private Button btn;
}
@NonNull
@Override
public View getView(int position, View convertView, @NonNull ViewGroup parent) {
ViewHolder vh;
if (convertView == null) {
vh = new ViewHolder();
convertView = LayoutInflater.from(getContext()).inflate(resource, parent, false);
vh.iv = convertView.findViewById(R.id.iv_fruitImage);
vh.tv = convertView.findViewById(R.id.tv_fruitName);
CheckBox checkBox = convertView.findViewById(R.id.cb_selectItem);
checkBox.setTag(position);
checkBox.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
CheckBox cb = (CheckBox) v;
if (cb.isChecked()) {
map.put(getItem((int) cb.getTag()).getName(), true);
} else {
map.put(getItem((int) cb.getTag()).getName(), false);
}
}
});
vh.cb = checkBox;
Button button = convertView.findViewById(R.id.btn_delete);
button.setTag(position);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//Toast.makeText(context, fruit.getName(), Toast.LENGTH_LONG).show();
Button btn = (Button) v;
map.remove(getItem((int) btn.getTag()).getName());
fruitManager.deleteFruit(getItem((int) btn.getTag()).getName());
notifyDataSetChanged();
}
});
vh.btn = button;
LinearLayout ll = convertView.findViewById(R.id.ll_item);
vh.ll = ll;
convertView.setTag(vh);
} else {
vh = (ViewHolder) convertView.getTag();
}
Fruit fruit = getItem(position);
assert fruit != null;
vh.iv.setImageResource(fruit.getImageId());
vh.tv.setText(fruit.getName());
if (position % 2 == 0) {
vh.ll.setBackgroundColor(Color.rgb(0, 191, 255));
} else {
vh.ll.setBackgroundColor(Color.parseColor("#FFC1C1"));
}
vh.btn.setTag(position);
vh.cb.setTag(position);
Boolean b = map.get(fruit.getName());
if (b != null) {
vh.cb.setChecked(b);
}
return convertView;
}
void selectAll() {
for (int i = 0; i < getCount(); i++) {
map.put(getItem(i).getName(), true);
}
notifyDataSetChanged();
}
void selectNone() {
for (int i = 0; i < getCount(); i++) {
map.put(getItem(i).getName(), false);
}
notifyDataSetChanged();
}
void deleteSelected() {
List<String> selectedFruits = new ArrayList<>();
for (int i = 0; i < getCount(); i++) {
String fruitName = getItem(i).getName();
if (map.get(fruitName)) {
selectedFruits.add(fruitName);
}
}
fruitManager.deleteSelectedFruits(selectedFruits);
notifyDataSetChanged();
}
}
Fruit
public class Fruit {
private String name;
private int imageId;
Fruit(String name, int imageId) {
this.name = name;
this.imageId = imageId;
}
public String getName() {
return name;
}
int getImageId() {
return imageId;
}
}
FruitManager
import java.util.Iterator;
import java.util.List;
class FruitManager {
private List<Fruit> fruitList;
FruitManager(List<Fruit> objects) {
fruitList = objects;
}
Fruit get(int i) {
return fruitList.get(i);//List 中的元素index 0...1...2......
}
void deleteFruit(String fruitName) {
Iterator<Fruit> it = fruitList.iterator();
while (it.hasNext()) {
if (it.next().getName().equals(fruitName)) {
it.remove();
}
}
}
void deleteSelectedFruits(List<String> list) {
for (int i = 0; i < list.size(); i++) {
deleteFruit(list.get(i));
}
}
}
activity_mylistview.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:orientation="vertical"
tools:context=".MyListViewActivity">
<TextView
android:id="@+id/tv_title"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_weight="0"
android:background="#ffa6af"
android:gravity="center"
android:text="My Fruit ListView"
android:textAllCaps="false"
android:textSize="20sp" />
<ListView
android:id="@+id/lv_fruits"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"></ListView>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0"
android:background="@color/colorPrimaryDark"
android:orientation="horizontal">
<Button
android:id="@+id/btn_deleteSelected"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#5ddf6a"
android:onClick="onClick"
android:text="DeleteSelected"
android:textAllCaps="false" />
<Button
android:id="@+id/btn_selectAll"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#3dc9bc"
android:onClick="onClick"
android:text="SelectAll"
android:textAllCaps="false" />
</LinearLayout>
</LinearLayout>
myfruititem.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/ll_item"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/iv_fruitImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:contentDescription="@string/app_name" />
<TextView
android:id="@+id/tv_fruitName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1" />
<CheckBox
android:id="@+id/cb_selectItem"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginRight="20dp"
android:layout_weight="0"
android:focusable="false" />
<Button
android:id="@+id/btn_delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="0"
android:background="#3dc9bc"
android:focusable="false"
android:text="Delete"
android:textAllCaps="false"
android:textColor="#af39e0"
android:textSize="16sp" />
</LinearLayout>