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/login_root_layout" android:layout_width="240dp" android:layout_height="90dp" android:background="@drawable/wc_redpacket_right_normal"> <TextView android:id="@+id/redpacket_content" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:text="恭喜发财,大吉大利" android:textColor="#ffffff" android:textSize="16sp" android:textStyle="bold" app:layout_constraintBottom_toBottomOf="@+id/redpacket_icon" app:layout_constraintStart_toEndOf="@+id/redpacket_icon" app:layout_constraintTop_toTopOf="@+id/redpacket_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/redpacket_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="私人红包" android:textColor="#d9d6c3" android:textSize="10sp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" /> <androidx.appcompat.widget.AppCompatImageView android:id="@+id/redpacket_icon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="18dp" android:layout_marginTop="10dp" android:src="@drawable/wc_redpacket_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/other_redpacket_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_redpacket_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_redpacket_icon"/> <TextView android:id="@+id/redpacket_content" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="恭喜发财,大吉大利" android:textSize="16sp" android:textColor="#ffffff" android:textStyle="bold" android:layout_marginLeft="10dp" app:layout_constraintStart_toEndOf="@+id/other_redpacket_icon" app:layout_constraintTop_toTopOf="@+id/other_redpacket_icon" app:layout_constraintBottom_toBottomOf="@+id/other_redpacket_icon"/> <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_redpacket_icon" app:layout_constraintBottom_toTopOf="@+id/redpacket_tip"/> <TextView android:id="@+id/redpacket_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="私人红包" android:textSize="10sp" android:textColor="#d9d6c3"/> </androidx.constraintlayout.widget.ConstraintLayout> </layout>
/** * Author : wangning * Email : maoning20080809@163.com * Date : 2022/5/29 18:09 * Description : 红包页面 */ class RedpacketFragment : BaseDataBindingFragment<WcRedpacketMainBinding>(),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) }