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) } }