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



















