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

实现代码:
<?xml version="1.0" encoding="utf-8"?>
<layout>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/wc_base_bg">
<androidx.appcompat.widget.AppCompatEditText
android:id="@+id/contacts_search_phone"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
android:paddingLeft="12dp"
android:drawableLeft="@android:drawable/ic_search_category_default"
android:layout_width="300dp"
android:layout_height="48dp"
android:background="@color/white"
android:hint="账户/手机号"/>
<TextView
android:id="@+id/contacts_search_cancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="@+id/contacts_search_phone"
app:layout_constraintBottom_toBottomOf="@+id/contacts_search_phone"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginEnd="10dp"
android:padding="12dp"
android:textColor="@color/blue"
android:textSize="18sp"
android:text="取消"/>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/contacts_search_result_layout"
app:layout_constraintTop_toBottomOf="@+id/contacts_search_phone"
app:layout_constraintStart_toStartOf="parent"
android:layout_margin="20dp"
android:visibility="gone"
android:background="@color/white"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/contacts_search_result_icon"
app:layout_constraintTop_toTopOf="@+id/contacts_search_result_layout"
app:layout_constraintStart_toStartOf="parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/contacts_default_icon"/>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/contacts_search_result_txt"
app:layout_constraintStart_toEndOf="@+id/contacts_search_result_icon"
app:layout_constraintTop_toTopOf="@+id/contacts_search_result_icon"
app:layout_constraintBottom_toBottomOf="@+id/contacts_search_result_icon"
android:layout_marginLeft="20dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/black"
android:textSize="16sp"
android:text="搜索:185xxxxxxxxx"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/contacts_search_recycler_view"
app:layout_constraintTop_toBottomOf="@+id/contacts_search_result_layout"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_width="match_parent"
android:layout_margin="10dp"
android:layout_height="0dp"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
/**
* Author : wangning
* Email : maoning20080809@163.com
* Date : 2022/4/21 21:18
* Description : 根据账户搜索用户
*/
class SearchFriendsFragment : BaseDataBindingFragment<WcFragmentContactsSearchBinding>() {
override fun getLayoutRes() = R.layout.wc_fragment_contacts_search
private val xmppViewModel : XmppViewModel by viewModels()
private val userViewModel : UserViewModel by viewModels()
private val contactViewModel : ContactsViewModel by viewModels()
private var adapter : SearchContactsAdapter? = null
//好友列表
private var contactsList : MutableList<ContactsBean>? = null
private var navController : NavController? = null
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
super.builder().setTitleContent("")
navController = findNavController()
contacts_search_cancel.setOnClickListener {
Navigation.findNavController(it).popBackStack()
}
var account = DataStoreUtils.getAccount()
contacts_search_result_layout.setOnClickListener {
TagUtils.d("搜索查询:${contacts_search_phone.text.toString()}")
//xmppViewModel.searchUserByName(contacts_search_phone.text.toString())
userViewModel.getUserLikeAccount(account, contacts_search_phone.text.toString())
}
contacts_search_phone.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) {
//TagUtils.d("onTextChanged ${s}, , count = ${count}, length = ${s?.length}")
if(s?.length!! > 0){
var result = getString(R.string.wc_search_friend_tips, s)
contacts_search_result_layout.visibility = View.VISIBLE
contacts_search_result_txt.text = result
} else {
contacts_search_result_layout.visibility = View.GONE
contacts_search_recycler_view.visibility = View.GONE
}
}
override fun afterTextChanged(s: Editable?) {
}
})
userViewModel.getUserListLiveData.observe(viewLifecycleOwner){
if(it == null || it.size < 1){
ToastUtils.makeText(R.string.search_list_empty)
} else {
contacts_search_recycler_view.visibility = View.VISIBLE
adapter?.refresh(it)
}
}
contactViewModel.getContactsList(account)
contactViewModel.contactsListLiveData.observe(viewLifecycleOwner){
contactsList = it
}
/*xmppViewModel.userListDataLiveData.observe(viewLifecycleOwner){
contacts_search_recycler_view.visibility = View.VISIBLE
adapter?.refresh(it)
}*/
adapter = SearchContactsAdapter()
var linearLayoutManager = LinearLayoutManager(activity)
linearLayoutManager.orientation = LinearLayoutManager.VERTICAL
contacts_search_recycler_view.layoutManager = linearLayoutManager
contacts_search_recycler_view.adapter = adapter
adapter?.setOnItemClickInterface(object : SearchContactsAdapter.OnItemClickInterface{
override fun onItemClick(userBean: UserBean) {
SoftInputUtils.hideSoftInput(contacts_search_result_layout)
navController?.popBackStack(R.id.nav_contacts_add_friends, true)
if(isFriend(userBean.account)) {
//如果是好友,直接跳转到聊天页面
var bundle = bundleOf(ChatFragment.USER_ID to userBean.account)
navController?.navigate(R.id.nav_chat, bundle)
} else {
val bundle = bundleOf("userbean" to userBean)
navController?.navigate(R.id.action_contacts_search_friends_details, bundle)
}
}
})
}
private fun isFriend(searchAccount : String) : Boolean{
var resultList = contactsList?.filter {
it.toAccount.equals(searchAccount)
}
return resultList?.size!! > 0
}
}
/**
* Author : wangning
* Email : maoning20080809@163.com
* Date : 2022/4/22 17:51
* Description :
*/
class SearchContactsAdapter : RecyclerView.Adapter<SearchContactsAdapter.SearchViewHolder>(){
private var userList = ArrayList<UserBean>()
private var onItemClickInterface :OnItemClickInterface? = null
fun setOnItemClickInterface(onItemClickInterface :OnItemClickInterface?){
this.onItemClickInterface = onItemClickInterface
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SearchViewHolder {
var view = LayoutInflater.from(parent.context).inflate(R.layout.wc_fragment_contacts_search_item, parent, false)
return SearchViewHolder(view)
}
override fun onBindViewHolder(holder: SearchViewHolder, position: Int) {
var userBean = userList.get(position)
holder.account.text = BaseUtils.getString(R.string.wc_search_friend_account, userBean.account)
holder.account.setOnClickListener {
onItemClickInterface?.onItemClick(userBean)
}
}
fun refresh(userList : ArrayList<UserBean>) {
if(userList == null || userList.size == 0){
this.userList = ArrayList<UserBean>()
} else {
this.userList = userList
}
notifyDataSetChanged()
}
override fun getItemCount(): Int = userList?.size
class SearchViewHolder(itemView : View) : RecyclerView.ViewHolder(itemView) {
var account = itemView.findViewById<TextView>(R.id.contacts_search_item_account)
}
interface OnItemClickInterface{
abstract fun onItemClick(userBean: UserBean)
}
}












![[附源码]Python计算机毕业设计Django家庭教育app](https://img-blog.csdnimg.cn/be5aac86c7d2459b9082b79a723efc27.png)
![[附源码]Python计算机毕业设计Django惠农微信小程序论文](https://img-blog.csdnimg.cn/a27c1cb9b5fd4a27be3024b431c3cac1.png)




![[附源码]计算机毕业设计JAVA校园淘宝节系统](https://img-blog.csdnimg.cn/fb7f1dc558b7448fa6e8fe84a8ffde43.png)