一個簡潔漂亮的聊天界面:界面編寫實戰(zhàn)-kotlin

目前還只能自言自語,日后會考慮使用圖靈機器人的API寫一個完整的AI聊天程序

效果

image

image

布局源碼


整體布局activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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=".MainActivity">
    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_margin="16dp"
            android:text="只會說一句話的聊天機器人"
            android:textAlignment="center"
            android:textColor="#000000"
            android:textSize="18sp" />o

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recyclerView"
            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:background="@drawable/bottom_background">

                <EditText
                    android:id="@+id/editText"
                    style="@style/Widget.AppCompat.AutoCompleteTextView"
                    android:layout_width="0dp"
                    android:layout_height="wrap_content"
                    android:layout_margin="10dp"
                    android:layout_weight="1"
                    android:background="@null"
                    android:layout_gravity="center"
                    android:hint="@string/hint_text"
                    android:maxLines="2" />

                <Button
                    android:id="@+id/send_button"
                    style="@style/Widget.AppCompat.Button.Borderless.Colored"
                    android:textColor="#42D363"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="@string/send" />
            </LinearLayout>


    </LinearLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

左聊天氣泡布局msg_left_layout.xml

<?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:layout_marginRight="100dp"
    android:padding="10dp">

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="left"
        android:layout_margin="5dp"
        android:background="@drawable/left_chat">

        <TextView
            android:id="@+id/leftText"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="10dp"
            android:textColor="#191919"
            android:textSize="16dp" />
    </LinearLayout>
</FrameLayout>

右聊天氣泡布局msg_right_layout.xml

<?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:layout_marginLeft="100dp"
    android:padding="10dp">

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="right"
        android:layout_margin="5dp"
        android:background="@drawable/right_chat">

        <TextView
            android:id="@+id/rightText"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="10dp"
            android:textColor="#fff"
            android:textSize="16dp" />
    </LinearLayout>


</FrameLayout>

邏輯實現(xiàn)MainActivity.kt

package com.example.chatui

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import android.widget.TextView
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.activity_main.*
import org.w3c.dom.Text
import java.lang.IllegalArgumentException
//定義消息的實體類
class Msg(val content:String,val type:Int){
    //定義靜態(tài)成員
    companion object{
        const val RIGHT = 0
        const val LEFT = 1
    }
};
class MainActivity : AppCompatActivity() {
    //建立消息數(shù)據(jù)列表
    private val msgList = ArrayList<Msg>()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        supportActionBar?.hide()  //隱藏頂部狀態(tài)欄
        initMsg()   //初始化聊天機器人的見面語
        recyclerView.layoutManager = LinearLayoutManager(this)  //布局為線性垂直
        val adapter = MsgAdapter(msgList)   //建立適配器實例
        recyclerView.adapter = adapter  //傳入適配器
        send_button.setOnClickListener{
            val content:String = editText.text.toString()   //獲取輸入框的文本
            if(content.isNotEmpty()){
                msgList.add(Msg(content,Msg.RIGHT))     //將輸入的消息及其類型添加進消息數(shù)據(jù)列表中
                adapter.notifyItemInserted(msgList.size-1)   //為RecyclerView添加末尾子項
                recyclerView.scrollToPosition(msgList.size-1) //跳轉(zhuǎn)到當前位置
                editText.setText("")    //清空輸入框文本
            }

        }

    }

    fun initMsg(){
        msgList.add(Msg("Hello",Msg.LEFT))
    }
}
class MsgAdapter(val msgList:List<Msg>):RecyclerView.Adapter<RecyclerView.ViewHolder>(){

    //載入右聊天框布局控件
    inner class RightViewHolder(val view: View):RecyclerView.ViewHolder(view){
        val rightMsg: TextView = view.findViewById(R.id.rightText)
    }
    //載入左聊天框布局控件
    inner class LeftViewHolder(val view:View):RecyclerView.ViewHolder(view){
        val leftMsg:TextView = view.findViewById(R.id.leftText)
    }
    //獲取消息類型(左或者右),返回到onCreateViewHolder()方法的viewType參數(shù)里面
    override fun getItemViewType(position: Int): Int {
        val msg = msgList[position] //根據(jù)當前數(shù)據(jù)源的元素類型
        return msg.type
    }
    //根據(jù)viewType消息類型的不同,構(gòu)建不同的消息布局(左&右)
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        if(viewType==Msg.LEFT){
            val leftView = LayoutInflater.from(parent.context).inflate(R.layout.msg_left_layout,parent,false)
            return LeftViewHolder(leftView) //返回控件+布局
        }else{
            val rightView = LayoutInflater.from(parent.context).inflate(R.layout.msg_right_layout,parent,false)
            return RightViewHolder(rightView)
        }

    }
    //對聊天控件的消息文本進行賦值
    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()
        }
    }
    //返回項數(shù)
    override fun getItemCount(): Int {
        return msgList.size
    }


}

完整代碼: https://github.com/cnatom/ChatBot

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市分冈,隨后出現(xiàn)的幾起案子圾另,更是在濱河造成了極大的恐慌,老刑警劉巖雕沉,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件集乔,死亡現(xiàn)場離奇詭異,居然都是意外死亡坡椒,警方通過查閱死者的電腦和手機扰路,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來肠牲,“玉大人幼衰,你說我怎么就攤上這事∽忽ǎ” “怎么了僚纷?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長缕棵。 經(jīng)常有香客問我入愧,道長,這世上最難降的妖魔是什么深碱? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任腹鹉,我火速辦了婚禮,結(jié)果婚禮上敷硅,老公的妹妹穿的比我還像新娘功咒。我一直安慰自己,他們只是感情好绞蹦,可當我...
    茶點故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布力奋。 她就那樣靜靜地躺著,像睡著了一般幽七。 火紅的嫁衣襯著肌膚如雪景殷。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天澡屡,我揣著相機與錄音猿挚,去河邊找鬼。 笑死驶鹉,一個胖子當著我的面吹牛绩蜻,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播室埋,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼办绝,長吁一口氣:“原來是場噩夢啊……” “哼踏兜!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起八秃,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤碱妆,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后昔驱,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體疹尾,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年骤肛,在試婚紗的時候發(fā)現(xiàn)自己被綠了纳本。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡腋颠,死狀恐怖繁成,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情淑玫,我是刑警寧澤巾腕,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布土涝,位于F島的核電站佛寿,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏但壮。R本人自食惡果不足惜冀泻,卻給世界環(huán)境...
    茶點故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蜡饵。 院中可真熱鬧弹渔,春花似錦捞附、人聲如沸巾乳。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽压状。三九已至仆抵,卻和暖如春跟继,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背镣丑。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工舔糖, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人莺匠。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓金吗,卻偏偏與公主長得像,于是被迫代替她去往敵國和親趣竣。 傳聞我的和親對象是個殘疾皇子摇庙,可洞房花燭夜當晚...
    茶點故事閱讀 44,592評論 2 353