Android列表用法之二:实战ListView高级用法

本文介绍如何使用ListView实现类似QQ聊天界面的复杂布局。内容包括ListView的使用,圆形头像AvatarImageView的选择,消息框的组合,以及通过在Adapter中重写方法来标识不同布局。此外,还展示了数据实体类、各部分布局XML的实现和最终运行效果。
摘要由CSDN通过智能技术生成

在我们的项目中,并不是所有列表都是简单的使用。类似于新闻列表、QQ聊天列表等,具有图文并排的列表,每个item都有它不同的布局类型,都有其不同的实现方式。这类复杂的列表表现形式,在各类知名应用当中,不可或缺的存在着。今天我们就来看看,使用ListView能不能实现此类复杂布局。

今天的实例为众所周知的QQ聊天界面:
这里写图片描述

一、纵观全局
1、一个ListView。
2、圆形头像和消息框。
3、时间分隔行。

二、技术选型
1、列表当然选择ListView,我们今天使用的就是这个。
2、圆形头像,目前三方开源的比较多,有CircleImageView、AvatarImageView等可以选择,今天我就选择AvatarImageView。为什么要选择这个,它是我常用的控件之一,只是最近使用它的频率比较高,就选择它了。后续我会有专门贴子说明圆形头像控件的选择。
3、文本框+layout组合成消息框。文本框显示消息内容,layout显示消息背景泡泡。
4、item的实现有几种方法:
1)写一个布局xml文件。里面include三个xml布局,一是自己发送消息,消息显示在右边的布局。二是对方发消息,消息显示在界面左边的布局。三是时间布局,显示在中间,并起到分隔作用。然后根据不同的消息类型,控制布局的显示与隐藏。
2)根据数据时间变化,以及不同消息的类型。直接构造不同的布局文件。这样就比较轻量级。不会在同一个布局当中,存在许多无用的布局。
3)在此我选择第一种方式,因为ListView有所限制,使用第二种方式不是特别方便。第二种方式我会使用后续的RecyclerView来讲解。

三、码代码
1、在上一篇listview简单用法当中,我们使用的viewholder,是集成在adapter当中进行优化的。另外,在这里我引入另外一个解耦合比较高的ViewHolder的写法。
另外新建一个专门的ViewHolder类,在里面实现静态的getViewHolder方法,比较简单,只是将内容移了个地方而已,直接看代码:

package oliver.zhantao.oliverproject.listviewhigh;

import android.view.View;
import android.view.ViewStub;
import android.widget.TextView;

import cn.carbs.android.avatarimageview.library.AvatarImageView;
import oliver.zhantao.oliverproject.R;

/**
 * ViewHolder的抽离,单独形成一个类,可以让代码更加明了
 * 另外,也可以使adapter更加轻量级,降低耦合性。
 * <p>
 * 将ViewHolder的实现方法完全封装在其本身的类中,功能更强大
 * 其方法与Adapter的getView()方法隔离,条理更加清晰,降低耦合性
 * 当getView()中需要实现多种样式时,不需要写重复代码
 * <p>
 * Created by ZhanTao on 2017/4/19.
 */

public class HighViewHolder {
   
    public View mineView;
    public View otherView;
    public View timeView;
    public AvatarImageView mineView_head;
    public AvatarImageView otherView_head;
    public TextView mineView_message;
    public TextView otherView_message;
    public TextView timeView_time;

    // 构造函数中就初始化View
    public HighViewHolder(View convertView) {
        mineView = convertView.findViewById(R.id.view_mine);
        otherView = convertView.findViewById(R.id.view_other);
        timeView = convertView.findViewById(R.id.view_time);
        mineView_head = (AvatarImageView) mineView.findViewById(R.id.aiv_head);
        otherView_head = (AvatarImageView) otherView.findViewById(R.id.aiv_head);
        mineView_message = (TextView) mineView.findViewById(R.id.tv_message);
        otherView_message = (TextView) otherView.findViewById(R.id.tv_message);
        timeView_time = (TextView) timeView.findViewById(R.id.tv_time);
    }

    // 得到一个ViewHolder
    public static HighViewHolder getViewHolder(View convertView) {
        HighViewHolder viewHolder = (HighViewHolder) convertView.getTag();
        if (viewHolder == null) {
            viewHolder = new HighViewHolder(convertView);
            convertView.setTag(viewHolder);
        }
        return viewHolder;
    }

}

2、再来看我们的adapter,在这个adapter当中,直接通过静态方法就可以获取ViewHolder实例,是不是简单明了多了。注意看getView方法。


package oliver.zhantao.oliverproject.listviewhigh;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;

import java.util.List;

import oliver.zhantao.oliverproject.R;

/**
 * 聊天列表适配器,在这里将数据与控件进行绑定
 * <p>
 * 项目中都是自定义适配器,很少用到系统提供的简易适配器。 所以果断抛弃系统的简易适配器,自定义想咋样就咋样,一个字,爽^_^
 * <p>
 * Created by ZhanTao on 2017/4/17.
 */

public class ListViewHighAdapter extends BaseAdapter {
   
    private Context mContext;
    // 餐厅列表
    private List<MessageBean> messageList;
    private LayoutInflater mInflater;

    public ListViewHighAdapter(Context context, List<MessageBean> messageList) {
        this.mContext = context;
        this.messageList = messageList;
        mInflater = LayoutInflater.from(context);
    }

    @Override
    public int getCount() {
        return messageList.size();
    }

    @Override
    public Object getItem(int position) {
        return position;
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public int getViewTypeCount() {
        // 已经知道有三种布局了,直接写死。当然也可以做成一个可扩展的,项目中灵活性更强。
        return 3;
    }

    @Override
    public int getItemViewType(int position) {
        return messageList.get(position).getLayoutType();
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        HighViewHolder holder;
        // 1、优化框架搭起
        if (convertView == null) {
            convertView = mInflater.inflate(R.layout.activity_listview_high_item, null);
        }
        //这样使用Holder,简单明了,还不占用adapter
        holder = HighViewHolder.getViewHolder(convertView);
        // 2、绑定数据到控件
        bindViewData(position, convertView, holder);
        // 3、控制VIEW的显示与隐藏
        controlViewVisible(position, holder);
        // 4、绑定监听事件
        bindViewClickListene
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值