前言
1. 简单定义Msg类
package com.bytedance.sjtu.msg
class Msg(val msg: String, val msgType: Int) {
companion object {
const val SEND = 0 //定义消息类型,0为发送, 1为收取
const val GET = 1
}
}
2. ChatActivity
class ChatActivity : AppCompatActivity() {
private val tvName : TextView by lazy { findViewById(R.id.tvName) }
private val recyclerView : RecyclerView by lazy { findViewById(R.id.recyclerView) }
private val editMsg : EditText by lazy { findViewById(R.id.editMsg) }
private val sendMsg : TextView by lazy { findViewById(R.id.sendMsg) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_chat)
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) //设置隐藏状态栏
val msgList = mutableListOf(
Msg( "你好", Msg.SEND),
Msg( "嗯嗯", Msg.GET),
Msg( "How are you?", Msg.SEND),
Msg( "I'm fine, thanks.", Msg.GET),
)
recyclerView.layoutManager = LinearLayoutManager(this)
recyclerView.adapter = ChatAdapter(this, msgList) //简单初始化聊天信息
editMsg.addTextChangedListener(object : TextWatcher { //监听消息输入框的输入状态
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
}
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
}
override fun afterTextChanged(p0: Editable?) {
if (editMsg.text.isNotEmpty()) {
sendMsg.setTextColor(resources.getColor(R.color.silver_red)) //输入框有内容,发布字体变红色
} else {
sendMsg.setTextColor(resources.getColor(R.color.light_gray)) //否则变灰色
}
}
})
sendMsg.setOnClickListener {
if (editMsg.text.isNotEmpty()) {
val msgType = Random.nextInt(0, 2) //随机生成 0 和 1
msgList.add(Msg(editMsg.text.toString(), msgType)) //模拟“发送消息”和“接收消息”
recyclerView.adapter = ChatAdapter(this, msgList) //更新适配器数据
recyclerView.scrollToPosition(msgList.size - 6)
recyclerView.smoothScrollBy(0, 1000, DecelerateInterpolator(), 1500) //平滑刷新消息界面,有bug
editMsg.text = null //输入框置空
}
}
}
}
3. 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"
android:fitsSystemWindows="true"
tools:context=".msg.ChatActivity">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="50dp">
<ImageView
android:id="@+id/imgBack"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginStart="5dp"
android:padding="15dp"
android:src="@drawable/ic_back" />
<TextView
android:id="@+id/tvName"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center"
android:gravity="center"
android:text="name"
android:textSize="20sp"
android:textColor="@color/black" />
<View
android:layout_width="match_parent"
android:layout_height="0.1dp"
android:layout_gravity="bottom"
android:background="@color/light_gray" />
</FrameLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#EAEDF6" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/editMsg"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_margin="10dp"
android:padding="12dp"
android:hint="输入..."
android:textSize="18sp"
android:background="@drawable/bg_round_rectangle_2" />
<TextView
android:id="@+id/sendMsg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_marginEnd="10dp"
android:layout_marginBottom="10dp"
android:text="发送"
android:textStyle="bold"
android:textSize="20sp"
android:textColor="@color/light_gray" />
</LinearLayout>
</LinearLayout>
4. ChatAdapter适配器
class ChatAdapter(
private val mContext: Context,
private val msgList: MutableList<Msg>
): RecyclerView.Adapter<ChatAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.layout_chat_item_view, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) { //绑定数据
if (msgList[position].msgType == Msg.SEND) { //发出的消息
holder.msgSend.text = msgList[position].msg
holder.msgSend.visibility = View.VISIBLE
holder.msgGet.visibility = View.GONE
} else if (msgList[position].msgType == Msg.GET) { //收到的消息
holder.msgGet.text = msgList[position].msg
holder.msgGet.visibility = View.VISIBLE
holder.msgSend.visibility = View.GONE
}
holder.itemView.setOnClickListener {
// Toast.makeText(mContext, "You click msg $position", Toast.LENGTH_SHORT).show()
}
}
override fun getItemCount(): Int {
return msgList.size
}
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val msgSend : TextView = itemView.findViewById(R.id.msgSend)
val msgGet : TextView = itemView.findViewById(R.id.msgGet)
}
}
5. layout_chat_item_view.XML布局文件
其中TextView的background应该设置为9-Patch文件,也就是.9.png文件,可以自己制作。
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="10dp">
<TextView
android:id="@+id/msgSend"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="25dp"
android:layout_gravity="end"
android:text="这是发送的消息"
android:textSize="18sp"
android:textColor="@color/white"
android:background="@drawable/bg_bubble_1_50" />
<TextView
android:id="@+id/msgGet"
android:gravity="start"
android:visibility="visible"
android:background="@drawable/bg_bubble_2_50"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="25dp"
android:text="这是收到的消息"
android:textSize="18sp"
android:textColor="@color/black" />
</FrameLayout>