Kotlin高仿微信-项目实践58篇详细讲解了各个功能点,包括:注册、登录、主页、单聊(文本、表情、语音、图片、小视频、视频通话、语音通话、红包、转账)、群聊、个人信息、朋友圈、支付服务、扫一扫、搜索好友、添加好友、开通VIP等众多功能。
Kotlin高仿微信-项目实践58篇,点击查看详情
效果图:

实现代码:
我的转账页面
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="right">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/transfer_me_root_layout"
android:layout_width="240dp"
android:layout_height="90dp"
android:background="@drawable/wc_redpacket_right_normal">
<TextView
android:id="@+id/transfer_me_balance"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:text="0.01"
android:textColor="#ffffff"
android:textSize="16sp"
android:textStyle="bold"
android:layout_marginTop="2dp"
android:maxLines="1"
android:ellipsize="end"
android:singleLine="true"
app:layout_constraintTop_toTopOf="@+id/transfer_me_icon"
app:layout_constraintStart_toEndOf="@+id/transfer_me_icon"/>
<TextView
android:id="@+id/transfer_me_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:text="你发起了一笔转账"
android:textColor="#ffffff"
android:textSize="12sp"
app:layout_constraintTop_toBottomOf="@+id/transfer_me_balance"
app:layout_constraintStart_toEndOf="@+id/transfer_me_icon"/>
<TextView
android:layout_width="match_parent"
android:layout_height="0.2dp"
android:layout_marginLeft="20dp"
android:layout_marginRight="10dp"
android:background="#ffffff"
app:layout_constraintBottom_toTopOf="@+id/redpacket_tip"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/transfer_me_icon" />
<TextView
android:id="@+id/redpacket_tip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginBottom="6dp"
android:text="@string/wc_chat_transfer_tip"
android:textColor="#d9d6c3"
android:textSize="10sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/transfer_me_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="12dp"
android:src="@drawable/wc_chat_transfer_icon"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</RelativeLayout>
好友的转账页面:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/transfer_other_root_layout"
android:layout_width="240dp"
android:layout_height="90dp"
android:background="@drawable/wc_redpacket_left_normal">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/other_transfer_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="18dp"
android:layout_marginTop="10dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:background="@drawable/wc_chat_transfer_icon"/>
<TextView
android:id="@+id/transfer_other_balance"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0.01"
android:textSize="16sp"
android:textColor="#ffffff"
android:textStyle="bold"
android:layout_marginTop="2dp"
android:layout_marginLeft="10dp"
app:layout_constraintStart_toEndOf="@+id/other_transfer_icon"
app:layout_constraintTop_toTopOf="@+id/other_transfer_icon"/>
<TextView
android:id="@+id/transfer_other_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="请收款"
android:textSize="12sp"
android:textColor="#ffffff"
android:textStyle="bold"
android:layout_marginLeft="10dp"
app:layout_constraintStart_toEndOf="@+id/other_transfer_icon"
app:layout_constraintTop_toBottomOf="@+id/transfer_other_balance"/>
<TextView
android:layout_width="match_parent"
android:layout_height="0.2dp"
android:background="#ffffff"
android:layout_marginLeft="20dp"
android:layout_marginRight="10dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/other_transfer_icon"
app:layout_constraintBottom_toTopOf="@+id/transfer_tip"/>
<TextView
android:id="@+id/transfer_tip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginBottom="6dp"
android:layout_marginLeft="20dp"
android:text="@string/wc_chat_transfer_tip"
android:textSize="10sp"
android:textColor="#d9d6c3"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
package com.wn.wechatclientdemo.fragment.me.payment
import android.os.Bundle
import android.view.View
import androidx.fragment.app.viewModels
import androidx.navigation.NavController
import androidx.navigation.fragment.findNavController
import com.wn.wechatclientdemo.R
import com.wn.wechatclientdemo.databinding.WcTransferMainBinding
import com.wn.wechatclientdemo.fragment.base.BaseDataBindingFragment
import com.wn.wechatclientdemo.utils.*
import com.wn.wechatclientdemo.view.BaseDialogUtils
import com.wn.wechatclientdemo.viewmodel.ChatViewModel
import com.wn.wechatclientdemo.viewmodel.UserViewModel
import kotlinx.android.synthetic.main.wc_transfer_main.*
/**
* Author : wangning
* Email : maoning20080809@163.com
* Date : 2022/5/22 16:43
* Description : 查看转账详情
*/
class TransferDetailsFragment : BaseDataBindingFragment<WcTransferMainBinding>(){
override fun getLayoutRes() = R.layout.wc_transfer_main
private val userViewModel: UserViewModel by viewModels()
private val chatViewModel: ChatViewModel by viewModels()
private var navController : NavController? = null
private var balance: Float = 0.0f
private var messageId = ""
private var toUser = ""
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
super.builder().setTitleContent(R.string.wc_base_top_transfer)
arguments?.let {
toUser = it.get(CommonUtils.QRCommon.TO_USER) as String
messageId = it.get(CommonUtils.Chat.MESSAGE_ID) as String
var balanceStr = it.get(CommonUtils.QRCommon.TRANSFER_BALANCE) as String
TagUtils.d("转账:${toUser}, ${messageId}, ${balanceStr}")
balance = balanceStr.toFloat()
trans_main_balance.text = CommonUtils.Base.getFormatBalanceUnit(balance)
}
navController = findNavController()
var account = DataStoreUtils.getAccount()
var userBean = userViewModel.getUserLocalAsync(toUser)
var chatBean = chatViewModel.getChatByMessageIdAsync(messageId)
trans_main_time.text = CommonUtils.Date.getCurrentDate(chatBean.addTime)
if(account.equals(toUser)){
if(chatBean.isClick == 1){
//已经领取
trans_main_icon.setImageResource(R.drawable.wc_transfer_time_complete)
trans_main_name.text = BaseUtils.getString(R.string.wc_transfer_receive_other)
trans_main_receive.visibility = View.GONE
} else {
//待收款
trans_main_name.text = BaseUtils.getString(R.string.wc_transfer_waitfor_other)
trans_main_receive.visibility = View.VISIBLE
}
} else {
trans_main_name.text = BaseUtils.getString(R.string.wc_transfer_name_me, userBean.nickName)
trans_main_receive.visibility = View.GONE
}
userViewModel.balanceLiveData.observe(viewLifecycleOwner){
dismissLoadingDialog()
if(it >0){
chatViewModel.updateChatClickByMessageIdLocal(1, messageId)
navController?.popBackStack()
} else {
TagUtils.d("收款失败!")
}
}
trans_main_receive.setOnClickListener {
if(balance < 0){
ToastUtils.makeText("转账金额不能小于0")
} else {
showLoadingDialog()
userViewModel.updateBalanceServer(toUser, CommonUtils.User.OPERATOR_PLUS, balance)
}
}
}
override fun onDestroy() {
super.onDestroy()
}
private var loadingUtils : BaseDialogUtils? = null
//显示加载对话框
private fun showLoadingDialog(){
loadingUtils = BaseDialogUtils(requireActivity())
loadingUtils!!.builder()
.hideCancel()
.hideConfirm()
.setCancelable(true)
.setOnLoadingClick(object : BaseDialogUtils.OnLoadingClick{
override fun onClickCancel() {
ToastUtils.makeText(requireActivity(), "对话框取消按钮")
}
override fun onClickConfirm() {
ToastUtils.makeText(requireActivity(), "对话框确定按钮")
}
})
loadingUtils?.show()
}
//隐藏加载对话框
private fun dismissLoadingDialog(){
loadingUtils?.dismiss()
}
}
/**
* Author : wangning
* Email : maoning20080809@163.com
* Date : 2022/5/22 16:43
* Description : 转账
*/
class PaymentTransferFragment : BaseDataBindingFragment<WcPaymentTransferBinding>(), MyDispatchTouchEventListener {
override fun getLayoutRes() = R.layout.wc_payment_transfer
private val userViewModel : UserViewModel by viewModels()
private var navController : NavController? = null
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
super.builder().setTitleContent("")
var toUser = arguments?.get(CommonUtils.QRCommon.TO_USER) as String
BaseUtils.showAvatarRounded(toUser, transfer_icon, transfer_name, BaseUtils.getDimension(R.dimen.distance_10))
DispatchTouchEventUtils.registerDispatchTouchListener(this)
navController = findNavController()
transfer_balance.showSoftInputOnFocus = false
num_keyboard_view.initEditText(transfer_balance)
num_keyboard_view.setValue(R.string.wc_transfer_txt)
transfer_balance.setOnClickListener {
num_keyboard_view.visibility = View.VISIBLE
}
num_keyboard_item_recharge.setOnClickListener {
TagUtils.d("转账金额:${transfer_balance.text}")
var result = transfer_balance.text.toString()
if(TextUtils.isEmpty(result)){
ToastUtils.makeText(requireActivity(), "请输入金额")
return@setOnClickListener
}
//减掉服务器金额
userViewModel.updateBalanceServer(toUser, CommonUtils.User.OPERATOR_MINUS, transfer_balance.text.toString().toFloat())
navController?.previousBackStackEntry?.savedStateHandle?.set(CommonUtils.QRCommon.TRANSFER_BALANCE, transfer_balance.text.toString().toFloat())
//弹出的id为fragment,不能为action
navController?.popBackStack()
}
}
override fun onDestroy() {
super.onDestroy()
DispatchTouchEventUtils.unregisterDispatchTouchListener(this)
}
override fun dispatchTouchEvent(ev: MotionEvent) {
if (ev.action == MotionEvent.ACTION_DOWN) {
if (SoftInputUtils.isInput(transfer_balance, ev)) {
num_keyboard_view?.visibility = View.GONE
}
}
}
override fun onResume() {
super.onResume()
transfer_balance.isFocusableInTouchMode = true
transfer_balance.requestFocus()
transfer_balance.setOnKeyListener { view, i, keyEvent ->
if (i == KeyEvent.KEYCODE_BACK && keyEvent.getAction() == KeyEvent.ACTION_DOWN) {
if(num_keyboard_view.visibility == View.VISIBLE){
hideNumKeyboardView()
true
} else {
false
}
} else {
false
}
}
}
private fun hideNumKeyboardView(){
num_keyboard_view.visibility = View.GONE
}
private fun showNumKeyboardView(){
num_keyboard_view.visibility = View.VISIBLE
}
}
//发送文本、红包、表情
private fun sendMessage(chatBean: ChatBean){
if(chatBean == null){
ToastUtils.makeText(requireActivity(), "发送信息不能为空")
return
}
var content = chatBean.content
if(TextUtils.isEmpty(content)){
ToastUtils.makeText(requireActivity(), "发送信息不能为空")
} else {
ChatManagerUtils.getInstance().sendMessage(toUserId, content)
chat_content.setText("")
CoroutineScope(Dispatchers.IO).launch {
if(chatBean.contentType == ChatBean.CONTENT_TYPE_REDPACKET){
var content = chatBean.content
chatBean.content = CommonUtils.Chat.getRedpacket(content).toString()
} else if(chatBean.contentType == ChatBean.CONTENT_TYPE_TRANSFER){
var content = chatBean.content
chatBean.content = CommonUtils.Chat.getTransfer(content).toString()
}
ChatRepository.insertChat(chatBean)
}
refreshBase(chatBean)
}
}
/**
* 刷新发送、接收聊天信息
* @param chatBean ChatBean
*/
private fun refreshBase(chatBean: ChatBean){
CoroutineScope(Dispatchers.Main).launch {
//chatViewModel.insertChat(chatBean)
TagUtils.d("ChatFragment refreshBase 刷新聊天信息 ")
adapter.refresh(chatBean)
if(chatBean.contentType == ChatBean.CONTENT_TYPE_LOCATION){
delay(200)
}
swipe_target.scrollToPosition(adapter.itemCount -1)
}
}





![[第二十二篇]——Docker 安装 MongoDB](https://img-blog.csdnimg.cn/img_convert/53ddec9b43ef36c3d6fe140664ac2c58.png)












