RecyclerView是什么?
一个用于大量数据展示的新控件RecylerView,可以用来代替传统的ListView,更加强大和灵活。可以实现横向滚动(ListView做不到)和瀑布流控件。
使用RecyclerView编写一个聊天界面
- 在app/build.gradle中添加依赖(RecyclerView在AndroidX包里)
//实现RecyclerView要添加依赖
implementation 'androidx.recyclerview:recyclerview:1.0.0'
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>
界面效果图:
- 定义消息的实体类,新建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;
}
}
- 编写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>
界面效果图:
- 创建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();
}
}
- 编写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;
}
}
真机运行效果图: