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

实现代码:
我的红包页面
好友的红包页面:
/** * Author : wangning * Email : maoning20080809@163.com * Date : 2022/5/29 18:09 * Description : 红包页面 */ class RedpacketFragment : BaseDataBindingFragment(),MyDispatchTouchEventListener { override fun getLayoutRes() = R.layout.wc_redpacket_main private var navController : NavController? = null companion object { const val REDPACKET_BALANCE = "redpacket_balance" } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) super.builder().setTitleContent(R.string.wc_base_top_redpacket) navController = findNavController() redpacket_balance.showSoftInputOnFocus = false num_keyboard_view.initEditText(redpacket_balance) num_keyboard_view.setRechargeBackground(R.drawable.wc_base_red_selector) num_keyboard_view.setValue(R.string.wc_confirm) num_keyboard_view.visibility = View.GONE redpacket_balance.setOnClickListener { showNumKeyboardView() SoftInputUtils.hideSoftInput(redpacket_greetings) } num_keyboard_item_recharge.setOnClickListener { hideNumKeyboardView() } redpacket_main_root.setOnClickListener { hideNumKeyboardView() SoftInputUtils.hideSoftInput(redpacket_greetings) } redpacket_greetings.setOnClickListener { hideNumKeyboardView() } redpacket_balance.addTextChangedListener(object : TextWatcher{ override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { } override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { if(TextUtils.isEmpty(s)){ redpacket_result_balance.text = "" } else { var balance = s.toString().toFloat() redpacket_result_balance.text = CommonUtils.Base.getFormatBalanceUnit(balance) } } override fun afterTextChanged(s: Editable?) { } }) redpacket_ok.setOnClickListener { var balance = redpacket_balance.text?.toString()?.trim()!! if(TextUtils.isEmpty(balance)){ ToastUtils.makeText(requireActivity(), "请输入红包金额") } else { TagUtils.d("发送红包:${balance}") if(!UserRepository.judgeBalanceAvailable(balance.toFloat())){ ToastUtils.makeText(R.string.wc_payment_balance_available) } else { navController?.previousBackStackEntry?.savedStateHandle?.set(REDPACKET_BALANCE, redpacket_balance.text.toString().toFloat()) navController?.popBackStack() } } } } override fun onResume() { super.onResume() redpacket_balance.isFocusableInTouchMode = true redpacket_balance.requestFocus() redpacket_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 } } } override fun dispatchTouchEvent(ev: MotionEvent) { if (ev.action == MotionEvent.ACTION_DOWN) { if (SoftInputUtils.isInput(rechange_balance, ev)) { num_keyboard_view?.visibility = View.GONE } } } 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)
}
}
插入本地数据库:
fun insertChat(chatBean: ChatBean) : Long {
var chatListLocal = getAllChat()
if(chatListLocal == null || chatListLocal.size < 1){
return WcDatabase.getInstance(WcApp.getContext()).chatDao().insertChat(chatBean)
}
var resultList = chatListLocal.filter {
it.messageId.equals(chatBean.messageId)
}
//过滤重复数据
if(resultList.size > 0){
return 0
}
return WcDatabase.getInstance(WcApp.getContext()).chatDao().insertChat(chatBean)
}
接收红包:
if(content.startsWith(CommonUtils.Chat.REDPACKET_MARK)){
//发送红包, 去掉redpacket###写入数据库
content = CommonUtils.Chat.getRedpacket(content).toString()
var chatBean = CommonUtils.Chat.getChatBean(fromUser, toUser, userType, content, ChatBean.CONTENT_TYPE_REDPACKET, "",0.0, 0.0)
ChatRepository.insertChat(chatBean)
chatBean.isReceive = true
EventBus.getDefault().post(chatBean)
}