美文网首页
Android学习笔记12—自定义 ListView开发详解(二

Android学习笔记12—自定义 ListView开发详解(二

作者: advance_bravely | 来源:发表于2016-09-29 20:37 被阅读59次
引言

该节介绍如何在开发中使用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;
  }
}

相关文章

网友评论

      本文标题:Android学习笔记12—自定义 ListView开发详解(二

      本文链接:https://www.haomeiwen.com/subject/fjklyttx.html