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

智能推荐

FSMC配置_fsmc layout要求_industrienorm的博客-程序员秘密

FSMC配置控制一个NOR闪存存储器,需要FSMC提供下述功能:●选择合适的存储块映射NOR闪存存储器:共有4个独立的存储块可以用于与NOR闪存、SRAM和PSRAM存储器接口,每个存储块都有一个专用的片选管脚。●使用或禁止地址/数据总线的复用功能。●选择所用的存储器类型:NOR闪存、SRAM或PSRAM。●定义外部存储器的数据总线宽度:8或16位。●使用或关闭同步NOR闪

84.7%!BoTNet:视觉识别的Bottleneck Transformers_Amusi(CVer)的博客-程序员秘密

基于Transformer的新backbone来了!在ImageNet上高达84.7%的top-1精度,性能优于SENet、EfficientNet等,将其应用于目标检测、实例分割等下游任务,涨点显著!代码即将开源!实验做得相当充分!注1:文末附【Transformer】流群Bottleneck Transformers for Visual Recognition作者单位:UC Berkeley, 谷歌论文:https://arxiv.org/abs/2101.11605我们介绍BoTNe

使用spring-data-elasticsearch进行自定义打分_aa28786109的博客-程序员秘密

近期工作中有个小小的推荐需求,其实更像是一个条件多一点的匹配排序功能。需求大致如下:A产品与B客户的部分过滤属性全部满足,其余属性满足至少一个,则可以展示在推荐列表中,但是展示优先级按照属性c1,c2,c3,c4是否匹配(实际应用中有大致二十个条件)。可以使用支持自定义打分的工具如solr,es等来比较好的实现 c1属性权重23 =8 分 c2属性权重4分 c3权重2分 c4...

java.lang.NumberFormatException: multiple points_at sun.misc.floatingdecimal.parsefloat_幺零小柒的博客-程序员秘密

今天生产环境报了如下异常:java.lang.NumberFormatException: multiple points at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1890) at sun.misc.FloatingDecimal.parseDouble(FloatingDecimal...

DS 证据理论_ds证据理论_lilyweiG的博客-程序员秘密

DS证据理论学习笔记 参考资料:浙江大学徐从富教授   可见点击打开链接 一、经典证据理论       1、经典证据理论的主要特点:        ①满足比比贝叶斯概率更弱的条件,即不必蛮子概率可加性        ②具有直接表达“不确定”和“不知道”的能力        ③证据理论不但允许人们将信度赋予假设空间的单个元素,而且还能赋予他的子集        ...

【caffe-MATLAB】自己编译faster-rcnn的MATLAB版本_浩瀚之水_csdn的博客-程序员秘密

今天在自己的电脑上编译MATLAB版本的faster-RCNN代码,将过程在这作一记录。1.我的环境:Windows10 ,VS2013 , MATLAB2017a ,CUDA7.5首先下载作者的源码:https://github.com/ShaoqingRen/faster_rcnn[html] view plain copy ### Preparat

随便推点

android-小知识_adolph_jun的博客-程序员秘密

1、android studio 新建shape 的xml文件   drawable里面 new一个 Drawable resource xml 一般打开是selector ,把selector改成shape2、得到textview的值String displatText = (String)display.getText();

可重新设置偏置电压的放大电路_运放的偏置电压怎么加_lookingsnow的博客-程序员秘密

在实际应用中,我们常常遇到这样的情况:输入信号是骑在某个直流电平上的,现在需要对这个信号进行放大,同时重新设置其偏置电压,也就是让它骑在另一个电压上。下图电路的输入信号是骑在1V上,可以重新设置输出偏置电压的一个3倍同相放大电路。对其分析如下:首先,分析静态时的电路状态。当电路处于静态时,正输入端只有1V电压(输入信号的直流电平),此时根据虚短,负输入端的电压也为1V,设此时运放的输出电压为Uo,设VDC1电压为Vref(图中设置为2V,暂且不管),根据虚断,以下公式成立:(Uo – 1)/2 = (

解决Intel/AMD双显卡环境下Ubuntu系统过热问题_Flood_Dragon的博客-程序员秘密

本文转自:http://ubuntuforums.org/showthread.php?t=1930450If you do want to make the switch possible between your Intel and your AMD graphics cards, then this post is for you. If you do n

springboot搭建个人博客(前后端分离,附源码)_springboot个人博客源码_IT资源 itit2022的博客-程序员秘密

springboot搭建个人博客(完整代码,更新中)首先呢,先说明一声,这个项目还在不断更新中,现在前后台可以简单交互起来了,现在正在些搜索功能的后台,使用的是elasticsearch,对了,还有再说一点,我是学后台的,所以前台搭的不好的话,不要建议哦,其实我已经尽力,尽了我的洪荒之力了,嘻嘻

G2文法之最左推导_证明语法有一个最左推导_acsuperman的博客-程序员秘密

G2E-&amp;gt;E+T | E-T | TT-&amp;gt;T*F | T/F |FF-&amp;gt;(E) | nn-&amp;gt;0 | 1 |2 |… |9注意扫描是从右向左扫描,第一次的展开其实得到的是最后一个符号。如果遇到+或-,则将表达式中的E变为E+T或E-T;如果遇到*或/,则将表达式中的T变成T*F或T/F;如果遇到括号对,则将表达式中的F变成(E);如果没有符号,只有数字,则将表达式中的E变成T...

Spring项目搭建三(整合mybaties)_spring.core.minidle_muum_sun的博客-程序员秘密

Spring整合了Springmvc后,再整合mybaties.首先,依旧是添加依赖:整合mybaties需要添加的依赖有: org.mybatis mybatis ${mybatis.version} org.mybatis mybatis-spring

推荐文章

热门文章

相关标签