赞
踩
安装并配置好Android Studio
Android Studio Electric Eel | 2022.1.1 Patch 2
Build #AI-221.6008.13.2211.9619390, built on February 17, 2023
Runtime version: 11.0.15+0-b2043.56-9505619 amd64
VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o.
Windows 11 10.0
GC: G1 Young Generation, G1 Old Generation
Memory: 1280M
Cores: 6
Registry:
external.system.auto.import.disabled=true
ide.text.editor.with.preview.show.floating.toolbar=false
ide.balloon.shadow.size=0
Non-Bundled Plugins:
com.intuit.intellij.makefile (1.0.15)
com.github.setial (4.0.2)
com.alayouni.ansiHighlight (1.2.4)
GsonOrXmlFormat (2.0)
GLSL (1.19)
com.mistamek.drawablepreview.drawable-preview (1.1.5)
com.layernet.plugin.adbwifi (1.0.5)
com.likfe.ideaplugin.eventbus3 (2020.0.2)
gradle-wrapper.properties
- #Tue Apr 25 13:34:44 CST 2023
- distributionBase=GRADLE_USER_HOME
- distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
- distributionPath=wrapper/dists
- zipStorePath=wrapper/dists
- zipStoreBase=GRADLE_USER_HOME
build.gradle(:Project)
- // Top-level build file where you can add configuration options common to all sub-projects/modules.
- plugins {
- id 'com.android.application' version '7.3.1' apply false
- id 'com.android.library' version '7.3.1' apply false
- id 'org.jetbrains.kotlin.android' version '1.7.20' apply false
- }
setting.gradle
- pluginManagement {
- repositories {
- google()
- mavenCentral()
- gradlePluginPortal()
- maven { url 'https://jitpack.io' }
- }
- }
- dependencyResolutionManagement {
- repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
- repositories {
- google()
- mavenCentral()
- gradlePluginPortal()
- maven { url 'https://jitpack.io' }
- }
- }
- rootProject.name = "logindemo"
- include ':app'

build.gralde(:app)
- plugins {
- id 'com.android.application'
- id 'org.jetbrains.kotlin.android'
- }
-
- android {
- namespace 'com.example.fechat'
- compileSdk 33
-
- defaultConfig {
- applicationId "com.example.fechat"
- minSdk 26
- targetSdk 33
- versionCode 1
- versionName "1.0"
- }
-
- buildTypes {
- release {
- minifyEnabled false
- proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
- }
- }
- compileOptions {
- sourceCompatibility JavaVersion.VERSION_11
- targetCompatibility JavaVersion.VERSION_11
- }
- kotlinOptions {
- jvmTarget = '1.8'
- }
- }
-
- dependencies {
-
- implementation 'androidx.core:core-ktx:1.7.0'
- implementation 'androidx.appcompat:appcompat:1.6.1'
- implementation 'com.google.android.material:material:1.8.0'
- implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
-
- // 沉浸式状态栏 https://github.com/gyf-dev/ImmersionBar
- implementation 'com.gyf.immersionbar:immersionbar:3.0.0'
- implementation 'com.gyf.immersionbar:immersionbar-components:3.0.0' // fragment快速实现(可选)
- implementation 'com.gyf.immersionbar:immersionbar-ktx:3.0.0' // kotlin扩展(可选)
- implementation 'com.google.code.gson:gson:2.8.9'
- }

对Kotlin语言有基本了解
内容在前一篇博客中写了基础配置,如果本篇内容看不懂,可以先去上一篇。
activity_message.xml中 标题+内容RecyclerView+底部输入框+发送
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:fitsSystemWindows="true">
-
- <RelativeLayout
- android:id="@+id/titleLayout"
- android:layout_width="match_parent"
- android:layout_height="50dp"
- android:background="@color/title">
-
- <TextView
- android:id="@+id/backTv"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="返回"
- android:textSize="16sp"
- android:textColor="#000000"
- android:padding="10dp"
- android:layout_centerVertical="true"
- android:layout_marginStart="15dp"/>
-
- <TextView
- android:id="@+id/userName"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="用户X"
- android:textSize="16sp"
- android:textColor="#000000"
- android:layout_centerInParent="true"/>
-
- </RelativeLayout>
-
-
- <androidx.recyclerview.widget.RecyclerView
- android:id="@+id/itemView"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="@color/white"
- android:layout_below="@+id/titleLayout"
- android:layout_above="@+id/messageLayout"/>
-
- <RelativeLayout
- android:id="@+id/messageLayout"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- android:background="#F6F6F6"
- android:gravity="center_vertical">
-
- <EditText
- android:id="@+id/inputText"
- android:layout_width="match_parent"
- android:layout_height="40dp"
- android:background="@drawable/message_text_shape"
- android:layout_toStartOf="@+id/sendText"
- android:layout_marginStart="16dp"
- android:layout_marginTop="6dp"
- android:layout_marginEnd="6dp"
- android:layout_marginBottom="6dp"
- android:padding="10dp"
- android:maxLines="1"
- android:singleLine="true"
- android:textSize="16sp"
- android:textColor="#000000"/>
-
- <TextView
- android:id="@+id/sendText"
- android:layout_width="70dp"
- android:layout_height="40dp"
- android:background="@drawable/message_send_shape"
- android:layout_alignParentEnd="true"
- android:layout_marginStart="6dp"
- android:layout_marginTop="6dp"
- android:layout_marginEnd="16dp"
- android:layout_marginBottom="6dp"
- android:textSize="16sp"
- android:textColor="@color/white"
- android:text="发送"
- android:gravity="center"/>
- </RelativeLayout>
-
- </RelativeLayout>

- package com.example.fechat.activity
-
- import android.annotation.SuppressLint
- import android.os.Bundle
- import android.widget.EditText
- import android.widget.TextView
- import androidx.appcompat.app.AppCompatActivity
- import androidx.recyclerview.widget.LinearLayoutManager
- import androidx.recyclerview.widget.RecyclerView
- import com.example.fechat.R
- import com.example.fechat.adapter.ChatAdapter
- import com.example.fechat.bean.ChatBean
- import com.example.fechat.bean.MessageBean
- import com.google.gson.Gson
- import com.gyf.immersionbar.ImmersionBar
-
- class MessageActivity : AppCompatActivity() {
- private val beans: MutableList<MessageBean> = ArrayList()
- private var adapter: ChatAdapter? = null
- private lateinit var itemView: RecyclerView
- private lateinit var chatBean: ChatBean
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- ImmersionBar.with(this)
- .statusBarDarkFont(true)
- .statusBarColor(R.color.title)
- .navigationBarColor(R.color.white)
- .navigationBarDarkIcon(true)
- .init()
- setContentView(R.layout.activity_message)
- val backTv = findViewById<TextView>(R.id.backTv)
- val inputText: EditText = findViewById(R.id.inputText)
- val sendText: TextView = findViewById(R.id.sendText)
- val userName: TextView = findViewById(R.id.userName)
- backTv.setOnClickListener {
- finish()
- }
- sendText.setOnClickListener {
- sendText(inputText.text.toString())
- }
- initItemRecyclerView()
- getBundle()
- userName.text = chatBean.nick
- }
-
- private fun getBundle() {
- val userInfo = intent.getStringExtra("UserInfo")
- chatBean = Gson().fromJson(userInfo, ChatBean::class.java)
- }
-
- private fun initItemRecyclerView() {
- itemView = findViewById(R.id.itemView)
- val layoutManager = LinearLayoutManager(this)
- layoutManager.orientation = RecyclerView.VERTICAL
- itemView.layoutManager = layoutManager
- adapter = ChatAdapter(beans)
- itemView.adapter = adapter
- }
-
- @SuppressLint("NotifyDataSetChanged")
- private fun sendText(message: String) {
- beans.add(
- MessageBean(
- message,
- "用户",
- false,
- System.currentTimeMillis()
- )
- )
- beans.add(
- MessageBean(
- message,
- chatBean.nick,
- true,
- System.currentTimeMillis(),
- true
- )
- )
- adapter?.notifyDataSetChanged()
- }
- }

适配器的xml中,分为两部分 主用户发送消息,同时接收聊天对象的消息
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- xmlns:app="http://schemas.android.com/apk/res-auto">
-
- <RelativeLayout
- android:id="@+id/userLayout"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginStart="30dp"
- android:layout_marginTop="10dp">
-
- <com.example.fechat.view.CircleImageView
- android:id="@+id/userHead"
- android:layout_width="46dp"
- android:layout_height="46dp"
- android:src="@mipmap/ic_ai_user"
- android:layout_alignParentEnd="true"/>
-
- <androidx.constraintlayout.widget.ConstraintLayout
- android:id="@+id/messageLayout"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_toStartOf="@+id/userHead"
- android:layout_marginEnd="12dp">
-
- <TextView
- android:id="@+id/userMessage"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintEnd_toEndOf="parent"
- android:background="@drawable/message_user_shape"
- android:textSize="16sp"
- android:textColor="@color/black"
- android:paddingStart="15dp"
- android:paddingEnd="15dp"
- android:paddingTop="20dp"
- android:paddingBottom="20dp"
- android:text="请推荐"
- android:textIsSelectable="true"/>
-
- <TextView
- android:id="@+id/userTime"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- app:layout_constraintTop_toBottomOf="@+id/userMessage"
- app:layout_constraintStart_toStartOf="parent"
- android:text="22:32"
- android:textColor="#B1B1B1"
- android:textSize="14sp"
- android:layout_marginTop="8dp"/>
-
- </androidx.constraintlayout.widget.ConstraintLayout>
-
- </RelativeLayout>
-
- <RelativeLayout
- android:id="@+id/respLayout"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginEnd="30dp"
- android:layout_marginTop="10dp"
- android:visibility="gone">
-
- <com.example.fechat.view.CircleImageView
- android:id="@+id/respHead"
- android:layout_width="46dp"
- android:layout_height="46dp"
- android:src="@mipmap/ic_ai_user"/>
-
- <androidx.constraintlayout.widget.ConstraintLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_toEndOf="@+id/respHead"
- android:layout_marginStart="12dp">
-
- <RelativeLayout
- android:id="@+id/respMessageLayout"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toTopOf="parent"
- android:background="@drawable/message_ai_shape">
-
- <TextView
- android:id="@+id/respMessage"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textSize="16sp"
- android:textColor="@color/black"
- android:paddingStart="15dp"
- android:paddingEnd="15dp"
- android:paddingTop="20dp"
- android:paddingBottom="20dp"
- android:text="小猪佩奇"
- android:textIsSelectable="true"/>
-
- <ImageView
- android:id="@+id/respImage"
- android:layout_width="220dp"
- android:layout_height="160dp"
- android:layout_below="@+id/respMessage"
- android:scaleType="center"
- android:layout_marginStart="20dp"
- android:layout_marginEnd="20dp"
- android:layout_marginBottom="20dp"
- android:visibility="gone"/>
-
- </RelativeLayout>
- <TextView
- android:id="@+id/respTime"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="22:32"
- android:textColor="#B1B1B1"
- android:textSize="14sp"
- android:layout_marginTop="8dp"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintTop_toBottomOf="@+id/respMessageLayout"/>
-
- </androidx.constraintlayout.widget.ConstraintLayout>
- </RelativeLayout>
-
- </RelativeLayout>

- package com.example.fechat.adapter
-
- import android.view.LayoutInflater
- import android.view.View
- import android.view.ViewGroup
- import android.widget.ImageView
- import android.widget.RelativeLayout
- import android.widget.TextView
- import androidx.recyclerview.widget.RecyclerView
- import androidx.recyclerview.widget.RecyclerView.Adapter
- import com.example.fechat.R
- import com.example.fechat.bean.MessageBean
- import com.example.fechat.view.CircleImageView
- import java.text.SimpleDateFormat
- import java.util.*
-
- class ChatAdapter(private val data: List<MessageBean>) : Adapter<ChatAdapter.BaseHolder>() {
-
- private fun getTime(time: Long): String {
- val sDateFormat = SimpleDateFormat("MM-dd HH:mm", Locale.getDefault())
- return sDateFormat.format(time)
- }
-
- class BaseHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
- val userLayout: RelativeLayout = itemView.findViewById(R.id.userLayout)
- val userHead: CircleImageView = itemView.findViewById(R.id.userHead)
- val userMessage: TextView = itemView.findViewById(R.id.userMessage)
- val userTime: TextView = itemView.findViewById(R.id.userTime)
-
- val respLayout: RelativeLayout = itemView.findViewById(R.id.respLayout)
- val respHead: CircleImageView = itemView.findViewById(R.id.respHead)
- val respMessage: TextView = itemView.findViewById(R.id.respMessage)
- val respTime: TextView = itemView.findViewById(R.id.respTime)
- val respImage: ImageView = itemView.findViewById(R.id.respImage)
- }
-
- override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseHolder {
- val view = LayoutInflater.from(parent.context).inflate(R.layout.item_message, null, false);
- return BaseHolder(view)
- }
-
- override fun getItemCount(): Int {
- return data.size
- }
-
- override fun onBindViewHolder(holder: BaseHolder, position: Int) {
- val item = data[position]
- if (item.isResponse) {
- holder.respLayout.visibility = View.VISIBLE
- holder.userLayout.visibility = View.GONE
- holder.respMessage.text = item.message
- holder.respTime.text = getTime(item.time)
- } else {
- holder.userLayout.visibility = View.VISIBLE
- holder.respLayout.visibility = View.GONE
- holder.userMessage.text = item.message
- holder.userTime.text = getTime(item.time)
- }
- }
- }

聊天内容适配器中的data数据结构如下:
- package com.example.fechat.bean
-
- data class MessageBean(
- var message: String,
- var userName: String,
- var isResponse: Boolean = false,
- var time: Long,
- var isSuccess: Boolean = true
- )
其中首页用户聊天列表中的data修改,主要是data转化为string方便intent传输,如下:
- package com.example.fechat.bean
-
- data class ChatBean(
- val head: String, val nick: String,
- val newest: String, val date: String
- ) {
- override fun toString(): String {
- return "{head:$head,nick:$nick,newest:$newest,date:$date}"
- }
- }
首页用户聊天记录的适配器作如下修改,主要是增加了适配器点击事件监听器:
- package com.example.fechat.base
-
- import android.view.LayoutInflater
- import android.view.View
- import android.view.ViewGroup
- import android.widget.TextView
- import androidx.recyclerview.widget.RecyclerView
- import com.example.fechat.R
- import com.example.fechat.bean.ChatBean
-
- class BaseAdapter(private val data: List<ChatBean>) :
- RecyclerView.Adapter<BaseAdapter.BaseHolder>() {
-
- private lateinit var onItemClickListener: OnItemClickListener
- override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseHolder {
- val view = LayoutInflater.from(parent.context).inflate(R.layout.base_item, null, false);
- return BaseHolder(view)
- }
-
- override fun getItemCount(): Int {
- return data.size
- }
-
- override fun onBindViewHolder(holder: BaseHolder, position: Int) {
- holder.headTv.visibility = if (data[position].head.isEmpty()) View.GONE else View.VISIBLE
- holder.nickTv.visibility = if (data[position].nick.isEmpty()) View.GONE else View.VISIBLE
- holder.newestTv.visibility =
- if (data[position].newest.isEmpty()) View.GONE else View.VISIBLE
- holder.dateTv.visibility = if (data[position].date.isEmpty()) View.GONE else View.VISIBLE
-
- holder.headTv.text = data[position].head
- holder.nickTv.text = data[position].nick
- holder.newestTv.text = data[position].newest
- holder.dateTv.text = data[position].date
-
- holder.itemView.setOnClickListener {
- onItemClickListener.onItemClick(holder.itemView, position)
- }
- }
-
- class BaseHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
- val headTv: TextView = itemView.findViewById(R.id.headTv)
- val nickTv: TextView = itemView.findViewById(R.id.nickTv)
- val newestTv: TextView = itemView.findViewById(R.id.newestTv)
- val dateTv: TextView = itemView.findViewById(R.id.dateTv)
- }
-
- fun setOnItemClickListener(onItemClickListener: OnItemClickListener) {
- this.onItemClickListener = onItemClickListener
- }
-
- interface OnItemClickListener {
- fun onItemClick(view: View, position: Int)
- }
-
- }

- package com.example.fechat.fragment
-
- import android.content.Intent
- import android.os.Bundle
- import android.view.LayoutInflater
- import android.view.View
- import android.view.ViewGroup
- import androidx.fragment.app.Fragment
- import androidx.recyclerview.widget.LinearLayoutManager
- import androidx.recyclerview.widget.RecyclerView
- import com.example.fechat.R
- import com.example.fechat.activity.MessageActivity
- import com.example.fechat.base.BaseAdapter
- import com.example.fechat.bean.ChatBean
-
- class ChatFragment : Fragment() {
-
- private lateinit var recyclerView: RecyclerView
-
- override fun onCreateView(
- inflater: LayoutInflater, container: ViewGroup?,
- savedInstanceState: Bundle?
- ): View? {
- val view = inflater.inflate(R.layout.fragment_chat, container, false)
- recyclerView = view.findViewById(R.id.recyclerView)
- val data = ArrayList<ChatBean>()
- data.add(ChatBean("头像0", "用户0", "聊天记录0", "4月25日"))
- data.add(ChatBean("头像1", "用户1", "聊天记录1", "4月24日"))
- data.add(ChatBean("头像2", "用户2", "聊天记录2", "4月23日"))
- data.add(ChatBean("头像3", "用户3", "聊天记录3", "4月22日"))
- data.add(ChatBean("头像4", "用户4", "聊天记录4", "4月21日"))
- data.add(ChatBean("头像5", "用户5", "聊天记录5", "4月20日"))
- data.add(ChatBean("头像6", "用户6", "聊天记录6", "4月19日"))
- data.add(ChatBean("头像7", "用户7", "聊天记录7", "4月18日"))
- data.add(ChatBean("头像8", "用户8", "聊天记录8", "4月17日"))
- data.add(ChatBean("头像9", "用户9", "聊天记录9", "4月16日"))
- recyclerView.layoutManager = LinearLayoutManager(context)
- val baseAdapter = BaseAdapter(data)
- recyclerView.adapter = baseAdapter
- baseAdapter.setOnItemClickListener(object : BaseAdapter.OnItemClickListener {
- override fun onItemClick(view: View, position: Int) {
- val intent = Intent(context, MessageActivity::class.java)
- intent.putExtra("UserInfo", data[position].toString())
- startActivity(intent)
- }
- })
- return view
- }
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。