Android进阶——RecycleView的使用之自定义聊天界面(三)_android 聊天recycle_CrazyMo_的博客-程序员秘密

技术标签: RecyclView  自定义View  UI  Android 进阶  android  # Android系统组件使用  # Android自定义View  聊天界面  

引言

最近在项目中有一项是智能语音识别和唤醒的功能,正好需要用到类似聊天的界面,一开始有点懵,后面再去看了一下官方说明文档,发现了一个无论是在AdapterView的Apdapter还是RecycleView的Adapter中常常被很多教程忽略的方法(先卖个关子),也间接导致了不了解的人走了很多弯路,还好我比较喜欢先看api,因为有些时候再第一次学的时忽略掉了一些api,没有走多少弯路,借助于这个方法瞬间思路豁然开朗。

一、RecycleView大致的工作流程

RecycleView得以正常完成基本的工作离不开RecycleView.Adapter和RecyclerView.LayoutManager,RecycleView相当于只是一个容器,如果没有Adapter那么它就没有任何价值。Acitivty通过布局加载RecycleView,然后触发对应的生命周期方法,去完成AdapterView的初始化工作:首先肯定是调用Adapter的构造方法——>然后调用getItemCount()方法——>getItemViewType()——>再调用onCreateViewHolder()来创建ViewHolder——>自然进入到ViewHolder的构造方法——>最后再到onBindViewHolder()把数据和View填充到ViewHolder里
这里写图片描述
创建第二个item时
这里写图片描述

二、自定义聊天界面的核心思路

我想通过上面的Log信息,已经不难看出来,RecycleView本身已经提供了这样的一个动态创建ItemView的机制,我们只需要在每次创建的时候,根据一个标记值去加载不同的布局创建不同的ViewHolder即可,而getItemViewType()正好提供了这个值,还传递到了onCreateViewHolder里

  • getItemViewType的原型
/**
*如果不重写,默认返回0,代表该适配器所有Item都是一种布局。可以通过重写来实现在一个适配器里适配多种布局
*/
int getItemViewType (int position)
  • onCreateViewHolder(ViewGroup parent, int viewType)

三、实现自定义聊天界面

1、在Gradle脚本里引入RecycleView

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.jakewharton:butterknife:7.0.1'
    compile 'com.android.support:appcompat-v7:24.2.0'
    compile 'com.android.support:recyclerview-v7:24.0.0'
}

2、实现接收/发送信息时的item布局

这里有个小技巧:LinearLayout水平方向默认是从左到右布局的,但是可以通过设置gravity属性来改变布局的起点

item_response.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="wrap_content"
    android:padding="10dp"
    android:gravity="left"
    android:orientation="horizontal">
    <ImageView
        android:id="@+id/iv_response"
        android:layout_width="32dp"
        android:layout_height="32dp"
        android:src="@mipmap/ic_respnonse"
        />
    <TextView
        android:id="@+id/tv_resopense"
        android:padding="2dp"
        android:layout_width="120dp"
        android:layout_height="30dp"
        android:gravity="center"
        android:textSize="20sp"
        android:background="@mipmap/delay_time_wait"
        android:text="Hi~~" />
</LinearLayout>

item_send.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="wrap_content"
    android:padding="10dp"
    android:orientation="horizontal"
    android:gravity="right">
    <TextView
        android:id="@+id/tv_send"
        android:layout_width="200dp"
        android:layout_height="30dp"
        android:textAlignment="center"
        android:padding="2dp"
        android:gravity="center"
        android:textSize="20sp"
        android:text="Hello!!~"
        android:background="@mipmap/delay_time_over"
        />
    <ImageView
        android:id="@+id/iv_send"
        android:layout_width="32dp"
        android:layout_height="32dp"
        android:src="@mipmap/ic_send"
        />
</LinearLayout>

3、封装Bean实现Adapter

public class ChatBean {
    String content;
    Drawable drawable;//可以通过这个来修改头像
    int type;//用于标识告知Adpater应该创建的是哪一类的ItenView

    public ChatBean(String content, Drawable drawable, int type) {
        this.content = content;
        this.drawable = drawable;
        this.type = type;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public Drawable getDrawable() {
        return drawable;
    }

    public void setDrawable(Drawable drawable) {
        this.drawable = drawable;
    }

    public int getType() {
        return type;
    }

    public void setType(int type) {
        this.type = type;
    }
}
/*为了方便这个类是写在MainActivity里作为内部类的*/
class ChatAdapter extends RecyclerView.Adapter<ChatAdapter.ChatViewHolder> {
    

        private List<ChatBean> chatBeanList;
        private LayoutInflater inflater;

        public ChatAdapter(Context context,List<ChatBean> chatBeans){
            this.chatBeanList=chatBeans;
            this.inflater=LayoutInflater.from(context);
        }

        @Override
        public ChatViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            ChatViewHolder holder;
            //根据ViewType值创建不同的ViewHolder
            if(viewType==0) {
                holder = new ChatViewHolder(LayoutInflater.from(
                        MainActivity.this).inflate(R.layout.item_response, parent,
                        false));
            }
            else{
                holder = new ChatViewHolder(LayoutInflater.from(
                        MainActivity.this).inflate(R.layout.item_send, parent,
                        false));
            }
            return holder;
        }

        @Override
        public int getItemViewType(int position) {
            return chatBeanList.get(position).getType();//**返回集合Bean里的值作为标记值将传递到onCreateViewHolder里
        }

        @Override
        public void onBindViewHolder(ChatViewHolder holder, int position) {
            //这里只是简单的实现了设置聊天内容并未对头像处理
            if(chatBeanList.get(position).getType()==0) {
                holder.tvResponse.setText(chatBeanList.get(position).getContent());
            }else {
                holder.tvSend.setText(chatBeanList.get(position).getContent());
            }
        }

        @Override
        public int getItemCount() {
            return chatBeanList.size();
        }
        //简单实现的ViewHolder,开发中最好再做些优化可以参考上一篇
        class ChatViewHolder extends RecyclerView.ViewHolder {
    

            TextView tvResponse;
            TextView tvSend;

            public ChatViewHolder(View view) {
                super(view);
                tvResponse = (TextView) view.findViewById(R.id.tv_resopense);
                tvSend=(TextView)view.findViewById(R.id.tv_send);
            }
        }
    }

4、实现Activity

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

/**
 * @auther: Crazy.Mo
 * Date: 2016/10/11
 * Time:01:01
 * Des:
 */
public class MainActivity extends Activity {
    
    private RecyclerView recyclerView;
    private List<ChatBean> chatBeanList;
    private ChatAdapter chatAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();
    }

    private void getViews() {
        recyclerView = (RecyclerView) findViewById(R.id.listv_chatting);
    }

    private void initAdapter(){
        chatBeanList=new ArrayList<>();
        chatBeanList.add(new ChatBean("Hello~~~",null,0));
        chatBeanList.add(new ChatBean("Nice to meet U",null,1));
        chatBeanList.add(new ChatBean("Me tooo",null,0));
        chatBeanList.add(new ChatBean("LOL~~~",null,1));
        chatBeanList.add(new ChatBean("LOL~~~",null,1));
        chatBeanList.add(new ChatBean("LOL~~~",null,0));
    }
    private void initRecyclerView(){
        //设置布局管理器
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        //设置adapter
        recyclerView.setAdapter(new ChatAdapter(this, chatBeanList));
        //设置默认动画
        recyclerView.setItemAnimator(new DefaultItemAnimator());
    }

    private void init() {
        getViews();
        initAdapter();
        initRecyclerView();
    }
}

这里写图片描述

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/CrazyMo_/article/details/52701303

智能推荐

基因数据处理10之BWA处理速度太慢_如何提高bwa的速度_KeepLearningBigData的博客-程序员秘密

基因数据处理9之BWA处理速度太慢:[email protected]:~/cloud/adam/xubo/data/data_HDFS/GRCH38/GCA_000001405.15_GRCh38/test20160310$ bwa aln GCA_000001405.15_GRCh38/GCA_000001405.15_GRCh38_full_analysis_set.fna SRR003161

又来秀焊接技术了!_芯片之家的博客-程序员秘密

作者:晓宇,排版:晓宇微信公众号:芯片之家(ID:chiphome-dy)1、这就是芯片原型了,老哥这祖传的焊接手艺我服了,献上我的膝盖不过江山代有才人出,下面这几位表示不服2、芯片杯...

基于Simulink 与TI DSP的模型设计的环境搭建(一)_ti dsp基于simulink的开发_hilloword的博客-程序员秘密

前言 一、什么是基于模型的设计 二、基于模型的设计对于电力电子工程师以及控制工程师的意义 三、Simulink 与TI DSP的模型设计的环境搭建前言Simulink除了提供基本的算法模块外,还提供了提供的优质的可视化环境(matlab的UI工程师真的好赞呀)。于此同时Simulink还提供了多种coder工具,包括MATLAB Coder、Embedded Coder、HDL Coder、GPU Coder等。我们主要使用Embedded Coder,对目标硬件进行代码生成。...

Verilog学习之求两个数的差值设计_verilog两个无符号数相减_一个默默无闻的小程序员的博客-程序员秘密

今天我们做的是第七道题——求两个数的差值,其实听名字就可以知道这道题其实特别的简单,只是两个数之间的比较求差而已,所以这道题我们就不具体写思路了,直接附上代码。[

FPGA之道(45)正确的变量访问思路_fpga变量初始化_李锐博恩的博客-程序员秘密

变量的访问思路,简而言之就是“一写多读”,即如果有多个并行语句需要操作一个变量时,有且只能有一个固定的并行语句可以对变量进行写操作,而所有的并行语句都可以对变量进行读操作,因为一个变量只能有一个驱动源,如果被多个驱动源驱动,就会产生冲突。

安全方向比路由交换难吗_互联网最离不开的设备,路由器和交换机你了解吗?..._weixin_39872123的博客-程序员秘密

21世纪前20年,互联网发展影响工业化的进程,让人与人之间沟通更加方便快捷,每天接收着地球上发生各类信息,供你阅读。互联网已深深影响我们的生活,互联网已经是生活中不可缺失的基本需求。问题就来了,这些网络是靠什么传输到我们手机或电脑的呢,今天我一起了解下互联网组成的重要设备,路由器和交换机。路由器的主要功能是实现不同网络的数据转发,交换机用于扩展内网范围,实现内网数据交换。路由器属于三层设备,处理I...

随便推点

python 爬虫实战 抓取学校bbs相关板块的发帖信息_爬虫bbs代表什么_枯萎的海风的博客-程序员秘密

1. 前言之前也因为感兴趣, 写过一个抓取桌面天空里面喜欢的动漫壁纸的爬虫代码。这两天突然看到有人写了这么一篇文章: 爬取京东本周热卖商品基本信息存入MySQL 觉得蛮有趣的, 正好临近找工作的季节, 就想着能不能写个爬虫, 把咱们学校bbs上面相关的板块里面的发帖信息给记录下来。2. 项目分析首先我们打开我们的目标网页http://bbs.ustc.edu.cn/main.html 结

从国内的 PyPI 镜像(源)安装 Python 包_weixin_34356138的博客-程序员秘密

不论是使用 pip,还是 Pipenv、Poetry 等工具,安装 Python 包的时候会默认从官方的 PyPI 源下载文件,速度比较慢。国内的一些公司和机构提供了 PyPI 镜像源(mirror source),你可以设置让这些工具从国内的镜像源安装 Python 包,以便提高下载速度。官方 PyPI 源的 URL 为 https://pypi.org/simple (旧的 URL 为 htt...

基于FPGA的AES加密解密vivado仿真,verilog开发,包含testbench_aes128 verilog_我爱C编程的博客-程序员秘密

AES原理:AES是对数据按128位,也就是16个字节进行分组进行加密的,每次对一组数据加密需要运行多轮,而输入密钥的长度可以为128、192和256位,也就是16个字节、24个字节和32个字节,如果用户输入的密钥长度不是这几种长度,也会补成这几种长度。AES算法在对明文加密的时候,并不是把整个明文一股脑的加密成一整段密文,而是把明文拆分成一个个独立的明文块,每一个明文块长度128bit。无论输入密钥是多少字节,加密还是以16字节的数据一组来进行的,密钥长度的不同仅仅影响加密运行的轮数。

Redisson入门_unable to decode data. channel_梦青尘的博客-程序员秘密

一、Redisson是什么?二、使用步骤1.引入库2.Redisson 配置2.增(改)3.删4.查5.测试类三、遇到错误(ERROR org.redisson.client.handler.CommandDecoder - Unable to decode data. channel)总结参考资料

Python - Python vs Java: Key Differences_做人,最重要的就是开心嘛的博客-程序员秘密

分享一个大牛的人工智能教程。零基础!通俗易懂!风趣幽默!希望你也加入到人工智能的队伍中来!请点击http://www.captainbed.netPython and Java are two very different programming languages, but both can be useful tools for modern developers. If you are ...

BERT+使用transformers库加载自己数据集做BERT预训练(普通方式+TrainerAPI)_import transformers_RunningQzh的博客-程序员秘密

Word Embedding在NLP任务中,我们需要对文本进行编码,使之成为计算机可以读懂的语言。在编码时,我们期望句子之间保持词语间的相似性。word embedding做的事情就是把一个词映射到低维的稠密空间,切语义相近的词向量离得比较近。...

推荐文章

热门文章

相关标签