RecyclerView是什么?

一个用于大量数据展示的新控件RecylerView,可以用来代替传统的ListView,更加强大和灵活。可以实现横向滚动(ListView做不到)和瀑布流控件。

使用RecyclerView编写一个聊天界面

  1. 在app/build.gradle中添加依赖(RecyclerView在AndroidX包里)
//实现RecyclerView要添加依赖
    implementation 'androidx.recyclerview:recyclerview:1.0.0'

android 设置RecyclerView设置头部 androidx.recyclerview.widget.recyclerview_数据

2.编写主界面activity_chat.xml中的代码

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#d8e0e8"
    android:orientation="vertical"
    tools:context=".ChatActivity">

    <androidx.appcompat.widget.Toolbar
        android:id="@+id/tool_bar_setting"
        xmlns:app="http //schemas android com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="@color/purple_200"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
        tools:ignore="MissingConstraints"></androidx.appcompat.widget.Toolbar>
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/msg_recycler_view"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1">
    </androidx.recyclerview.widget.RecyclerView>
    <LinearLayout
        android:layout_below="@id/tool_bar_setting"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        >
        <EditText
            android:id="@+id/inputText"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:hint="Type something here"
            android:maxLines="2"
            ></EditText>
        <Button
            android:id="@+id/send"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAllCaps="false"
            android:text="send"></Button>
<!--        android:textAllCaps="false"  使button的默认大写变小写-->
    </LinearLayout>

</LinearLayout>

界面效果图:

android 设置RecyclerView设置头部 androidx.recyclerview.widget.recyclerview_xml_02

  1. 定义消息的实体类,新建Msg
package com.example.networktest;

public class Msg {

    static final int TYPE_RECEIVED = 0;//表示一条收到的消息
    static final int TYPE_SEND = 1;//表示一条发出的消息

    private String content;//表示消息内容
    private int type;//表示消息的类型

    public String getContent() {
        return content;
    }

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

    public int getType() {
        return type;
    }

    public void setType(int type) {
        this.type = type;
    }


    public Msg(String content, int type) {
        this.content = content;
        this.type = type;
    }



}
  1. 编写RecyclerView子项的布局,新建msg_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="10dp">

    <LinearLayout
        android:id="@+id/left_layout"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="left"
        android:background="@drawable/po_left">

        <TextView
            android:id="@+id/left_msg"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_margin="10dp"
            android:textColor="#fff"></TextView>
    </LinearLayout>

    <LinearLayout
        android:id="@+id/right_layout"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="right"
        android:layout_margin="10dp"
        android:background="@drawable/po_right"
        android:orientation="horizontal"
        tools:ignore="RtlHardcoded">

        <TextView
            android:id="@+id/right_msg"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_margin="10dp"></TextView>
    </LinearLayout>


</LinearLayout>

界面效果图:

android 设置RecyclerView设置头部 androidx.recyclerview.widget.recyclerview_android_03

  1. 创建RecyclerView的适配器类,新建类MsgAdapter
package com.example.networktest;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import java.util.List;

public class MsgAdapter extends RecyclerView.Adapter<MsgAdapter.ViewHolder> {

    private List<Msg> mMsgList;

    static class ViewHolder extends RecyclerView.ViewHolder {

        LinearLayout leftLayout;//做边子项布局

        LinearLayout rightLayout;//右边子项布局

        TextView leftMsg;//左边消息(接收)

        TextView rightMSg;//右边消息(发送)

        //绑定item控件 
        public ViewHolder(View view) {

            super(view);

            leftLayout = view.findViewById(R.id.left_layout);

            rightLayout = view.findViewById(R.id.right_layout);

            leftMsg = view.findViewById(R.id.left_msg);

            rightMSg = view.findViewById(R.id.right_msg);

        }
    }

    //绑定 数据
    public MsgAdapter(List<Msg> msgList) {

        mMsgList = msgList;
    }

    //绑定 显示页面
    // onCreateViewHolder 用于创建一个ViewHolder实例
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.msg_item, parent, false);
        return new ViewHolder(view);
    }


    //对消息类型的判断
    //onBindViewHolder 用于对RecyclerView子项的数据进行赋值的
    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {

        //获得 当前的Msg实例
        Msg msg = mMsgList.get(position);

        //如果是 收到的消息,则显示左边的消息布局,将右边的消息布局隐藏
        if (msg.getType() == Msg.TYPE_RECEIVED) {

            holder.leftLayout.setVisibility(View.VISIBLE);

            holder.rightLayout.setVisibility(View.GONE);

            //消息内容
            holder.leftMsg.setText(msg.getContent());

        } else if (msg.getType() == Msg.TYPE_SEND) {
            //如果是 发出的消息,则显示右边的消息布局,将左边的消息布局隐藏
            holder.rightLayout.setVisibility(View.VISIBLE);

            holder.leftLayout.setVisibility(View.GONE);

            //消息内容
            holder.rightMSg.setText(msg.getContent());
        }


    }

    //获取 RecyclerView一共有多少子项
    @Override
    public int getItemCount() {
        return mMsgList.size();
    }
}
  1. 编写ChatActivity.java,为RecyclerView初始化数据,并给发送按钮加入事件响应
package com.example.networktest;

import androidx.appcompat.app.AppCompatActivity;

import androidx.appcompat.widget.Toolbar;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.Toast;

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

public class ChatActivity extends AppCompatActivity {

    private Toolbar tool_bar_setting;

    private List<Msg> msgList = new ArrayList<>();
    private EditText inputText;//文本输入框
    private Button send;//发送按钮
    private RecyclerView msgRecyclerView;
    private MsgAdapter mAdapter;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_chat);
        init();
        initMsgs();
        listen();
    }

    private void init() {
        //绑定 Toolbar
        tool_bar_setting = findViewById(R.id.tool_bar_setting);

        //得到toolBar实例
        setSupportActionBar(tool_bar_setting);

        //显示 tool_bar左侧按钮
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);


//            setSupportActionBar(toolbar);参数报错
//            Android Studio 自动导包错误
//            import android.widget.Toolbar;
//            将上面的代码替换成下面的
//            import androidx.appcompat.widget.Toolbar;

        inputText = findViewById(R.id.inputText);

        send = findViewById(R.id.send);

        msgRecyclerView = findViewById(R.id.msg_recycler_view);

        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);

        msgRecyclerView.setLayoutManager(linearLayoutManager);

        //给适配器绑定数据
        mAdapter = new MsgAdapter(msgList);

        //给RecyclerView控件绑定适配器
        msgRecyclerView.setAdapter(mAdapter);

    }

    private void listen() {

        send.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                String content = inputText.getText().toString();

                //发送内容不为空时
                if (!"".equals(content)) {

                    //将数据传入实体类
                    Msg msg = new Msg(content, Msg.TYPE_SEND);

                    msgList.add(msg);

                    //有新消息时刷新msgRecyclerView
                    mAdapter.notifyItemInserted(msgList.size() - 1);
                    
                    //将 RecyclerView 定位到最后一行,以保证可以看到最后发出的一条消息
                    msgRecyclerView.scrollToPosition(msgList.size()-1);

                    //发送完 清空输入框中的内容
                    inputText.setText("");
                }
            }
        });
    }

    //初始化几条 接收到的消息(毕竟是个没有联网的聊天界面)
    private void initMsgs() {

        Msg msg1 = new Msg("hello guy.", Msg.TYPE_RECEIVED);

        msgList.add(msg1);

        Msg msg2 = new Msg("hello. Who is that ?", Msg.TYPE_SEND);

        msgList.add(msg2);

        Msg msg3 = new Msg("This is Tom.Nice talking to you.", Msg.TYPE_RECEIVED);

        msgList.add(msg3);


    }

    //加载 toorlbar.xml这个菜单文件
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.tool_bar_setting, menu);
        return true;
    }

    //处理多个按钮的点击事件
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                Intent intent = new Intent(ChatActivity.this, MainActivity.class);
                startActivity(intent);
                finish();
                break;
            case R.id.love_setting:
                Toast.makeText(this, "you clicked love", Toast.LENGTH_SHORT).show();
                break;
        }
        return true;
    }
}

真机运行效果图:

android 设置RecyclerView设置头部 androidx.recyclerview.widget.recyclerview_数据_04