Android高級控件(一)——ListView綁定CheckBox實現全選,添加和刪除等功能
這個控件還是挺復雜的。也是項目中應該算是比較經常使用的了,所以寫了一個小Demo來講講,主要是自己定義adapter的使用方法。加了非常多的推斷等等等等….我們先來看看實現的效果吧!
好的,我們新建一個項目LvCheckBox
我們事先先把這兩個布局寫好吧,一個是主布局,另一個listview的item.xml。相信不用多說
activity_main.xml
<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" >
<RelativeLayout android:layout_width="match_parent" android:layout_height="50dp" android:background="#238286" >
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:text="ListView綁定CheckBox" android:textColor="#fff" />
<TextView android:id="@+id/tv_add" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_centerVertical="true" android:layout_marginRight="17dp" android:text="添加" android:textColor="#fff" />
</RelativeLayout>
<ListView android:id="@+id/listview" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" >
</ListView>
<LinearLayout android:layout_width="match_parent" android:layout_height="50dp" android:orientation="horizontal" >
<Button android:id="@+id/btn_detele" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginRight="1dp" android:layout_weight="1" android:background="#238286" android:text="刪除" android:textColor="#fff" />
<Button android:id="@+id/btn_select_all" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginLeft="1dp" android:layout_weight="1" android:background="#238286" android:text="全選" android:textColor="#fff" />
</LinearLayout>
</LinearLayout>
item.xml
<?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="50dp" android:gravity="center_vertical" android:orientation="horizontal" >
<TextView android:id="@+id/tvTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="15dp" android:layout_weight="7" android:text="text" />
<CheckBox android:id="@+id/cbCheckBox" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" />
</LinearLayout>
item.xml僅僅有兩個控件。非常好理解吧
初始化控件
我們用initView()方法來初始化這些控件
private void initView() {
tv_add = (TextView) findViewById(R.id.tv_add);
tv_add.setOnClickListener(this);
btn_detele = (Button) findViewById(R.id.btn_detele);
btn_detele.setOnClickListener(this);
btn_select_all = (Button) findViewById(R.id.btn_select_all);
btn_select_all.setOnClickListener(this);
listview = (ListView) findViewById(R.id.listview);
}
然后繼承點擊事件,button的和listview的
implements OnClickListener,OnItemClickListener
自己定義Adapter
這里最難的就是adapter了
1.Bean
我們為了數據的記錄方便。我們提前寫一個實體類
package com.lgl.lvcheckbox;
public class Bean {
private String title;
// 構造方法
public Bean(String title) {
super();
this.title = title;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
ListAdapter
這里全部的都寫了凝視,也方便大家看清
package com.lgl.lvcheckbox;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.TextView;
/** * 自己定義適配器 * * @author LGL * */
public class ListAdapter extends BaseAdapter {
// 數據集
private List<Bean> list = new ArrayList<Bean>();
// 上下文
private Context mContext;
// 存儲勾選框狀態的map集合
private Map<Integer, Boolean> isCheck = new HashMap<Integer, Boolean>();
// 構造方法
public ListAdapter(Context mContext) {
super();
this.mContext = mContext;
// 默覺得不選中
initCheck(false);
}
// 初始化map集合
public void initCheck(boolean flag) {
// map集合的數量和list的數量是一致的
for (int i = 0; i < list.size(); i++) {
// 設置默認的顯示
isCheck.put(i, flag);
}
}
// 設置數據
public void setData(List<Bean> data) {
this.list = data;
}
// 加入數據
public void addData(Bean bean) {
// 下標 數據
list.add(0, bean);
}
@Override
public int getCount() {
// TODO Auto-generated method stub
// 假設為null就返回一個0
return list != null ? list.size() : 0;
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return list.get(position);
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder = null;
View view = null;
// 推斷是不是第一次進來
if (convertView == null) {
view = LayoutInflater.from(mContext).inflate(R.layout.item, null);
viewHolder = new ViewHolder();
viewHolder.title = (TextView) view.findViewById(R.id.tvTitle);
viewHolder.cbCheckBox = (CheckBox) view
.findViewById(R.id.cbCheckBox);
// 標記,能夠復用
view.setTag(viewHolder);
} else {
view = convertView;
// 直接拿過來用
viewHolder = (ViewHolder) view.getTag();
}
// 拿到對象
Bean bean = list.get(position);
// 填充數據
viewHolder.title.setText(bean.getTitle().toString());
// 勾選框的點擊事件
viewHolder.cbCheckBox
.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
// 用map集合保存
isCheck.put(position, isChecked);
}
});
// 設置狀態
if (isCheck.get(position) == null) {
isCheck.put(position, false);
}
viewHolder.cbCheckBox.setChecked(isCheck.get(position));
return view;
}
// 優化
public static class ViewHolder {
public TextView title;
public CheckBox cbCheckBox;
}
// 全選button獲取狀態
public Map<Integer, Boolean> getMap() {
// 返回狀態
return isCheck;
}
// 刪除一個數據
public void removeData(int position) {
list.remove(position);
}
}
當然,有些方法是后面寫的,我們提前寫好。比方刪除和添加什么的
初始化數據
我們默認總是須要點數據的
private void initData() {
// 默認顯示的數據
List<Bean> list = new ArrayList<Bean>();
list.add(new Bean("張三"));
list.add(new Bean("李四"));
list.add(new Bean("王五"));
adapter = new ListAdapter(this);
adapter.setData(list);
listview.setAdapter(adapter);
}
添加數據
// 加入數據
case R.id.tv_add:
adapter.addData(new Bean("劉桂林"));
// 通知刷新適配器
adapter.notifyDataSetChanged();
break;
全選數據
當我們全選的時候,button應該為全不選的,所以這里我們這里有狀態的
case R.id.btn_select_all:
// 全選——全不選
Map<Integer, Boolean> isCheck = adapter.getMap();
if (btn_select_all.getText().equals("全選")) {
adapter.initCheck(true);
// 通知刷新適配器
adapter.notifyDataSetChanged();
btn_select_all.setText("全不選");
btn_select_all.setTextColor(Color.YELLOW);
} else if (btn_select_all.getText().equals("全不選")) {
adapter.initCheck(false);
// 通知刷新適配器
adapter.notifyDataSetChanged();
btn_select_all.setText("全選");
btn_select_all.setTextColor(Color.YELLOW);
}
break;
刪除數據
刪除也是要考慮非常多因素
// 刪除數據
case R.id.btn_detele:
// 拿到全部數據
Map<Integer, Boolean> isCheck_delete = adapter.getMap();
// 獲取到條目數量。map.size = list.size,所以
int count = adapter.getCount();
// 遍歷
for (int i = 0; i < count; i++) {
// 刪除有兩個map和list都要刪除 ,計算方式
int position = i - (count - adapter.getCount());
// 推斷狀態 true為刪除
if (isCheck_delete.get(i) != null && isCheck_delete.get(i)) {
// listview刪除數據
isCheck_delete.remove(i);
adapter.removeData(position);
}
}
btn_select_all.setText("全選");
btn_select_all.setTextColor(Color.WHITE);
adapter.notifyDataSetChanged();
break;
這里的
int position = i - (count - adapter.getCount());
是一個計算方式。當我們刪除之后。實際上數組是須要又一次排列的,同一時候button也要變回全選狀態的
listview的點擊
我們直接點擊也是能夠勾選cheakbox選中的
// listview的點擊事件
@Override
public void onItemClick(AdapterView<?
> parent, View view, int position, long id) { // 推斷view是否同樣 if (view.getTag() instanceof ViewHolder) { // 假設是的話。重用 ViewHolder holder = (ViewHolder) view.getTag(); // 自己主動觸發 holder.cbCheckBox.toggle(); } }
好的,這種話就能夠實現了,假設不懂的話能夠下載本文demo參考。覺得好的點個贊