This commit is contained in:
itgaojian 2024-10-29 18:03:41 +08:00
parent 2bfa4e85f6
commit d68d5f254b
43 changed files with 963 additions and 146 deletions

View File

@ -29,7 +29,7 @@
<activity
android:name=".page.activity.ChatActivity"
android:exported="false"
android:windowSoftInputMode="adjustResize|stateVisible" />
android:windowSoftInputMode="adjustPan|stateHidden" />
<activity
android:name=".page.activity.SplashActivity"
android:exported="true"

View File

@ -5,22 +5,5 @@ data class AppTokenUser(
val loginUserType: String,
val posIds: List<Any>,
val roleIds: List<String>,
val user: User
val user: TokenUser
)
data class User(
val avatar: String,
val email: String,
val id: String,
val isAccountExpired: Int,
val isAccountLocked: Int,
val isDelete: Int,
val isEnable: Int,
val isPasswordExpired: Int,
val nickname: String,
val password: String,
val phone: String,
val tenantId: String,
val userId: String,
val username: String
)

View File

@ -8,7 +8,7 @@ import java.io.Serializable
@Entity(tableName = "db_category")
data class MsgCategoryBean(
@PrimaryKey(autoGenerate = true)
var id: Long,
var id: Long = 0,
@ColumnInfo(name = "avatar")
var avatar: String,
@ColumnInfo(name = "from")

View File

@ -1,10 +1,40 @@
package com.tenlionsoft.aimz_k.model
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
@Dao
interface MsgCategoryDao {
/**
* 获取全部信息
*
* @return
*/
@Query("SELECT * FROM db_category")
fun getAllCategory(): List<MsgCategoryBean>
/**
* 根据ID获取消息
*
* @param id
* @return
*/
@Query("SELECT * FROM db_category WHERE id =(:id) ")
fun getCategoryById(id: String): List<MsgCategoryBean>
/**
* 根据信息来源查询消息
*
* @param from
* @return
*/
@Query("SELECT * FROM db_category WHERE `from`=(:from)")
fun getCategoryByFrom(from: String?): List<MsgCategoryBean>
/**
* 查询与单人的聊天记录 SELECT id FROM db_msg WHERE `from`=(:form) AND `to`=(:to) OR `from`=(:to) AND `to`=(:form) ORDER BY timestamp DESC LIMIT (((:page)-1)*(:pageSize)),(:pageSize)
*/
@ -12,5 +42,41 @@ interface MsgCategoryDao {
fun getCategoryPage(
pageSize: Int,
page: Int
): List<MsgCategoryBean?>?
): MutableList<MsgCategoryBean>
/**
* 清空与某个人的聊天记录
*/
@Query("DELETE FROM db_category WHERE `from`=(:from) AND `to`=(:to) OR `from`=(:to) AND `to`=(:from)")
fun delChatHistory(from: String?, to: String?)
/**
* 添加消息多个
*
* @param beans
*/
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertAll(vararg beans: MsgCategoryBean)
/**
* 批量添加
*/
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertAll(beans: List<MsgCategoryBean>)
/**
* 添加消息-单个
*
* @param bean
*/
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertMsg(bean: MsgCategoryBean)
/**
* 清除全部聊天记录
*/
@Query("DELETE FROM db_category")
fun delAllMsg()
}

View File

@ -85,6 +85,7 @@ interface MsgDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertAll(beans: List<MsgBean>)
/**
* 添加消息-单个
*

View File

@ -0,0 +1,18 @@
package com.tenlionsoft.aimz_k.model
data class TokenUser(
val avatar: String,
val email: String,
val id: String,
val isAccountExpired: Int,
val isAccountLocked: Int,
val isDelete: Int,
val isEnable: Int,
val isPasswordExpired: Int,
val nickname: String,
val password: String,
val phone: String,
val tenantId: String,
val userId: String,
val username: String
)

View File

@ -1,10 +1,13 @@
package com.tenlionsoft.aimz_k.page.activity
import android.view.View
import android.view.WindowManager
import androidx.core.content.ContextCompat
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.ViewModelProvider
import com.tenlionsoft.aimz_k.R
import com.tenlionsoft.aimz_k.databinding.ActivityChatBinding
import com.tenlionsoft.aimz_k.viewmodel.ChatPageViewModel
import com.tenlionsoft.baselib.base.BaseActivity
/**
@ -12,7 +15,9 @@ import com.tenlionsoft.baselib.base.BaseActivity
*/
class ChatActivity : BaseActivity() {
private lateinit var mBinding: ActivityChatBinding
private val chatPageViewModel: ChatPageViewModel by lazy {
ViewModelProvider(this)[ChatPageViewModel::class.java]
}
override fun bindView() {
mBinding = DataBindingUtil.setContentView(this, R.layout.activity_chat);
@ -22,6 +27,10 @@ class ChatActivity : BaseActivity() {
mBinding.ivBack.setOnClickListener { finish(); }
mBinding.srlChats.setEnableRefresh(false)
mBinding.srlChats.setEnableLoadMore(false)
// SoftHideKeyBoardUtils.assistActivity(this);
mBinding.viewModel = chatPageViewModel
mBinding.lifecycleOwner = this
chatPageViewModel.showSendBtn.observe(this) {
mBinding.ivSend.visibility = if (it) View.GONE else View.VISIBLE
}
}
}

View File

@ -2,12 +2,12 @@ package com.tenlionsoft.aimz_k.page.activity
import android.content.Intent
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.lifecycleScope
import com.tenlionsoft.aimz_k.R
import com.tenlionsoft.aimz_k.databinding.ActivitySplashBinding
import com.tenlionsoft.aimz_k.model.DbManager
import com.tenlionsoft.baselib.base.BaseActivity
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.util.Timer
@ -22,18 +22,19 @@ class SplashActivity : BaseActivity() {
override fun bindView() {
mBinding = DataBindingUtil.setContentView(this, R.layout.activity_splash)
GlobalScope.launch(Dispatchers.IO) {
val msgDao = DbManager.db.msgDao()
val cDao = DbManager.db.categoryDao()
withContext(Dispatchers.Main) {
Timer().schedule(object : TimerTask() {
override fun run() {
startActivity(Intent(this@SplashActivity, LoginActivity::class.java));
finish();
}
}, 500)
mBinding.lifecycleOwner = this
lifecycleScope.launch {
withContext(Dispatchers.IO) {
val msgDao = DbManager.db.msgDao()
val cDao = DbManager.db.categoryDao()
}
Timer().schedule(object : TimerTask() {
override fun run() {
startActivity(Intent(this@SplashActivity, LoginActivity::class.java));
finish();
}
}, 500)
}
}
}

View File

@ -2,19 +2,25 @@ package com.tenlionsoft.aimz_k.page.fragments
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.viewModels
import com.tenlionsoft.aimz_k.R
import com.tenlionsoft.aimz_k.databinding.FragmentMsgBinding
import com.tenlionsoft.aimz_k.model.MsgCategoryBean
import com.tenlionsoft.aimz_k.page.activity.ChatActivity
import com.tenlionsoft.aimz_k.viewmodel.MsgViewModel
import com.tenlionsoft.baselib.widget.LoadingDialog
class MsgFragment : Fragment() {
class MsgFragment : Fragment(), MsgViewModel.OnItemClickListener {
private lateinit var mMsgBinding: FragmentMsgBinding
private var mActivity: FragmentActivity? = null
private var mLoading: LoadingDialog? = null;
companion object {
fun newInstance() = MsgFragment()
@ -37,9 +43,37 @@ class MsgFragment : Fragment() {
container,
false
);
mActivity = activity
mMsgBinding.llSearchLayout.llSearchLayout.setOnClickListener {
startActivity(Intent(this@MsgFragment.context, ChatActivity::class.java))
}
mMsgBinding.msgViewModel = viewModel
mMsgBinding.lifecycleOwner = this
viewModel.onItemClickListener = this//条目点击
initView();
return mMsgBinding.root;
}
/**
* 初始化页面
*/
private fun initView() {
mMsgBinding.srlMsgs.setOnLoadMoreListener { viewModel.loadMore() }
mMsgBinding.srlMsgs.setOnRefreshListener { viewModel.refresh() }
viewModel.isHasMore.observe(viewLifecycleOwner) {
mMsgBinding.srlMsgs.setNoMoreData(it)
mMsgBinding.srlMsgs.finishRefresh()
mMsgBinding.srlMsgs.finishLoadMore()
}
}
/**
* 条目点击
*/
override fun onItemClick(msgCategoryBean: MsgCategoryBean) {
Log.e("MsgFragment", "onItemClick: ${msgCategoryBean}")
startActivity(Intent(mActivity, ChatActivity::class.java))
}
}

View File

@ -0,0 +1,24 @@
package com.tenlionsoft.aimz_k.viewmodel
import androidx.lifecycle.MutableLiveData
import com.tenlionsoft.baselib.base.BaseViewModel
class ChatPageViewModel : BaseViewModel() {
var txtMsg: String = ""
var showSendBtn = MutableLiveData<Boolean>()
fun onTxtChange(s: CharSequence, start: Int, before: Int, count: Int) {
this.txtMsg = s.toString()
if (s.isEmpty()) {
showSendBtn.value = true
} else {
showSendBtn.value = false
}
}
/**
* 发送文本信息
*/
fun sendTxtMsg() {
}
}

View File

@ -20,8 +20,8 @@ import okhttp3.RequestBody.Companion.toRequestBody
class LoginPageViewModel : BaseViewModel() {
var userName: String = ""
var userPwd: String = ""
var userName: String = "admin"
var userPwd: String = "admin"
val isLoginSuccess = MutableLiveData<Boolean>()
private val gson = Gson()
private val userApi = RetrofitClient.getInstance(App.context)

View File

@ -1,7 +1,80 @@
package com.tenlionsoft.aimz_k.viewmodel
import android.util.Log
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.tenlionsoft.aimz_k.model.DbManager
import com.tenlionsoft.aimz_k.model.MsgCategoryBean
import com.tenlionsoft.aimz_k.widget.CategoryAdapter
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
class MsgViewModel : ViewModel() {
// TODO: Implement the ViewModel
private val _pwdList = MutableLiveData<List<MsgCategoryBean>>()
var adapter: CategoryAdapter = CategoryAdapter(_pwdList.value ?: emptyList(),this)
var onItemClickListener: OnItemClickListener? = null
private var mCurrentPage: Int = 1
var isHasMore: MutableLiveData<Boolean> = MutableLiveData<Boolean>().apply {
value = false
}
init {
Log.e("MsgViewModel", "Init:${_pwdList.value} ")
getPwdList(true)
}
/**
* 获取列表数据
*/
private fun getPwdList(isFirst: Boolean) {
viewModelScope.launch {
if (isFirst) {
_pwdList.value = emptyList()
mCurrentPage = 1
} else {
++mCurrentPage
}
val list = getCategoryListByPage(mCurrentPage)
if (list.isNotEmpty()) {
isHasMore.value = false
} else {
isHasMore.value = true
}
val updateData: List<MsgCategoryBean> = _pwdList.value!! + list
_pwdList.value = updateData
Log.e("MsgViewModel", "getPwdList: ${_pwdList.value}")
adapter.setData(_pwdList.value!!)
}
}
private suspend fun getCategoryListByPage(page: Int): List<MsgCategoryBean> {
var tempList: List<MsgCategoryBean>
withContext(Dispatchers.IO) {
val cDao = DbManager.db.categoryDao()
tempList = cDao.getCategoryPage(10, page)
}
return tempList
}
/**
* 加载更多
*/
fun loadMore() {
getPwdList(false)
}
/**
* 刷新
*/
fun refresh() {
getPwdList(true)
}
interface OnItemClickListener {
fun onItemClick(msgCategoryBean: MsgCategoryBean)
}
}

View File

@ -0,0 +1,51 @@
package com.tenlionsoft.aimz_k.widget
import android.widget.ImageView
import androidx.databinding.BindingAdapter
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.Adapter
import com.bumptech.glide.Glide
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.request.RequestOptions
import com.tenlionsoft.aimz_k.R
object BindingUtils {
@BindingAdapter("app:setAdapter")
@JvmStatic
fun bindAdapterToRecyclerView(recyclerView: RecyclerView, adapter: Adapter<*>) {
// adapter.setHasStableIds(true)
// recyclerView.setHasFixedSize(true)
recyclerView.layoutManager = LinearLayoutManager(recyclerView.context)
recyclerView.adapter = adapter
}
@BindingAdapter("app:imageUrl")
@JvmStatic
fun bindImgUrl(imageView: ImageView, url: String?) {
if (url.isNullOrEmpty()) {
imageView.setImageResource(R.drawable.app_logo_small)
} else {
val requestOptions = RequestOptions()
.error(R.drawable.app_logo_small)
.placeholder(R.drawable.app_logo_small)
.skipMemoryCache(false)
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
.centerInside()
Glide.with(imageView.context)
.load(url)
.apply(requestOptions)
.into(imageView)
}
}
@BindingAdapter("imgResource")
@JvmStatic
fun bindImgUrl(imageView: ImageView, url: Int) {
imageView.setImageResource(url)
}
}

View File

@ -0,0 +1,43 @@
package com.tenlionsoft.aimz_k.widget
import android.annotation.SuppressLint
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.tenlionsoft.aimz_k.databinding.ItemCategoryBinding
import com.tenlionsoft.aimz_k.model.MsgCategoryBean
import com.tenlionsoft.aimz_k.viewmodel.MsgViewModel
class CategoryAdapter(
private var list: List<MsgCategoryBean>,
private val viewModel: MsgViewModel
) : RecyclerView.Adapter<CategoryAdapter.NewsViewHolder>() {
class NewsViewHolder(val binding: ItemCategoryBinding) : RecyclerView.ViewHolder(binding.root)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NewsViewHolder {
val inflater = LayoutInflater.from(parent.context)
val binding = ItemCategoryBinding.inflate(inflater, parent, false)
return NewsViewHolder(binding)
}
override fun getItemCount(): Int {
return list.size
}
@SuppressLint("NotifyDataSetChanged")
fun setData(list: List<MsgCategoryBean>) {
this.list = list
this.notifyDataSetChanged()
}
override fun onBindViewHolder(holder: NewsViewHolder, position: Int) {
holder.binding.pos = position
holder.binding.item = list[position]
holder.binding.root.setOnClickListener {
viewModel.onItemClickListener?.onItemClick(list[position])
}
holder.binding.executePendingBindings()
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@color/red" />
</shape>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/chat_page_bg" />
<size
android:width=".5dp"
android:height=".5dp" />
</shape>

View File

@ -4,6 +4,9 @@
<data>
<variable
name="viewModel"
type="com.tenlionsoft.aimz_k.viewmodel.ChatPageViewModel" />
</data>
<RelativeLayout
@ -14,6 +17,7 @@
android:orientation="vertical"
tools:context=".page.activity.ChatActivity">
<LinearLayout
android:id="@+id/ll_title"
android:layout_width="match_parent"
@ -30,8 +34,8 @@
<ImageView
android:id="@+id/iv_back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_width="28dp"
android:layout_height="28dp"
android:layout_centerVertical="true"
android:src="@drawable/ic_back_left" />
@ -53,44 +57,98 @@
android:background="#CBCBCB" />
</LinearLayout>
<com.scwang.smart.refresh.layout.SmartRefreshLayout
android:id="@+id/srl_chats"
<LinearLayout
android:id="@+id/rlContent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/ll_title"
android:layout_marginTop="5dp"
android:layout_marginBottom="80dp">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rlv_chats"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</com.scwang.smart.refresh.layout.SmartRefreshLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:orientation="vertical">
<include
android:id="@+id/ll_input_layout"
layout="@layout/layout_chat_input" />
<View
<com.scwang.smart.refresh.layout.SmartRefreshLayout
android:id="@+id/srl_chats"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#CBCBCB" />
android:layout_height="0dp"
android:layout_weight="1">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rlv_shortcut"
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rlv_chats"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</com.scwang.smart.refresh.layout.SmartRefreshLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="300dp"
android:background="@color/input_layout_bg"
android:visibility="gone">
android:layout_height="wrap_content"
android:orientation="vertical">
</androidx.recyclerview.widget.RecyclerView>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/input_layout_bg"
android:gravity="center_vertical"
android:minHeight="50dp"
android:orientation="horizontal"
android:paddingLeft="10dp"
android:paddingTop="5dp"
android:paddingRight="10dp"
android:paddingBottom="5dp">
<ImageView
android:id="@+id/iv_msg"
android:layout_width="28dp"
android:layout_height="28dp"
android:src="@drawable/ic_msg_icon" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_weight="1"
android:gravity="center_vertical"
android:orientation="horizontal">
<EditText
android:id="@+id/et_msg"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginRight="5dp"
android:layout_weight="1"
android:background="@drawable/shp_white_5_radius"
android:gravity="center_vertical"
android:hint="请输入内容"
android:onTextChanged="@{viewModel::onTxtChange}"
android:padding="10dp"
android:text="@{viewModel.txtMsg}"
android:textSize="14sp" />
<ImageView
android:id="@+id/iv_send"
android:layout_width="35dp"
android:layout_height="30dp"
android:onClick="@{()->viewModel.sendTxtMsg()}"
android:scaleType="fitXY"
android:src="@drawable/ic_send_msg"
android:visibility="gone" />
</LinearLayout>
<ImageView
android:id="@+id/iv_emoji"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginEnd="8dp"
android:scaleType="fitXY"
android:src="@drawable/ic_emoji" />
<ImageView
android:id="@+id/iv_add"
android:layout_width="30dp"
android:layout_height="30dp"
android:scaleType="fitXY"
android:src="@drawable/ic_msg_add" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</RelativeLayout>
</layout>

View File

@ -1,8 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<layout 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">
<data>
<variable
name="msgViewModel"
type="com.tenlionsoft.aimz_k.viewmodel.MsgViewModel" />
</data>
<LinearLayout
@ -22,7 +27,9 @@
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rlv_msgs"
android:layout_width="match_parent"
android:layout_height="match_parent" />
app:setAdapter="@{msgViewModel.adapter}"
android:layout_height="match_parent"
tools:listitem="@layout/item_category" />
</com.scwang.smart.refresh.layout.SmartRefreshLayout>
</LinearLayout>

View File

@ -0,0 +1,107 @@
<?xml version="1.0" encoding="utf-8"?>
<layout 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">
<data>
<variable
name="pos"
type="Integer" />
<import type="android.view.View" />
<variable
name="item"
type="com.tenlionsoft.aimz_k.model.MsgCategoryBean" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:orientation="horizontal">
<RelativeLayout
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_margin="10dp">
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_centerInParent="true"
android:scaleType="fitXY"
app:imageUrl="@{item.avatar}"
tools:src="@drawable/app_logo_small" />
<ImageView
android:layout_width="10dp"
android:layout_height="10dp"
android:layout_alignParentRight="true"
android:src="@drawable/shp_circle_red"
android:visibility="@{item.read?View.VISIBLE:View.GONE}" />
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:layout_marginBottom="15dp"
android:orientation="horizontal"
android:paddingRight="15dp">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
android:paddingLeft="10dp"
android:paddingRight="10dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
android:text="@{item.fromName}"
android:textColor="#1D1D1D"
android:textSize="18sp"
tools:text="测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:ellipsize="end"
android:maxLines="1"
android:text="@{item.body}"
android:textColor="#B7B7B7"
tools:text="测试聊天内容" />
</LinearLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{String.valueOf(item.id)}"
android:textColor="#CACACA"
android:textSize="14sp"
tools:text="16:00" />
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginStart="10dp"
android:layout_marginEnd="5dp"
android:background="#E6E6E6" />
</LinearLayout>
</LinearLayout>
</layout>

View File

@ -1,52 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_alignParentBottom="true"
android:background="@color/input_layout_bg"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingLeft="10dp"
android:paddingTop="5dp"
android:paddingRight="10dp"
android:paddingBottom="5dp">
<ImageView
android:id="@+id/iv_msg"
android:layout_width="28dp"
android:layout_height="28dp"
android:src="@drawable/ic_msg_icon" />
<EditText
android:id="@+id/et_msg"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_weight="1"
android:background="@drawable/shp_white_5_radius"
android:gravity="center_vertical"
android:hint="请输入内容"
android:paddingLeft="5dp"
android:paddingTop="5dp"
android:paddingBottom="5dp"
android:textSize="14sp" />
<ImageView
android:id="@+id/iv_emoji"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginRight="8dp"
android:scaleType="fitXY"
android:src="@drawable/ic_emoji" />
<ImageView
android:id="@+id/iv_add"
android:layout_width="30dp"
android:layout_height="30dp"
android:scaleType="fitXY"
android:src="@drawable/ic_msg_add" />
</LinearLayout>
</layout>

View File

@ -0,0 +1,45 @@
package com.tenlionsoft.baselib.base
import androidx.databinding.ObservableList
import androidx.recyclerview.widget.RecyclerView
class DynamicChangeCallBack<T>(private val adapter: RecyclerView.Adapter<*>) :
ObservableList.OnListChangedCallback<ObservableList<T>>() {
override fun onChanged(sender: ObservableList<T>?) {
adapter.notifyDataSetChanged()
}
override fun onItemRangeChanged(
sender: ObservableList<T>?,
positionStart: Int,
itemCount: Int
) {
adapter.notifyItemRangeChanged(positionStart, itemCount)
}
override fun onItemRangeInserted(
sender: ObservableList<T>?,
positionStart: Int,
itemCount: Int
) {
adapter.notifyItemRangeInserted(positionStart, itemCount)
}
override fun onItemRangeMoved(
sender: ObservableList<T>?,
fromPosition: Int,
toPosition: Int,
itemCount: Int
) {
adapter.notifyItemRangeRemoved(fromPosition, itemCount)
adapter.notifyItemRangeInserted(toPosition, itemCount)
}
override fun onItemRangeRemoved(
sender: ObservableList<T>?,
positionStart: Int,
itemCount: Int
) {
adapter.notifyItemRangeRemoved(positionStart, itemCount)
}
}

View File

@ -1,5 +1,6 @@
package com.tenlionsoft.baselib.widget
import android.app.Activity
import android.app.Dialog
import android.content.Context
import android.content.DialogInterface
@ -33,7 +34,7 @@ class LoadingDialog : Dialog {
window.setBackgroundDrawable(ColorDrawable())
}
class Builder(private val context: Context) {
class Builder(private val context: Activity) {
//提示信息
private var message: String? = null

View File

@ -1,12 +1,10 @@
package com.tenlionsoft.baselib.widget.chat
import android.annotation.SuppressLint
import android.annotation.TargetApi
import android.app.Activity
import android.content.Context
import android.content.SharedPreferences
import android.graphics.Rect
import android.os.Build
import android.text.Editable
import android.text.TextWatcher
import android.util.DisplayMetrics
@ -26,10 +24,10 @@ class ChatUiHelper {
private var mActivity: Activity? = null
private var mContentLayout: LinearLayout? = null //整体界面布局
private var mBottomLayout: RelativeLayout? = null //底部布局
private var mEmojiLayout: LinearLayout? = null //表情布局
// private LinearLayout mEmojiLayout;//表情布局
// private LinearLayout mAddLayout;//添加布局
private var mSendBtn: Button? = null //发送按钮
private var mIvSend: ImageView? = null//发送按钮
private var mAddButton: View? = null //加号按钮
private var mAudioButton: Button? = null //录音按钮
private var mAudioIv: ImageView? = null //录音图片
@ -46,6 +44,11 @@ class ChatUiHelper {
return this
}
fun bindSendButton(iv: ImageView): ChatUiHelper {
this.mIvSend = iv
return this
}
@SuppressLint("ClickableViewAccessibility")
fun bindEditText(editText: EditText): ChatUiHelper {
mEditText = editText
@ -70,11 +73,11 @@ class ChatUiHelper {
override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {
if (mEditText!!.text.toString().trim { it <= ' ' }.isNotEmpty()) {
mSendBtn!!.visibility = View.VISIBLE
mAddButton!!.visibility = View.GONE
mIvSend?.visibility = View.VISIBLE
// TODO mAddButton!!.visibility = View.GONE
} else {
mSendBtn!!.visibility = View.GONE
mAddButton!!.visibility = View.VISIBLE
mIvSend?.visibility = View.GONE
// TODO mAddButton!!.visibility = View.VISIBLE
}
}
@ -93,7 +96,7 @@ class ChatUiHelper {
//绑定表情布局
fun bindEmojiLayout(emojiLayout: LinearLayout?): ChatUiHelper {
// mEmojiLayout = emojiLayout;
mEmojiLayout = emojiLayout;
return this
}
@ -103,12 +106,6 @@ class ChatUiHelper {
return this
}
//绑定发送按钮
fun bindttToSendButton(sendbtn: Button): ChatUiHelper {
mSendBtn = sendbtn
return this
}
//绑定语音按钮点击事件
// fun bindAudioBtn(audioBtn: RecordButton): ChatUiHelper {
@ -279,12 +276,12 @@ class ChatUiHelper {
private fun showEmotionLayout() {
// mEmojiLayout.setVisibility(View.VISIBLE);
mEmojiLayout?.setVisibility(View.VISIBLE);
// mIvEmoji.setImageResource(R.drawable.ic_keyboard);
}
private fun hideEmotionLayout() {
// mEmojiLayout.setVisibility(View.GONE);
mEmojiLayout?.setVisibility(View.GONE);
// mIvEmoji.setImageResource(R.drawable.ic_emoji);
}
@ -353,7 +350,7 @@ class ChatUiHelper {
/**
* 释放被锁定的内容高度
*/
fun unlockContentHeightDelayed() {
private fun unlockContentHeightDelayed() {
mEditText!!.postDelayed({
(mContentLayout!!.layoutParams as LinearLayout.LayoutParams).weight =
1.0f
@ -420,8 +417,6 @@ class ChatUiHelper {
const val SHARE_PREFERENCE_TAG: String = "soft_input_height"
fun with(activity: Activity): ChatUiHelper {
val mChatUiHelper = ChatUiHelper()
// AndroidBug5497Workaround.assistActivity(activity);
mChatUiHelper.mActivity = activity
mChatUiHelper.mInputManager =
activity.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager

View File

@ -0,0 +1,94 @@
package com.tenlionsoft.baselib.widget.chat
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.RectF
import android.os.Handler
import android.os.Looper
import android.os.Message
import android.util.AttributeSet
import android.widget.LinearLayout
import com.tenlionsoft.baselib.R
import com.tenlionsoft.baselib.utils.DensityUtils
class IndicatorView : LinearLayout {
private var indicatorColor = Color.rgb(0, 0, 0)
private var indicatorColorSelected = Color.rgb(0, 0, 0)
private var indicatorWidth = 0
private var gravity = 0
private var indicatorCount = 0
private var currentIndicator = 0
private val handler: Handler = object : Handler(Looper.getMainLooper()) {
override fun handleMessage(msg: Message) {
if (msg.what == 0x12) {
invalidate()
}
}
}
constructor(context: Context) : super(context) {
}
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
if (attrs != null) {
val typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.IndicatorView)
indicatorColor =
typedArray.getColor(R.styleable.IndicatorView_indicatorColor, Color.rgb(0, 0, 0))
indicatorColorSelected = typedArray.getColor(
R.styleable.IndicatorView_indicatorColorSelected,
Color.rgb(0, 0, 0)
)
indicatorWidth = DensityUtils.dp2px(
context,
typedArray.getFloat(R.styleable.IndicatorView_indicatorWidth, 0F)
)
gravity = typedArray.getInt(R.styleable.IndicatorView_gravity, 0)
typedArray.recycle()
}
}
override fun onDraw(canvas: Canvas) {
val viewWidth = width
val viewHeight = height
val totalWidth = indicatorWidth * (2 * indicatorCount - 1)
val paint = Paint()
paint.isAntiAlias = true
if (indicatorCount > 0) {
for (i in 0 until indicatorCount) {
if (i == currentIndicator) {
paint.color = indicatorColorSelected
} else {
paint.color = indicatorColor
}
var left = (viewWidth - totalWidth) / 2 + (i * 2 * indicatorWidth)
when (gravity) {
0 -> left = (viewWidth - totalWidth) / 2 + (i * 2 * indicatorWidth)
1 -> left = i * 2 * indicatorWidth
2 -> left = viewWidth - totalWidth + (i * 2 * indicatorWidth)
}
val top = (viewHeight - indicatorWidth) / 2
val right = left + indicatorWidth
val bottom = top + indicatorWidth
val rectF = RectF(left.toFloat(), top.toFloat(), right.toFloat(), bottom.toFloat())
canvas.drawOval(rectF, paint)
}
}
}
fun setIndicatorCount(indicatorCount: Int) {
this.indicatorCount = indicatorCount
}
fun setCurrentIndicator(currentIndicator: Int) {
this.currentIndicator = currentIndicator
handler.sendEmptyMessage(0x12)
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 481 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 476 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 650 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 710 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 906 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 901 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 562 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 546 B

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/ic_ctype_file_pre" android:state_pressed="true"/>
<item android:drawable="@drawable/ic_ctype_file" android:state_pressed="false"/>
<item android:drawable="@drawable/ic_ctype_file"/>
</selector>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/ic_ctype_image_pre" android:state_pressed="true"/>
<item android:drawable="@drawable/ic_ctype_image" android:state_pressed="false"/>
<item android:drawable="@drawable/ic_ctype_image"/>
</selector>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/ic_ctype_loaction_pre" android:state_pressed="true"/>
<item android:drawable="@drawable/ic_ctype_location" android:state_pressed="false"/>
<item android:drawable="@drawable/ic_ctype_location"/>
</selector>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/ic_ctype_video_pre" android:state_pressed="true"/>
<item android:drawable="@drawable/ic_ctype_video" android:state_pressed="false"/>
<item android:drawable="@drawable/ic_ctype_video"/>
</selector>

View File

@ -2,6 +2,6 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="5dp" />
<solid android:color="#78FFFFFF" />
<solid android:color="#D0A4A4A4" />
</shape>

View File

@ -0,0 +1,184 @@
<?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:orientation="vertical"
android:paddingBottom="100dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<RelativeLayout
android:id="@+id/rlPhoto"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1">
<ImageView
android:id="@+id/ivPhoto"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_centerHorizontal="true"
android:layout_marginTop="30dp"
android:background="@drawable/selector_ctype_image" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/ivPhoto"
android:layout_centerHorizontal="true"
android:layout_marginTop="15px"
android:text="相片"
android:textSize="12sp" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/rlVideo"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1">
<ImageView
android:id="@+id/ivVideo"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_centerHorizontal="true"
android:layout_marginTop="30dp"
android:background="@drawable/selector_ctype_video" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/ivVideo"
android:layout_centerHorizontal="true"
android:layout_marginTop="15px"
android:text="视频"
android:textSize="12sp" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/rlVideoCall"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:visibility="invisible">
<ImageView
android:id="@+id/ivVideoCall"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_centerHorizontal="true"
android:layout_marginTop="30dp"
android:background="@drawable/selector_ctype_file" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/ivVideoCall"
android:layout_centerHorizontal="true"
android:layout_marginTop="15px"
android:text="视频通话"
android:textSize="12sp" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/rlAudioCall"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:visibility="invisible">
<ImageView
android:id="@+id/ivAudioCall"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_centerHorizontal="true"
android:layout_marginTop="30dp"
android:background="@drawable/selector_ctype_file" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/ivAudioCall"
android:layout_centerHorizontal="true"
android:layout_marginTop="15px"
android:text="音频通话"
android:textSize="12sp" />
</RelativeLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:orientation="horizontal"
android:visibility="gone">
<RelativeLayout
android:id="@+id/rlFile"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1">
<ImageView
android:id="@+id/ivFile"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_centerHorizontal="true"
android:layout_marginTop="30dp"
android:background="@drawable/selector_ctype_file" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/ivFile"
android:layout_centerHorizontal="true"
android:layout_marginTop="15px"
android:text="文件"
android:textSize="12sp" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/rlLocation"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1">
<ImageView
android:id="@+id/ivLocation"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_centerHorizontal="true"
android:layout_marginTop="30dp"
android:background="@drawable/selector_ctype_location" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/ivLocation"
android:layout_centerHorizontal="true"
android:layout_marginTop="15px"
android:text="位置"
android:textSize="12sp" />
</RelativeLayout>
<RelativeLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1">
</RelativeLayout>
<RelativeLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1">
</RelativeLayout>
</LinearLayout>
</LinearLayout>

View File

@ -0,0 +1,38 @@
<?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"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:id="@+id/home_emoji"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.tenlionsoft.baselib.widget.chat.WrapContentHeightViewPager
android:id="@+id/vp_emoji"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="30dp" />
<com.tenlionsoft.baselib.widget.chat.IndicatorView
android:id="@+id/ind_emoji"
android:layout_width="match_parent"
android:layout_height="20dp"
android:layout_gravity="bottom"
android:layout_marginLeft="16dp"
android:layout_marginTop="30dp"
android:layout_marginRight="16dp"
android:background="#f3f3f3"
app:gravity="0"
app:indicatorColor="#668b8989"
app:indicatorColorSelected="#ffffff"
app:indicatorWidth="6" />
</LinearLayout>
</LinearLayout>

View File

@ -133,7 +133,7 @@
<declare-styleable name="IndicatorView">
<attr name="indicatorColor" format="color" />
<attr name="indicatorColorSelected" format="color" />
<attr name="indicatorWidth" format="integer" />
<attr name="indicatorWidth" format="float" />
<attr name="gravity" format="integer" />
</declare-styleable>
<declare-styleable name="LimitEmojiEditText">

View File

@ -6,5 +6,6 @@
<color name="tr">#00FFFFFF</color>
<color name="tr_bg">#54000000</color>
<color name="chat_page_bg">#EDEDED</color>
<color name="red">#E75D58</color>
<color name="black">#000000</color>
</resources>