引言
该节介绍如何在开发中使用ViewHolder实现自定义ListView
开发流程
Step-1 新建一个Module,命名为ViewHolderListViewActivity
Step-2 在ViewHolderListViewActivity绑定的布局文件中添加ListView组件
<!-- divider="@null" 属性的作用为取消ListView各Item间的分割线 -->
<ListView
android:id="@+id/listViewInfo"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="@null"/>
Step-3 添加自定义布局文件设置每个Item的基本样式
<ImageView
android:id="@+id/imgIcon"
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@drawable/photo02"/>
<TextView
android:id="@+id/txtUserName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/imgIcon"
android:layout_marginLeft="10dp"
android:text="用户姓名"
android:textSize="16sp"
android:textColor="#3c6393"/>
<TextView
android:id="@+id/txtInfo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/imgIcon"
android:layout_marginLeft="10dp"
android:layout_below="@id/txtUserName"
android:layout_marginTop="6dp"
android:text="消息消息消息消息消息消息消息消息消息消息消息消息消息消息消息消息"
android:textSize="14sp"
android:lineSpacingMultiplier="1.1"
android:textColor="#2a2b2b"/>
<!-- 嵌套布局LinearLayout线型布局模式 -->
<LinearLayout
android:id="@+id/layoutImages"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/imgIcon"
android:layout_marginLeft="10dp"
android:layout_below="@id/txtInfo"
android:layout_marginTop="10dp"
android:orientation="horizontal">
<ImageView
android:layout_width="60dp"
android:layout_height="60dp"
android:src="@drawable/photo01"
android:layout_marginRight="5dp"/>
<ImageView
android:layout_width="60dp"
android:layout_height="60dp"
android:src="@drawable/photo02"
android:layout_marginRight="5dp"/>
<ImageView
android:layout_width="60dp"
android:layout_height="60dp"
android:src="@drawable/photo03"
android:layout_marginRight="5dp"/>
</LinearLayout>
<TextView
android:id="@+id/txtPublish"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/imgIcon"
android:layout_marginLeft="10dp"
android:layout_below="@id/layoutImages"
android:layout_marginTop="10dp"
android:text="2016-09-29 14:35"
android:textSize="10sp"
android:textColor="#3c6393"/>
<ImageView
android:id="@+id/btnPin"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_below="@id/layoutImages"
android:layout_alignParentRight="true"
android:src="@android:drawable/ic_menu_send"/>
<!-- 嵌套布局LinearLayout线型布局模式 -->
<LinearLayout
android:id="@+id/layoutReplys"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/imgIcon"
android:layout_marginLeft="10dp"
android:layout_below="@id/txtPublish"
android:layout_marginTop="10dp"
android:orientation="vertical"
android:background="#c8d8f1"
android:padding="5dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="吕布 回复:不错!"
android:layout_marginBottom="3dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="吕布 回复:不错!"
android:layout_marginBottom="3dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="吕布 回复:不错!"
android:layout_marginBottom="3dp"/>
</LinearLayout>
<TextView
android:id="@+id/txtNickName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="貂蝉"
android:layout_toRightOf="@id/imgPhoto"
android:layout_marginLeft="10dp"
android:textColor="#4a90e6"
android:textSize="16sp"/>
<TextView
android:id="@+id/txtMessage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="这里是我发送的消息,呵呵呵呵这里是我发送的消息,呵呵呵呵这里是我发送的消息,呵呵呵呵这里是我发送的消息,呵呵呵呵"
android:layout_toRightOf="@id/imgPhoto"
android:layout_marginLeft="10dp"
android:layout_below="@id/txtNickName"
android:layout_marginTop="5dp"
android:lineSpacingMultiplier="1.1"
android:textSize="12sp"
android:textColor="#3e3d3d"/>
Step-4 新建一个ViewHolder文件,用于声明获取各组件的id的变量
public class InfoViewHolder {
public ImageView imgIcon, btnPin;
public TextView txtUserName, txtInfo, txtPublish;
public LinearLayout layoutImages, layoutReplys;
}
Step-5 自定义适配器
public class InfoAdapter extends BaseAdapter {
private Context mContext;
private List<Map<String, ?>> listItems;
private LayoutInflater inflater;
public InfoAdapter(List<Map<String, ?>> listItems, Context mContext) {
super();
this.inflater = LayoutInflater.from(mContext);
this.listItems = listItems;
this.mContext = mContext;
}
@Override
public int getCount() {
return this.listItems.size();
}
@Override
public Object getItem(int position) {
return this.listItems.get(position);
}
@Override
public long getItemId(int position) {
return 0;
}
/*
* 使用循环迭代遍历listItems中的每一个选项对象,并通过转换视图对象ConverView动态加载当前选项布局资源
* 同时根据ListItem中的选项对象参数,动态设置其组件显示和内容
* */
@Override
public View getView(int position, View convertView, ViewGroup parent) {
/* 步骤1:创建一个空的InfoViewHolder对象 */
InfoViewHolder infoViewHolder = null;
/* 步骤2:判断但钱的转换视图参数convertView是否为空,若为空则实例化viewHolder对象中的组件 */
if(convertView == null){
infoViewHolder = new InfoViewHolder();
/* 步骤3:转换视图绑定列表选项布局文件 */
convertView = this.inflater.inflate(R.layout.listitem_view_holder_list_view, null);
/* 步骤4:获取列表布局中的所有组件对象 */
infoViewHolder.imgIcon = (ImageView) convertView.findViewById(R.id.imgIcon);
infoViewHolder.txtUserName = (TextView) convertView.findViewById(R.id.txtUserName);
infoViewHolder.txtInfo = (TextView) convertView.findViewById(R.id.txtInfo);
infoViewHolder.layoutImages = (LinearLayout) convertView.findViewById(R.id.layoutImages);
infoViewHolder.txtPublish = (TextView) convertView.findViewById(R.id.txtPublish);
infoViewHolder.btnPin = (ImageView) convertView.findViewById(R.id.btnPin);
infoViewHolder.layoutReplys = (LinearLayout) convertView.findViewById(R.id.layoutReplys);
/* 步骤5:转换视图设置ViewHolder对象*/
convertView.setTag(infoViewHolder);
}else{
infoViewHolder = (InfoViewHolder) convertView.getTag();
}
/* 步骤6:动态为每一个选项对象赋值 */
infoViewHolder.imgIcon.setImageResource((Integer) this.listItems.get(position).get("imgIcon"));
infoViewHolder.txtUserName.setText(this.listItems.get(position).get("txtUserName").toString());
infoViewHolder.txtInfo.setText(this.listItems.get(position).get("txtInfo").toString());
infoViewHolder.txtPublish.setText(this.listItems.get(position).get("txtPublish").toString());
/* 步骤7:动态设置适配器中的组件显示 */
if(this.listItems.get(position).get("layoutImages").toString().equals("0")){
infoViewHolder.layoutImages.setVisibility(View.GONE);
}
if(this.listItems.get(position).get("layoutReplys").toString().equals("0")){
infoViewHolder.layoutReplys.setVisibility(View.GONE);
}
/* 步骤8:监听器绑定 */
infoViewHolder.btnPin.setOnClickListener(new ViewOcl(position));
return convertView;
}
/* 自定义一个单击监听器 */
private class ViewOcl implements View.OnClickListener{
private int position;
public ViewOcl(int position) {
this.position = position;
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btnPin:
Toast.makeText(mContext, "你要回复 ["+ listItems.get(position).get("txtUserName") +"]", Toast.LENGTH_SHORT).show();
break;
}
}
}
}
Step-6 在Activity中初始化ListView适配器并绑定
public class ViewHolderListViewActivity extends AppCompatActivity {
private ListView listViewInfo;
private List<Map<String, ?>> listItems;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_holder_list_view);
this.listItems = this.getListItems();
InfoAdapter adapter = new InfoAdapter(this.listItems, this);
this.listViewInfo = (ListView) findViewById(R.id.listViewInfo);
this.listViewInfo.setAdapter(adapter);
}
private List<Map<String, ?>> getListItems() {
List<Map<String, ?>> listItems = new ArrayList<>();
Map<String, Object> item01 = new HashMap<>();
item01.put("id", 1);
item01.put("imgIcon", R.drawable.photo01);
item01.put("txtUserName", "西施");
item01.put("txtInfo", "西施发送的消息发送的消息发送的消息发送的消息发送的消息发送的消息发送的消息");
item01.put("txtPublish", new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date()));
item01.put("layoutImages", "0");
item01.put("layoutReplys", "1");
listItems.add(item01);
Map<String, Object> item02 = new HashMap<>();
item02.put("id", 2);
item02.put("imgIcon", R.drawable.photo02);
item02.put("txtUserName", "貂蝉");
item02.put("txtInfo", "貂蝉发送的消息发送的消息发送的消息发送的消息发送的消息发送的消息发送的消息");
item02.put("txtPublish", new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date()));
item02.put("layoutImages", "1");
item02.put("layoutReplys", "0");
listItems.add(item02);
Map<String, Object> item03 = new HashMap<>();
item03.put("id", 3);
item03.put("imgIcon", R.drawable.photo03);
item03.put("txtUserName", "吕布");
item03.put("txtInfo", "吕布发送的消息发送的消息发送的消息发送的消息发送的消息发送的消息发送的消息");
item03.put("txtPublish", new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date()));
item03.put("layoutImages", "1");
item03.put("layoutReplys", "1");
listItems.add(item03);
return listItems;
}
}
结果展示
ViewHolderListView.png
代码清单
activity_view_holder_list_view.xml
<?xml version="1.0" encoding="utf-8"?>
<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="com.chinasofti.demo04listview.ViewHolderListViewActivity">
<ListView
android:id="@+id/listViewInfo"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="@null"/>
</RelativeLayout>
listitem_view_holder_list_view.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="match_parent"
android:padding="16dp">
<ImageView
android:id="@+id/imgIcon"
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@drawable/photo02"/>
<TextView
android:id="@+id/txtUserName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/imgIcon"
android:layout_marginLeft="10dp"
android:text="用户姓名"
android:textSize="16sp"
android:textColor="#3c6393"/>
<TextView
android:id="@+id/txtInfo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/imgIcon"
android:layout_marginLeft="10dp"
android:layout_below="@id/txtUserName"
android:layout_marginTop="6dp"
android:text="消息消息消息消息消息消息消息消息消息消息消息消息消息消息消息消息"
android:textSize="14sp"
android:lineSpacingMultiplier="1.1"
android:textColor="#2a2b2b"/>
<!-- 嵌套布局LinearLayout线型布局模式 -->
<LinearLayout
android:id="@+id/layoutImages"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/imgIcon"
android:layout_marginLeft="10dp"
android:layout_below="@id/txtInfo"
android:layout_marginTop="10dp"
android:orientation="horizontal">
<ImageView
android:layout_width="60dp"
android:layout_height="60dp"
android:src="@drawable/photo01"
android:layout_marginRight="5dp"/>
<ImageView
android:layout_width="60dp"
android:layout_height="60dp"
android:src="@drawable/photo02"
android:layout_marginRight="5dp"/>
<ImageView
android:layout_width="60dp"
android:layout_height="60dp"
android:src="@drawable/photo03"
android:layout_marginRight="5dp"/>
</LinearLayout>
<TextView
android:id="@+id/txtPublish"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/imgIcon"
android:layout_marginLeft="10dp"
android:layout_below="@id/layoutImages"
android:layout_marginTop="10dp"
android:text="2016-09-29 14:35"
android:textSize="10sp"
android:textColor="#3c6393"/>
<ImageView
android:id="@+id/btnPin"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_below="@id/layoutImages"
android:layout_alignParentRight="true"
android:src="@android:drawable/ic_menu_send"/>
<!-- 嵌套布局LinearLayout线型布局模式 -->
<LinearLayout
android:id="@+id/layoutReplys"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/imgIcon"
android:layout_marginLeft="10dp"
android:layout_below="@id/txtPublish"
android:layout_marginTop="10dp"
android:orientation="vertical"
android:background="#c8d8f1"
android:padding="5dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="吕布 回复:不错!"
android:layout_marginBottom="3dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="吕布 回复:不错!"
android:layout_marginBottom="3dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="吕布 回复:不错!"
android:layout_marginBottom="3dp"/>
</LinearLayout>
</RelativeLayout>
InfoViewHolder.java
package com.chinasofti.holder;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
public class InfoViewHolder {
public ImageView imgIcon, btnPin;
public TextView txtUserName, txtInfo, txtPublish;
public LinearLayout layoutImages, layoutReplys;
}
InfoAdapter.java
package com.chinasofti.adapter;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.chinasofti.demo04listview.R;
import com.chinasofti.holder.InfoViewHolder;
import java.util.List;
import java.util.Map;
public class InfoAdapter extends BaseAdapter {
private Context mContext;
private List<Map<String, ?>> listItems;
private LayoutInflater inflater;
public InfoAdapter(List<Map<String, ?>> listItems, Context mContext) {
super();
this.inflater = LayoutInflater.from(mContext);
this.listItems = listItems;
this.mContext = mContext;
}
@Override
public int getCount() {
return this.listItems.size();
}
@Override
public Object getItem(int position) {
return this.listItems.get(position);
}
@Override
public long getItemId(int position) {
return 0;
}
/*
* 使用循环迭代遍历listItems中的每一个选项对象,并通过转换视图对象ConverView动态加载当前选项布局资源
* 同时根据ListItem中的选项对象参数,动态设置其组件显示和内容
* */
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// 步骤1:创建一个空的InfoViewHolder对象
InfoViewHolder infoViewHolder = null;
// 步骤2:判断但钱的转换视图参数convertView是否为空,若为空则实例化viewHolder对象中的组件
if(convertView == null){
infoViewHolder = new InfoViewHolder();
// 步骤3:转换视图绑定列表选项布局文件
convertView = this.inflater.inflate(R.layout.listitem_view_holder_list_view, null);
// 步骤4:获取列表布局中的所有组件对象
infoViewHolder.imgIcon = (ImageView) convertView.findViewById(R.id.imgIcon);
infoViewHolder.txtUserName = (TextView) convertView.findViewById(R.id.txtUserName);
infoViewHolder.txtInfo = (TextView) convertView.findViewById(R.id.txtInfo);
infoViewHolder.layoutImages = (LinearLayout) convertView.findViewById(R.id.layoutImages);
infoViewHolder.txtPublish = (TextView) convertView.findViewById(R.id.txtPublish);
infoViewHolder.btnPin = (ImageView) convertView.findViewById(R.id.btnPin);
infoViewHolder.layoutReplys = (LinearLayout) convertView.findViewById(R.id.layoutReplys);
// 步骤5:转换视图设置ViewHolder对象
convertView.setTag(infoViewHolder);
}else{
infoViewHolder = (InfoViewHolder) convertView.getTag();
}
// 步骤6:动态为每一个选项对象赋值
infoViewHolder.imgIcon.setImageResource((Integer) this.listItems.get(position).get("imgIcon"));
infoViewHolder.txtUserName.setText(this.listItems.get(position).get("txtUserName").toString());
infoViewHolder.txtInfo.setText(this.listItems.get(position).get("txtInfo").toString());
infoViewHolder.txtPublish.setText(this.listItems.get(position).get("txtPublish").toString());
// 步骤9:动态设置适配器中的组件显示
if(this.listItems.get(position).get("layoutImages").toString().equals("0")){
infoViewHolder.layoutImages.setVisibility(View.GONE);
}
if(this.listItems.get(position).get("layoutReplys").toString().equals("0")){
infoViewHolder.layoutReplys.setVisibility(View.GONE);
}
// 步骤10:监听器绑定
infoViewHolder.btnPin.setOnClickListener(new ViewOcl(position));
return convertView;
}
// 自定义一个单击监听器
private class ViewOcl implements View.OnClickListener{
private int position;
public ViewOcl(int position) {
this.position = position;
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btnPin:
Toast.makeText(mContext, "你要回复 ["+ listItems.get(position).get("txtUserName") +"]", Toast.LENGTH_SHORT).show();
break;
}
}
}
}
ViewHolderListViewActivity.java
package com.chinasofti.demo04listview;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ListView;
import com.chinasofti.adapter.InfoAdapter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ViewHolderListViewActivity extends AppCompatActivity {
private ListView listViewInfo;
private List<Map<String, ?>> listItems;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_holder_list_view);
this.listItems = this.getListItems();
InfoAdapter adapter = new InfoAdapter(this.listItems, this);
this.listViewInfo = (ListView) findViewById(R.id.listViewInfo);
this.listViewInfo.setAdapter(adapter);
}
private List<Map<String, ?>> getListItems() {
List<Map<String, ?>> listItems = new ArrayList<>();
Map<String, Object> item01 = new HashMap<>();
item01.put("id", 1);
item01.put("imgIcon", R.drawable.photo01);
item01.put("txtUserName", "西施");
item01.put("txtInfo", "西施发送的消息发送的消息发送的消息发送的消息发送的消息发送的消息发送的消息");
item01.put("txtPublish", new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date()));
item01.put("layoutImages", "0");
item01.put("layoutReplys", "1");
listItems.add(item01);
Map<String, Object> item02 = new HashMap<>();
item02.put("id", 2);
item02.put("imgIcon", R.drawable.photo02);
item02.put("txtUserName", "貂蝉");
item02.put("txtInfo", "貂蝉发送的消息发送的消息发送的消息发送的消息发送的消息发送的消息发送的消息");
item02.put("txtPublish", new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date()));
item02.put("layoutImages", "1");
item02.put("layoutReplys", "0");
listItems.add(item02);
Map<String, Object> item03 = new HashMap<>();
item03.put("id", 3);
item03.put("imgIcon", R.drawable.photo03);
item03.put("txtUserName", "吕布");
item03.put("txtInfo", "吕布发送的消息发送的消息发送的消息发送的消息发送的消息发送的消息发送的消息");
item03.put("txtPublish", new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date()));
item03.put("layoutImages", "1");
item03.put("layoutReplys", "1");
listItems.add(item03);
return listItems;
}
}
网友评论