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"
tools:context=".Chat"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:id="@+id/chatRecyclerView"
></androidx.recyclerview.widget.RecyclerView>
<LinearLayout
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"
></EditText>
<Button
android:id="@+id/send"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="發送"
tools:ignore="InvalidId"></Button>
</LinearLayout>
</LinearLayout>
編寫chat Activity
class Chat : AppCompatActivity(), View.OnClickListener {
private val msgList =ArrayList<Msg>()
private var adapter:MsgAdapter?=null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_chat)
initMsg()
val layoutManager=LinearLayoutManager(this)
chatRecyclerView.layoutManager=layoutManager
adapter= MsgAdapter(msgList)
chatRecyclerView.adapter=adapter
send.setOnClickListener(this)
}
private fun initMsg(){
val msg1=Msg("在嗎?",Msg.TYPE_RECEIVED)
msgList.add(msg1)
val msg2=Msg("在",Msg.TYRE_SENT)
msgList.add(msg2)
val msg3=Msg("上號!!",Msg.TYPE_RECEIVED)
msgList.add(msg3)
}
override fun onClick(v: View?) {
when(v){
send -> {
val content = inputText.text.toString()
if(content.isNotEmpty()){
val msg=Msg(content,Msg.TYRE_SENT)
msgList.add(msg)
adapter?.notifyItemInserted(msgList.size - 1)//當有新消息時,刷新RecyclerView中的顯示
chatRecyclerView.scrollToPosition(msgList.size-1)//定位到最後一行
inputText.setText("")
}
}
}
}
}
創建實體類Msg
class Msg(val content:String,val type:Int) {
companion object{
const val TYPE_RECEIVED=0
const val TYRE_SENT=1
}
}
創建MsgAdapter
class MsgAdapter (val msgList:List<Msg>): RecyclerView.Adapter<RecyclerView.ViewHolder>() {
inner class LeftViewHolder(view:View):RecyclerView.ViewHolder(view){
val leftMsg : TextView=view.findViewById(R.id.leftMsg)
}
inner class RightViewHolder(view:View):RecyclerView.ViewHolder(view){
val rightMsg : TextView=view.findViewById(R.id.rightMsg)
}
override fun getItemViewType(position: Int): Int {
val msg =msgList[position]
return msg.type
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int)=if (viewType==Msg.TYPE_RECEIVED) {
val view = LayoutInflater.from(parent.context).inflate(R.layout.msg_left_item,parent,false)
LeftViewHolder(view)
}else{
val view = LayoutInflater.from(parent.context).inflate(R.layout.msg_right_item,parent,false)
RightViewHolder(view)
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val msg =msgList[position]
when(holder){
is LeftViewHolder -> holder.leftMsg.text=msg.content
is RightViewHolder -> holder.rightMsg.text=msg.content
else -> throw IllegalArgumentException()
}
}
override fun getItemCount(): Int {
return msgList.size
}
}
創建兩個xml
1msg_left_item
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:orientation="vertical"
>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:background="@drawable/message_left"
>
<TextView
android:id="@+id/leftMsg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="10dp"
android:textColor="#fff"
></TextView>
</LinearLayout>
</FrameLayout>
2.msg_right_item
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:orientation="vertical"
>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/message_right"
android:layout_gravity="right"
>
<TextView
android:id="@+id/rightMsg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="10dp"
android:textColor="#000"
></TextView>
</LinearLayout>
</FrameLayout>
2.Kotlin增強
2.1對變量延遲初始化
關鍵字lateinit
class Chat : AppCompatActivity(), View.OnClickListener {
private val msgList =ArrayList<Msg>()
// private var adapter:MsgAdapter?=null
private lateinit var adapter : MsgAdapter
val content = inputText.text.toString()
if(content.isNotEmpty()){
val msg=Msg(content,Msg.TYRE_SENT)
msgList.add(msg)
// adapter?.notifyItemInserted(msgList.size - 1)//當有新消息時,刷新RecyclerView中的顯示
adapter.notifyItemInserted(msgList.size - 1)
chatRecyclerView.scrollToPosition(msgList.size-1)//定位到最後一行
inputText.setText("")
它可以告訴Kotlin編譯器,我們會延遲初始化的
判斷全局變量是否完成初始化
if(!::adapter.isInitialized){
adapter= MsgAdapter(msgList)
}
2.2使用密封優化代碼
關鍵字 sealed class
創建一個Kotlin文件 Result.kt
sealed class Result
class Success(val msg:String ) : Result()
class Failure (val error:Exception) : Result()
fun getResultMsg(result: Result)=when(result){
is Success ->result.msg
is Failure ->result.error.message
}
當When語句傳入一個密封類變量作爲條件時,kotlin編譯器會自動檢查該密封類有哪些子類,並強制要求你將每一個子類對應的條件全部處理。這樣幫助及時沒有編寫else條件也不肯出現漏寫的情況。