使用RecycleView显示聊天消息,使用Nine-patche图片作为聊天气泡,实现我和我自己聊天。素材可以去阿里巴巴矢量图标库下载,然后可以通过我上上篇博客学习RecycleView的使用,通过上一篇博客学习制作Nine-Patch图片。
效果图
1. 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:orientation="vertical"
tools:context=".ChatActivity.ChatActivity">
<TextView
android:layout_width="match_parent"
android:layout_height="48dp"
android:gravity="center"
android:text="@string/String1"/>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginBottom="5dp"
android:background="@color/mypink"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycleview"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
/>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/mypink"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="72dp"
android:padding="10dp"
android:orientation="horizontal">
<EditText
android:id="@+id/content"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:background="@drawable/shape_button_transparent_pinkstroke"/>
<Button
android:id="@+id/btn_send"
android:layout_width="100dp"
android:layout_height="match_parent"
android:text="发送"
android:layout_marginLeft="10dp"
android:background="@drawable/shape_button_pink_corners"/>
</LinearLayout>
</LinearLayout>
2. item_for_message.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:layout_margin="10dp"
android:orientation="vertical">
<LinearLayout
android:id="@+id/left_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start"
android:gravity="center"
android:orientation="horizontal">
<ImageView
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginRight="10dp"
android:src="@drawable/shuguang" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minHeight="30dp"
android:background="@mipmap/chatframe_pink_left"
android:orientation="horizontal">
<TextView
android:id="@+id/left_msg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:padding="10dp"
android:text="@string/String1" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/right_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:gravity="center"
android:orientation="horizontal">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@mipmap/chatframe_pink_right"
android:orientation="horizontal">
<TextView
android:id="@+id/right_msg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:padding="10dp"
android:text="@string/String1" />
</LinearLayout>
<ImageView
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginLeft="10dp"
android:src="@drawable/xiyao" />
</LinearLayout>
</LinearLayout>
3. Messages
/**
* create by 星航指挥官
* create on 2020/8/30
* 我为天帝 当镇压世间一切敌
* 遮天
*/
public class Messages {
public static final int TYPE_RECEIVED = 0;
public static final int TYPE_SEND = 1;
private String content;
private int type;
public Messages() {
}
public Messages(String content, int type) {
this.content = content;
this.type = 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;
}
}
4. MessageAdapter
/**
* create by 星航指挥官
* create on 2020/8/30
* 我为天帝 当镇压世间一切敌
* 遮天
*/
public class MessageAdapter extends RecyclerView.Adapter<MessageAdapter.ViewHolder> {
//创建一个全局变量,存储数据源,以便进行后续操作
private List<Messages> messagesList;
/*
*创建内部类ViewHolder继承RecyclerView.ViewHolder
* ViewHolder的构造器要传入一个View参数
* 用来获取自定义布局中的对象
*/
static class ViewHolder extends RecyclerView.ViewHolder{
//保存布局实例
View view;
//声明自定义布局中的控件
LinearLayout leftlayout;
LinearLayout rightlayout;
TextView leftcontent;
TextView rightcontent;
public ViewHolder(@NonNull View itemView) {
super(itemView);
//保存布局实例
view = itemView;
//获取控件
leftlayout = itemView.findViewById(R.id.left_layout);
rightlayout = itemView.findViewById(R.id.right_layout);
leftcontent = itemView.findViewById(R.id.left_msg);
rightcontent = itemView.findViewById(R.id.right_msg);
}
}
/*
* 适配器的构造方法
* 主要用于将要展示的数据传入
* 然后存储到全局变量中
* */
public MessageAdapter(List<Messages> messagesList) {
this.messagesList = messagesList;
}
/*
* 继承RecyclerView.Adapter必须要重写
* 该方法主要用于创建ViewHolder实例
* */
@NonNull
@Override
public MessageAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
//加载自定义布局
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_for_message,parent,false);
//将布局传入ViewHolder的构造器获得ViewHolder实例
MessageAdapter.ViewHolder holder = new MessageAdapter.ViewHolder(view);
//为控件设置监听
//...
//返回ViewHolder实例
return holder;
}
/*
* 继承RecyclerView.Adapter必须要重写
* 该方法主要用于对RecycleView的子项进行赋值
* 会在每个子项被滚动到屏幕内的时候执行
* */
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
//通过position参数得到当前项的数据源实列
Messages messages = messagesList.get(position);
//然后将实例的数据设置到ViewHolder声明的控件中
if (messages.getType() == Messages.TYPE_SEND){
holder.leftlayout.setVisibility(View.GONE);
holder.rightcontent.setText(messages.getContent());
}else if (messages.getType() == Messages.TYPE_RECEIVED){
holder.rightlayout.setVisibility(View.GONE);
holder.leftcontent.setText(messages.getContent());
}
}
/*
* 继承RecyclerView.Adapter必须要重写
* 该方法主要用于返回RecycleView子项的数量
* 直接返回数据源的长度就可以了
* */
@Override
public int getItemCount() {
return messagesList.size();
}
}
5. ChatActivity
/**
* create by 星航指挥官
* create on 2020/8/30
* 我为天帝 当镇压世间一切敌
* 遮天
*/
public class ChatActivity extends BaseActivity {
private List<Messages> messagesList = new ArrayList<>();
MessageAdapter adapter;
@BindView(R.id.recycleview)
RecyclerView recycleview;
@BindView(R.id.content)
EditText content;
@BindView(R.id.btn_send)
Button btnSend;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat);
ButterKnife.bind(this);
setRecycleView();
}
/*
* 给RecycleView设置布局和适配器
* */
private void setRecycleView() {
//线性布局:layoutManager
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
//layoutManager1.setOrientation(RecyclerView.HORIZONTAL);//setOrientation()控制方向,默认垂直
//设置recycle布局管理器
recycleview.setLayoutManager(layoutManager);
//创建Adapter实例
adapter = new MessageAdapter(messagesList);
//给RecycleView设置适配器
recycleview.setAdapter(adapter);
}
private int type = 1;
@OnClick(R.id.btn_send)
public void onViewClicked() {
String str = content.getText().toString();
if (!"".equals(str)) {
if (type == 1) {
type = 0;
Messages msg = new Messages(str, Messages.TYPE_SEND);
messagesList.add(msg);
//刷新适配器
adapter.notifyItemInserted(messagesList.size() - 1);
//定位到最后一条
recycleview.scrollToPosition(messagesList.size() - 1);
//清空输入框内容
content.setText("");
} else {
type = 1;
Messages msg = new Messages(str, Messages.TYPE_RECEIVED);
messagesList.add(msg);
//刷新适配器
adapter.notifyItemInserted(messagesList.size() - 1);
//定位到最后一条
recycleview.scrollToPosition(messagesList.size() - 1);
//清空输入框内容
content.setText("");
}
}
}
}
kee