先看效果图。是不是你们想要的。大概就是这样的效果

Android 实现左右布局聊天界面(好友左、自己右)
采用 RecyclerView + 双布局 Item 实现,结构清晰、可直接复用,适配聊天气泡样式。
一、整体思路
两种 Item 布局:
item_msg_left.xml:对方消息(居左)
item_msg_right.xml:自己消息(居右)
消息实体类:记录消息内容、发送者类型
RecyclerView 适配器:根据类型加载不同布局
气泡背景:自带圆角、区分左右样式
二、1. 消息实体类 MsgBean
java
public class MsgBean {
// 消息文本
private String content;
// 0=对方消息(左) 1=自己消息(右)
private int msgType;
public MsgBean(String content, int msgType) {
this.content = content;
this.msgType = msgType;
}
// getter & setter
public String getContent() {
return content;
}
public int getMsgType() {
return msgType;
}
}
三、2. 左边 Item 布局(对方消息)item_msg_left.xml
java
<?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">
<TextView
android:id="@+id/tv_msg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:maxWidth="250dp"
android:textColor="#333333"
android:background="@drawable/bg_msg_left"/>
</LinearLayout>
- 右边 Item 布局(自己消息)item_msg_right.xml
java
<?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="right">
<TextView
android:id="@+id/tv_msg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:maxWidth="250dp"
android:textColor="#FFFFFF"
android:background="@drawable/bg_msg_right"/>
</LinearLayout>
四、4. 气泡背景 drawable
bg_msg_left.xml(左侧灰色气泡)
java
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#E5E5E5"/>
<corners
android:topLeftRadius="5dp"
android:topRightRadius="15dp"
android:bottomLeftRadius="15dp"
android:bottomRightRadius="15dp"/>
</shape>
bg_msg_right.xml(右侧蓝色气泡)
java
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#0099FF"/>
<corners
android:topLeftRadius="15dp"
android:topRightRadius="5dp"
android:bottomLeftRadius="15dp"
android:bottomRightRadius="15dp"/>
</shape>
五、5. RecyclerView 适配器 MsgAdapter
java
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
public class MsgAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final List<MsgBean> msgList;
// 区分两种布局类型
private static final int TYPE_LEFT = 0;
private static final int TYPE_RIGHT = 1;
public MsgAdapter(List<MsgBean> msgList) {
this.msgList = msgList;
}
// 根据消息类型返回布局
@Override
public int getItemViewType(int position) {
return msgList.get(position).getMsgType();
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
if (viewType == TYPE_LEFT) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_msg_left, parent, false);
return new LeftHolder(view);
} else {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_msg_right, parent, false);
return new RightHolder(view);
}
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
MsgBean bean = msgList.get(position);
if (holder instanceof LeftHolder) {
((LeftHolder) holder).tvMsg.setText(bean.getContent());
} else if (holder instanceof RightHolder) {
((RightHolder) holder).tvMsg.setText(bean.getContent());
}
}
@Override
public int getItemCount() {
return msgList.size();
}
// 左边ViewHolder
static class LeftHolder extends RecyclerView.ViewHolder {
TextView tvMsg;
public LeftHolder(@NonNull View itemView) {
super(itemView);
tvMsg = itemView.findViewById(R.id.tv_msg);
}
}
// 右边ViewHolder
static class RightHolder extends RecyclerView.ViewHolder {
TextView tvMsg;
public RightHolder(@NonNull View itemView) {
super(itemView);
tvMsg = itemView.findViewById(R.id.tv_msg);
}
}
// 添加消息 + 自动滚动到底部
public void addMsg(MsgBean bean) {
msgList.add(bean);
notifyItemInserted(msgList.size() - 1);
}
}
六、6. 主界面布局 activity_chat.xml
java
<?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="match_parent"
android:orientation="vertical">
<!-- 聊天列表 -->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_chat"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
<!-- 输入栏 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="8dp">
<EditText
android:id="@+id/et_input"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="输入消息"/>
<Button
android:id="@+id/btn_send"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="发送"/>
</LinearLayout>
</LinearLayout>
七、7. 聊天 Activity 逻辑 ChatActivity.java
java
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.List;
public class ChatActivity extends AppCompatActivity {
private RecyclerView recyclerChat;
private EditText etInput;
private MsgAdapter msgAdapter;
private List<MsgBean> msgList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat);
recyclerChat = findViewById(R.id.recycler_chat);
etInput = findViewById(R.id.et_input);
Button btnSend = findViewById(R.id.btn_send);
// 初始化列表
msgList = new ArrayList<>();
msgAdapter = new MsgAdapter(msgList);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
recyclerChat.setLayoutManager(layoutManager);
recyclerChat.setAdapter(msgAdapter);
// 模拟对方默认消息
msgAdapter.addMsg(new MsgBean("你好呀", 0));
// 发送按钮点击
btnSend.setOnClickListener(v -> {
String content = etInput.getText().toString().trim();
if (!content.isEmpty()) {
// 添加自己消息(右)
msgAdapter.addMsg(new MsgBean(content, 1));
etInput.setText("");
// 自动滚动到底部
recyclerChat.scrollToPosition(msgAdapter.getItemCount() - 1);
}
});
}
}
效果说明
1.好友消息:左侧灰色气泡
2.自己消息:右侧蓝色气泡
3.发送消息自动滚到底部
4.消息最大宽度限制,长文本自动换行
八、软键盘弹出自动上移聊天列表(安卓聊天界面必备)
默认情况下:弹出输入法键盘时,RecyclerView 聊天列表不会往上顶,输入框会被键盘遮挡、最新消息被键盘盖住看不到。
软键盘弹起 → 整个聊天布局自动上移
最新消息自动显示在键盘上方,不会被遮挡
AndroidManifest.xml 配置(最简单,一行搞定)
找到你的 ChatActivity 对应的 activity 标签,添加属性:
xml
android:windowSoftInputMode="adjustResize"
完整示例:
xml
<activity
android:name=".ChatActivity"
android:windowSoftInputMode="adjustResize">
</activity>