使用过ListView 的开发人员都知道,ListView 在一般情况下只能对每条记录设置一个监听事件。如果想在其中添加多个事件,就需要自定义Adapter 。
下面介绍一下如何自定义adapter 以及如何在一个Item 中绑定多个事件。
这里我们需要两个XML 文件、两个java 类。分别是存放ListView 的XML 、ListViewItem 的XML 、Activity 类和Adapter 类。
首先说说两个XML 文件。
main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:padding= "10dip" android:orientation="vertical" > <ListView android:id="@id/android:list" android:layout_width = "fill_parent" android:layout_height = "fill_parent" /> </LinearLayout>
注意:这里的ListView 中id 使用了android 自定义的: @id/android:list
lvItem.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:descendantFocusability="blocksDescendants" android:padding="5dip" > <ImageView android:id="@+id/ItemImage" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="5dip" /> <ImageButton android:id="@+id/ItemCloseWin" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBottom="@+id/ItemWinName" android:layout_alignTop="@+id/ItemWinName" android:layout_alignParentRight="true" android:background="#e0000000" android:focusable="false" android:gravity="left|center_vertical" android:src="@android:drawable/ic_menu_close_clear_cancel" /> <ImageButton android:id="@+id/ItemEmail" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBottom="@id/ItemWinName" android:layout_alignTop="@id/ItemWinName" android:layout_toLeftOf="@id/ItemCloseWin" android:background="#e0000000" android:focusable="false" android:gravity="left|center_vertical" android:src="@android:drawable/ic_dialog_email" /> <TextView android:id="@+id/ItemWinName" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBottom="@id/ItemImage" android:layout_alignTop="@id/ItemImage" android:layout_toLeftOf="@id/ItemEmail" android:layout_toRightOf="@id/ItemImage" android:gravity="left|center_vertical" android:text="title" android:textSize="20dip" /> </RelativeLayout>
接下来看看Activity
package cn.mutil;
import java.util.ArrayList;
import java.util.HashMap;
import android.app.ListActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
/**
* ListView item 多事件Activity
* @author lihua
*
*/
public class LvWithButtonActivity extends ListActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 关联Layout中的ListView
ListView vncListView = (ListView) findViewById(android.R.id.list);
// 生成动态数组,加入数据
ArrayList<HashMap<String, Object>> remoteWindowItem = new ArrayList<HashMap<String, Object>>();
for (int i = 0; i < 10; i++) {
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("ItemImage", R.drawable.ic_launcher); // 图像资源的ID
map.put("ItemWinName", "Window ID " + i);
map.put("ItemEmail", android.R.drawable.ic_dialog_email);
map.put("ItemCloseWin", android.R.drawable.ic_menu_close_clear_cancel);
remoteWindowItem.add(map);
}
// 生成适配器的Item和动态数组对应的元素
LvButtonAdapter listItemAdapter = new LvButtonAdapter(this,
remoteWindowItem, // 数据源
R.layout.lvitem, // ListItem对应的XML
// 动态数组与ImageItem对应的子项
new String[] { "ItemImage", "ItemWinName","ItemEmail", "ItemCloseWin" },
// ImageItem的XML文件里面的一个ImageView,两个TextView ID
new int[] { R.id.ItemImage, R.id.ItemWinName, R.id.ItemEmail, R.id.ItemCloseWin });
vncListView.setAdapter(listItemAdapter);
/**
* 设置整个Item被点击的事件
* 该事件在其他有事件的组件未被点击时触发
*/
vncListView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapter, View view,
int position,long arg3) {
TextView content = (TextView)view.findViewById(R.id.ItemWinName);
Toast.makeText(LvWithButtonActivity.this, content.getText().toString() , Toast.LENGTH_SHORT).show();
}
});
}
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
l.getItemAtPosition(position);
}
}
最后一个也是最重要的一个,自定义adapter
package cn.mutil;
import java.util.ArrayList;
import java.util.HashMap;
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.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
public class LvButtonAdapter extends BaseAdapter {
private class ButtonViewHolder {
ImageView appIcon;
TextView appName;
ImageButton buttonEmail;
ImageButton buttonClose;
}
private ArrayList<HashMap<String, Object>> mAppList;//用于存放传递过来显示于ListView中的 数据
private LayoutInflater mInflater;
private Context mContext;
private String[] keyString;
private int[] valueViewID;
private ButtonViewHolder holder;
public LvButtonAdapter(Context c,//上下文
ArrayList<HashMap<String, Object>> appList,//绑定数据
int resource00000,//ListView行记录layout
String[] from,
int[] to) {
mAppList = appList;
mContext = c;
mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
keyString = new String[from.length];
valueViewID = new int[to.length];
System.arraycopy(from, 0, keyString, 0, from.length);
System.arraycopy(to, 0, valueViewID, 0, to.length);
}
@Override
public int getCount() {
return mAppList.size();
}
@Override
public Object getItem(int position) {
return mAppList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
/**
* 删除数据集中的值
* @param position
*/
public void removeItem(int position) {
mAppList.remove(position);
this.notifyDataSetChanged();
}
/**
* 改变数据集中的值
* @param position
* @param map
*/
public void changeItem(int position,HashMap<String, Object> map){
mAppList.remove(position);
mAppList.add(position, map);
this.notifyDataSetChanged();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView != null) {
holder = (ButtonViewHolder) convertView.getTag();
} else {
convertView = mInflater.inflate(R.layout.lvitem, null);
holder = new ButtonViewHolder();
holder.appIcon = (ImageView) convertView
.findViewById(valueViewID[0]);//可以将valueViewID[0]替换成R.id.xxx
holder.appName = (TextView) convertView
.findViewById(valueViewID[1]);
holder.buttonEmail = (ImageButton) convertView
.findViewById(valueViewID[2]);
holder.buttonClose = (ImageButton) convertView
.findViewById(valueViewID[3]);
convertView.setTag(holder);
}
HashMap<String, Object> appInfo = mAppList.get(position);
if (appInfo != null) {
String aname = (String) appInfo.get(keyString[1]);
int mid = (Integer) appInfo.get(keyString[0]);
int eid = (Integer) appInfo.get(keyString[2]);
int bid = (Integer) appInfo.get(keyString[3]);
holder.appName.setText(aname);
holder.appName.setOnClickListener(new LvButtonListener(position));
holder.appIcon.setImageDrawable(holder.appIcon.getResources().getDrawable(mid));
holder.buttonEmail.setImageDrawable(holder.buttonEmail.getResources().getDrawable(eid));
holder.buttonEmail.setOnClickListener(new LvButtonListener(position));
holder.buttonClose.setImageDrawable(holder.buttonClose.getResources().getDrawable(bid));
holder.buttonClose.setOnClickListener(new LvButtonListener(position));
}
return convertView;
}
/**
* 按钮事件监听
* @author lihua
*
*/
private class LvButtonListener implements View.OnClickListener {
private int position;
LvButtonListener(int pos) {
position = pos;
}
@Override
public void onClick(View v) {
int vid = v.getId();
HashMap<String, Object> curMap = (HashMap<String, Object>)getItem(position);
if (vid == holder.buttonClose.getId()){ //删除一行记录
Toast.makeText(mContext,"position:"+position+",data is being Deleted", Toast.LENGTH_LONG).show();
removeItem(position);
//可以在这里操作数据库或更新服务端数据
}else if(vid == holder.buttonEmail.getId()){//发送邮件
Toast.makeText(mContext, "position:"+position+",sending email to xxx!",
Toast.LENGTH_SHORT).show();
//可以在这里操作数据库或更新服务端数据
}else if(vid == holder.appName.getId()){//设置名称
Toast.makeText(mContext, "position is "+position+", appName:"+curMap.get("ItemWinName").toString(),
Toast.LENGTH_SHORT).show();
curMap.put("ItemWinName", System.currentTimeMillis()+"");
changeItem(position,curMap);
//可以在这里操作数据库或更新服务端数据
}
}
}
}