Kotlin高仿微信-第8篇-单聊

news/2024/4/27 9:31:57/文章来源:https://blog.csdn.net/maoning20080808/article/details/128095470

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:id="@+id/chat_main_root"android:background="@drawable/wc_base_bg"><include layout="@layout/wc_base_top_title"/><androidx.constraintlayout.widget.ConstraintLayoutandroid:layout_width="match_parent"android:layout_height="0dp"android:focusable="true"android:focusableInTouchMode="true"app:layout_constraintTop_toBottomOf="@+id/base_top_root_layout"app:layout_constraintBottom_toTopOf="@+id/chat_bottom_layout"><com.aspsine.swipetoloadlayout.SwipeToLoadLayoutandroid:id="@+id/swipeToLoadLayout"app:layout_constraintTop_toTopOf="parent"app:layout_constraintBottom_toTopOf="@+id/chat_audio"app:layout_constraintBottom_toBottomOf="parent"android:layout_marginBottom="12dp"android:layout_width="match_parent"android:layout_height="0dp"><com.wn.wechatclientdemo.view.ChatRefreshHeaderViewandroid:id="@+id/swipe_refresh_header"android:layout_width="match_parent"android:layout_height="wrap_content" /><androidx.recyclerview.widget.RecyclerViewandroid:id="@+id/swipe_target"android:layout_width="match_parent"android:layout_height="wrap_content"android:scrollbars="vertical" /></com.aspsine.swipetoloadlayout.SwipeToLoadLayout><androidx.appcompat.widget.AppCompatImageViewandroid:id="@+id/chat_audio"android:layout_width="38dp"android:layout_height="38dp"android:layout_marginBottom="10dp"android:layout_marginTop="100dp"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintStart_toStartOf="parent"android:src="@drawable/wc_chat_audio"/><EditTextandroid:id="@+id/chat_content"android:layout_width="0dp"android:layout_height="38dp"android:layout_marginHorizontal="10dp"android:paddingLeft="8dp"android:background="@drawable/chat_message_shap_bg"app:layout_constraintStart_toEndOf="@+id/chat_audio"app:layout_constraintEnd_toStartOf="@+id/chat_emoji"app:layout_constraintTop_toTopOf="@+id/chat_audio"app:layout_constraintBottom_toBottomOf="@+id/chat_audio"/><com.wn.wechatclientdemo.view.ChatRecordButtonandroid:id="@+id/chat_record_btn"android:layout_width="0dp"android:layout_height="38dp"android:visibility="gone"android:layout_marginHorizontal="10dp"android:background="@drawable/wc_chat_voice_selector"app:layout_constraintStart_toEndOf="@+id/chat_audio"app:layout_constraintEnd_toStartOf="@+id/chat_emoji"app:layout_constraintTop_toTopOf="@+id/chat_audio"app:layout_constraintBottom_toBottomOf="@+id/chat_audio"android:text="按住说话"/><androidx.appcompat.widget.AppCompatImageViewandroid:id="@+id/chat_emoji"android:layout_width="38dp"android:layout_height="38dp"android:layout_marginEnd="10dp"app:layout_constraintEnd_toStartOf="@+id/chat_add_or_send"app:layout_constraintBottom_toBottomOf="@+id/chat_content"app:layout_constraintTop_toTopOf="@+id/chat_content"android:src="@drawable/wc_chat_emoji"/><androidx.constraintlayout.widget.ConstraintLayoutandroid:id="@+id/chat_add_or_send"android:layout_width="wrap_content"android:layout_height="wrap_content"app:layout_constraintTop_toTopOf="@+id/chat_content"app:layout_constraintTop_toBottomOf="@+id/chat_content"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"><androidx.appcompat.widget.AppCompatImageViewandroid:id="@+id/chat_add"android:layout_width="38dp"android:layout_height="38dp"android:layout_marginEnd="10dp"android:layout_marginBottom="10dp"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"android:visibility="visible"android:src="@drawable/wc_chat_add"/><androidx.appcompat.widget.AppCompatTextViewandroid:id="@+id/chat_send"app:layout_constraintBottom_toBottomOf="@+id/chat_add_or_send"app:layout_constraintTop_toTopOf="@+id/chat_add_or_send"app:layout_constraintEnd_toEndOf="parent"android:layout_marginRight="10dp"android:layout_marginBottom="6dp"android:padding="6dp"android:layout_width="wrap_content"android:layout_height="wrap_content"android:gravity="center"android:visibility="gone"android:background="@drawable/wc_blue_light_shape"android:textColor="@color/blue"android:textStyle="bold"android:text="发送"/></androidx.constraintlayout.widget.ConstraintLayout></androidx.constraintlayout.widget.ConstraintLayout><androidx.constraintlayout.widget.ConstraintLayoutandroid:id="@+id/chat_bottom_layout"android:layout_width="match_parent"android:layout_height="220dp"android:visibility="gone"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"><includeandroid:id="@+id/chat_add_layout"android:layout_width="match_parent"android:layout_height="match_parent"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"android:visibility="gone"layout="@layout/wc_chat_add_layout"/><includeandroid:id="@+id/chat_emoji_layout"android:layout_width="match_parent"android:layout_height="match_parent"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"android:visibility="visible"layout="@layout/wc_chat_emoji_layout"/></androidx.constraintlayout.widget.ConstraintLayout></androidx.constraintlayout.widget.ConstraintLayout>
</layout>

/*** Author : wangning* Email : maoning20080809@163.com* Date : 2022/4/24 14:10* Description : 聊天页面*/
class ChatFragment : BaseDataBindingFragment<WcChatMainBinding>() , OnRefreshListener{override fun getLayoutRes()= R.layout.wc_chat_mainprivate val chatViewModel: ChatViewModel by viewModels()private val emojiViewModel : EmojiViewModel by viewModels()private val userViewModel : UserViewModel by viewModels()private val vipViewModel : VipManagerViewModel by viewModels()private val REQUEST_PICTURE_CODE = 101//申请权限private val REQUEST_PERMISSION_CODE = 102private var toUserId : String = ""private var toUserName : String = ""private var adapter : ChatAdapter = ChatAdapter(RedpacketClick(), OnItemLongClick())private var account = DataStoreUtils.get(DataStoreParams.User.DS_ACCOUNT, "") as Stringprivate var navController : NavController? = nullprivate var isOpenRedpacketDialog = falseprivate var mRedpacketBalance = 0fprivate var mRedpacketFromUser = ""//每页13条private val PAGE_SIZE = 13//当前页private var PAGE_NUM = 1//从那一条开始(为保证最新的先显示, 先查询最后的,并且不能用desc查询)private var startNum = 0//总共多少条private var CHAT_TOTAL = 0companion object {const val USER_ID = "CHAT_USER_ID"}override fun onViewCreated(view: View, savedInstanceState: Bundle?) {super.onViewCreated(view, savedInstanceState)TagUtils.d("ChatFragment 进入")//先判断是否已经注册if(!EventBus.getDefault().isRegistered(this)){EventBus.getDefault().register(this)}swipeToLoadLayout.setOnRefreshListener(this)//swipeToLoadLayout.setOnLoadMoreListener(this) 不适用加载更多handlePermission()ChatNotificationUtils.setChatFragment(true)}override fun onPause() {super.onPause()AudioUtils.stopChatVoice()}private fun processInit(){checkNetwork()initView()initListener()initEmoji()checkRenewall()}private fun processScrollToPosition(){//保证在主线程中进行滑动操作CoroutineScope(Dispatchers.Main).launch {delay(100)swipe_target.scrollToPosition(adapter.itemCount - 1)}}var scrollX : Float = 0fvar scrollY : Float = 0fvar linearLayoutManager: LinearLayoutManager? = nullprivate fun initView(){linearLayoutManager = LinearLayoutManager(requireContext())linearLayoutManager?.orientation = LinearLayoutManager.VERTICALswipe_target.layoutManager = linearLayoutManagerswipe_target.adapter = adapter//处理点击发送消息框, 列表向上移动chat_content.setOnClickListener {if(chat_bottom_layout.visibility == View.VISIBLE){chat_bottom_layout.visibility = View.GONE}SoftInputUtils.showSoftInput(requireActivity(), chat_content)processScrollToPosition()}swipeToLoadLayout.setOnTouchListener { view, motionEvent ->SoftInputUtils.hideSoftInput(chat_content)hideBottomLayout()false}navController = findNavController()navController?.currentBackStackEntry?.savedStateHandle?.getLiveData<Float>(RedpacketFragment.REDPACKET_BALANCE)?.observe(viewLifecycleOwner){TagUtils.d("红包返回金额:${it}")if(it > 0){var content = CommonUtils.Chat.REDPACKET_MARK + itvar chatBean = CommonUtils.Chat.getChatBean(account, toUserId, ChatBean.USER_TYPE_ME, content, ChatBean.CONTENT_TYPE_REDPACKET, "",0.0, 0.0)sendMessage(chatBean)}}navController?.currentBackStackEntry?.savedStateHandle?.getLiveData<Float>(CommonUtils.QRCommon.TRANSFER_BALANCE)?.observe(viewLifecycleOwner){TagUtils.d("转账返回金额:${it}")if(it > 0){var content = CommonUtils.Chat.TRANSFER_MARK + itvar chatBean = CommonUtils.Chat.getChatBean(account, toUserId, ChatBean.USER_TYPE_ME, content, ChatBean.CONTENT_TYPE_TRANSFER, "",0.0, 0.0)sendMessage(chatBean)}}//录音完成回调chat_record_btn.setOnFinishedRecordListener(object : ChatRecordButton.OnFinishedRecordListener{override fun onFinishedRecord(audioPath: String, time: Int) {chat_content.isFocusable = falseSoftInputUtils.hideSoftInput(chat_record_btn)AddFileListener.sendFile(ChatBean.CONTENT_TYPE_VOICE, audioPath, toUserId, time)}})userViewModel.balanceRedpacketLiveData.observe(viewLifecycleOwner){TagUtils.d("领取红包服务器返回:${it}")if(it.position >= 0){//ToastUtils.makeText(requireActivity(), BaseUtils.getString(R.string.wc_receive_redpacket_success))redPacketDialogUtils.dismissDialog()var position = it.positionvar chatBean = adapter.getItemObject(position)chatBean?.let {//设置为点击状态it.isClick = 1adapter.chatList?.set(position, it)adapter.notifyItemChanged(position)chatViewModel.updateChatClickByMessageIdLocal(it.isClick, it.messageId)}if(isOpenRedpacketDialog){CoroutineScope(Dispatchers.Main).launch {var bundle = bundleOf(CommonUtils.QRCommon.BALANCE to mRedpacketBalance,CommonUtils.QRCommon.TO_USER to mRedpacketFromUser,CommonUtils.QRCommon.FROM_ACCOUNT to account)navController?.navigate(R.id.action_redpacket_success, bundle)}}isOpenRedpacketDialog = falseTagUtils.d("点击的view值:${view}")} else {//ToastUtils.makeText(requireActivity(), BaseUtils.getString(R.string.wc_receive_redpacket_success))}}}fun initListener(){//发送文本消息chat_send.setOnClickListener {var content = chat_content.text.toString()var chatBean = CommonUtils.Chat.getChatBean(account, toUserId, ChatBean.USER_TYPE_ME, content, ChatBean.CONTENT_TYPE_TEXT, "",0.0, 0.0)sendMessage(chatBean)chat_emoji.setImageResource(R.drawable.wc_chat_emoji)}//相册chat_add_album.setOnClickListener {clickAddItem()sendPicture()}//拍摄chat_add_small_video.setOnClickListener {clickAddItem()var bundle = bundleOf(CameraFragment.TYPE_ENTER to CameraFragment.TYPE_CHAT)navController?.navigate(R.id.action_svideo_camera, bundle)}//视频通话chat_add_video_call.setOnClickListener {clickAddItem()showVideoPopupWindow()}//发送定位chat_add_location.setOnClickListener {clickAddItem()var bundle = bundleOf(CommonUtils.Chat.TO_USER_ID to toUserId)Navigation.findNavController(it).navigate(R.id.action_baidu_map_poi, bundle)}//录音chat_audio.setOnClickListener {if(chat_record_btn.isShown){hideAudioButton()SoftInputUtils.showSoftInput(requireActivity(), chat_content)} else {showAudioButton()hideEmojiLayout()hideBottomLayout()SoftInputUtils.hideSoftInput(chat_content)processScrollToPosition()}}//表情chat_emoji.setOnClickListener {showBottomLayout()showEmojiLayout()hideAddLayout()hideAudioButton()processScrollToPosition()}//加号chat_add.setOnClickListener {showBottomLayout()hideEmojiLayout()showAddLayout()hideAudioButton()processScrollToPosition()}chat_content.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(s.length > 0){chat_send.visibility = View.VISIBLEchat_add.visibility = View.GONE} else {chat_send.visibility = View.GONEchat_add.visibility = View.VISIBLE}}override fun afterTextChanged(s: Editable?) {}})//红包chat_add_radpacket.setOnClickListener {clickAddItem()navController?.navigate(R.id.action_redpacket)}//转账chat_add_transfer.setOnClickListener {clickAddItem()var bundle = bundleOf(CommonUtils.QRCommon.TO_USER to toUserId)navController?.navigate(R.id.action_payment_transfer, bundle)}//文件chat_add_file.setOnClickListener {clickAddItem()ToastUtils.showBaseTip()}//收藏chat_add_collection.setOnClickListener {clickAddItem()ToastUtils.showBaseTip()}}private fun initData(){//先进入页面,再刷新数据。toUserId = arguments?.getString(USER_ID)?:""super.builder().setTitleContent("")var fromAccount: String = accountvar toAccount: String = toUserIdCHAT_TOTAL = chatViewModel.getChatCountByAccountAsync(fromAccount, toAccount)startNum = CHAT_TOTAL - PAGE_SIZE * PAGE_NUM//先查询到我、朋友的头像var fromUserBean = UserRepository.getUserByAccountSync(fromAccount)var toUserBean = UserRepository.getUserByAccountSync(toAccount)adapter.addMeAtavar(fromUserBean?.avatar)adapter.addOtherAtavar(toUserBean?.avatar)toUserName = toUserBean.nickNamevar friendIsAvailable =  XmppConnectionManager.getInstance().getUserIsAvailable(toUserId)var titleContent = ""if(friendIsAvailable){titleContent = toUserName + BaseUtils.getString(R.string.wc_chat_online)} else {titleContent = toUserName + BaseUtils.getString(R.string.wc_chat_offline)}super.builder().setTitleContent(titleContent)chatViewModel.getChatListByAccountPage(fromAccount, toAccount, startNum, PAGE_SIZE)chatViewModel.chatListLiveData.observe(viewLifecycleOwner){if(PAGE_NUM == 1){adapter.add(it)} else {adapter.refresh(it)}//滚动到底部if(adapter.itemCount > 0){linearLayoutManager?.scrollToPositionWithOffset(adapter.getItemCount() - 1, Integer.MIN_VALUE);}if(startNum > 0){PAGE_NUM++}swipeToLoadLayout.isRefreshing = false}}//发送图片private fun sendPicture(){//单选  // 打开相册ImageSelector.builder().useCamera(false) // 设置是否使用拍照.setSingle(true) //设置是否单选.canPreview(true) //是否点击放大图片查看,,默认为true.start(this,REQUEST_PICTURE_CODE)}//发送文本、红包、表情private fun sendMessage(chatBean: ChatBean){if(chatBean == null){ToastUtils.makeText(requireActivity(), "发送信息不能为空")return}var content = chatBean.contentif(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.contentchatBean.content = CommonUtils.Chat.getRedpacket(content).toString()} else if(chatBean.contentType == ChatBean.CONTENT_TYPE_TRANSFER){var content = chatBean.contentchatBean.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)}}val EVERY_PAGE_SIZE = 21private var mListEmoji : MutableList<EmojiBean> = ArrayList()fun initEmoji(){emojiViewModel.getAllEmoji()emojiViewModel.emojiListLiveData.observe(viewLifecycleOwner) {mListEmoji = itval vpEmoji: ViewPager = chat_emoji_viewpageval indEmoji: EmojiIndicatorView = chat_emoji_ivval inflater = LayoutInflater.from(activity)val pageSize: Int = EVERY_PAGE_SIZEval mEmojiBean = EmojiBean(0, 0)val deleteCount = Math.ceil(mListEmoji.size * 1.0 / EVERY_PAGE_SIZE) .toInt() //要显示的删除键的数量//TagUtils.d("" + deleteCount)for (i in 1 until deleteCount + 1) {if (i == deleteCount) {mListEmoji.add(mListEmoji.size, mEmojiBean)} else {mListEmoji.add(i * EVERY_PAGE_SIZE - 1, mEmojiBean)}//TagUtils.d("添加次数$i")}val pageCount = Math.ceil(mListEmoji.size * 1.0 / pageSize).toInt() //一共的页数//TagUtils.d("总共的页数:$pageCount")val viewList: MutableList<View> = ArrayList()for (index in 0 until pageCount) {//每个页面创建一个recycleviewval recyclerView = inflater.inflate(R.layout.wc_chat_emoji_item_vprecy, vpEmoji, false) as RecyclerViewrecyclerView.layoutManager = GridLayoutManager(activity, 7)var entranceAdapter: EmojiAdapterif (index == pageCount - 1) {//最后一页的数据val lastPageList: List<EmojiBean> = mListEmoji.subList(index * EVERY_PAGE_SIZE,mListEmoji.size)entranceAdapter = EmojiAdapter(lastPageList)} else {entranceAdapter = EmojiAdapter(mListEmoji.subList(index * EVERY_PAGE_SIZE,(index + 1) * EVERY_PAGE_SIZE))}entranceAdapter.setOnItemClickListener(object : BaseQuickAdapter.OnItemClickListener{override fun onItemClick(adapter: BaseQuickAdapter<*, *>,view: View?,position: Int) {if (mEmojiBean.id === 0) {//如果是删除键//mEditText.dispatchKeyEvent( KeyEvent( KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL ) )} else {//mEditText.append((adapter.getData().get(position) as EmojiBean).getUnicodeInt() )}}})recyclerView.adapter = entranceAdapterviewList.add(recyclerView)entranceAdapter.setOnItemClickListener { adapter, view, position ->TagUtils.d("点击表情:${position} , ${adapter.getItem(position)}")var emojiBean = adapter.getItem(position) as EmojiBeanvar content = chat_content.text.toString()content += emojiBean.getEmojiStringByUnicode(emojiBean.unicode)chat_content.setText(content)//光标放在最后chat_content?.setSelection(content.length)}}val adapter = EmojiVpAdapter(viewList)vpEmoji.adapter = adapterindEmoji.setIndicatorCount(vpEmoji.adapter!!.count)indEmoji.setCurrentIndicator(vpEmoji.currentItem)vpEmoji.addOnPageChangeListener(object : SimpleOnPageChangeListener() {override fun onPageSelected(position: Int) {indEmoji.setCurrentIndicator(position)}})//TagUtils.d("Emoji初始化完毕")}}override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {super.onActivityResult(requestCode, resultCode, data)if (requestCode == REQUEST_PICTURE_CODE && data != null) {val images = data.getStringArrayListExtra(ImageSelector.SELECT_RESULT)if(images != null && images.size > 0) {AddFileListener.sendFile(ChatBean.CONTENT_TYPE_IMG, images[0], toUserId,0)}}}override fun onRequestPermissionsResult(requestCode: Int,permissions: Array<out String>,grantResults: IntArray) {super.onRequestPermissionsResult(requestCode, permissions, grantResults)if(requestCode == REQUEST_PERMISSION_CODE && grantResults != null && grantResults.size > 0){if(grantResults[0] == PackageManager.PERMISSION_GRANTED){//录音权限, 暂时不处理processInit()}}}private fun handlePermission(){if(checkPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)||checkPermission(Manifest.permission.CAMERA)||checkPermission(Manifest.permission.RECORD_AUDIO)||checkPermission(Manifest.permission.ACCESS_FINE_LOCATION)||checkPermission(Manifest.permission.ACCESS_COARSE_LOCATION)){var permissions = arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO,Manifest.permission.CAMERA,Manifest.permission.ACCESS_FINE_LOCATION,Manifest.permission.ACCESS_COARSE_LOCATION)requestPermissions(permissions, REQUEST_PERMISSION_CODE)} else {//录音权限, 暂时不处理processInit()}}private fun checkPermission(permission: String) :Boolean {return ContextCompat.checkSelfPermission(requireActivity(), permission) != PackageManager.PERMISSION_GRANTED}private lateinit var redPacketDialogUtils : RedPacketDialogUtils//长按inner  class OnItemLongClick : WcOnItemLongClickInterface {override fun onItemLongClick(position: Int) {TagUtils.d("长按position:${position}");var chatBean = adapter.getItemObject(position);TagUtils.d("长按chatBean:${chatBean?.content}");showDeleteDialog(position)}}private var baseDialogUtils : BaseDialogUtils? = null//显示删除对话框fun showDeleteDialog(position : Int){var view = LayoutInflater.from(this.requireActivity()).inflate(R.layout.wc_chat_delete_tip, null)baseDialogUtils = BaseDialogUtils(this.requireActivity())baseDialogUtils!!.builder().showView(view).setCancelable(false).setOnLoadingClick(object : BaseDialogUtils.OnLoadingClick{override fun onClickCancel() {}override fun onClickConfirm() {var chatBean = adapter.getItemObject(position)if(chatBean!=null){chatViewModel.deleteChat(chatBean)}adapter.remove(position)}})baseDialogUtils?.show()}//聊天页面点击红包inner class RedpacketClick : WcOnItemClickInterface {override fun onItemClick(obj: Any) {if(!NetWorkUtils.isNetworkConnected()){ToastUtils.makeText(requireActivity(), BaseUtils.getString(R.string.wc_base_network_tip))return}TagUtils.d("点击红包打开按钮 ${obj}")var redPacketBean = obj as RedPacketBean//var redPacketBean = RedPacketBean("chaychan","https://img2.baidu.com/it/u=2059292981,3255805850&fm=253&fmt=auto&app=138&f=JPEG?w=200&h=200","大吉大利,今晚吃鸡")if(redPacketBean.isClick == 1){var bundle = bundleOf(CommonUtils.QRCommon.BALANCE to redPacketBean.balance,CommonUtils.QRCommon.TO_USER to redPacketBean.account,CommonUtils.QRCommon.FROM_ACCOUNT to account)navController?.navigate(R.id.action_redpacket_success, bundle)} else {redPacketDialogUtils = RedPacketDialogUtils()redPacketDialogUtils.showRedPacketDialog(requireActivity(), redPacketBean, RedpacketDialogClick())isOpenRedpacketDialog = true}}}//弹出红包对话框点击open按钮inner class RedpacketDialogClick : RedPacketDialogClickInterface {override fun onOpenClick(redPacketBean: RedPacketBean) {if(!NetWorkUtils.isNetworkConnected()){ToastUtils.makeText(requireActivity(), BaseUtils.getString(R.string.wc_base_network_tip))redPacketDialogUtils.dismissDialog()return}GlobalScope.launch {delay(2000)//领取红包,调用接口var balance = redPacketBean.balanceTagUtils.d("点击领取红包元: ${balance}")if(balance > 0){mRedpacketBalance = balancemRedpacketFromUser = redPacketBean.accountvar account = DataStoreUtils.getAccount()userViewModel.updateBalanceRedpacketServer(redPacketBean.position, account, CommonUtils.User.OPERATOR_PLUS, balance)}}}}@Subscribe(threadMode = ThreadMode.MAIN)fun onMessageCallback(obj: Any) {//chatBean: ChatBeanif(obj == null){return}TagUtils.d("接收对象:${obj}")//本地小视频回调if(obj is SVideoBean){TagUtils.d("接收对象type :${obj.type} , ${obj.filePath}")if(obj.type == CommonUtils.Moments.TYPE_PICTURE){//图片//processSendFile(obj.filePath, toUserId)AddFileListener.sendFile(ChatBean.CONTENT_TYPE_IMG, obj.filePath, toUserId, 0)} else if(obj.type == CommonUtils.Moments.TYPE_VIDEO){//小视频//processSendVideo(obj.filePath, toUserId)AddFileListener.sendFile(ChatBean.CONTENT_TYPE_VIDEO, obj.filePath, toUserId,0)}}//接收信息if(obj is ChatBean){if(obj.isReceive){//接收信息, 当前聊天用户id页面才刷新if(obj.fromAccount.equals(toUserId)){refreshBase(obj)}} else {refreshBase(obj)}}}private fun hideAudioButton(){chat_record_btn.visibility = View.GONEchat_audio.setImageResource(R.drawable.wc_chat_audio)}private fun showAudioButton(){chat_record_btn.visibility = View.VISIBLEchat_audio.setImageResource(R.drawable.wc_chat_keyboard)}private fun hideEmojiLayout() {TagUtils.d("隐藏emojiLayout")chat_emoji_layout.visibility = View.GONEchat_emoji.setImageResource(R.drawable.wc_chat_emoji)}private fun showEmojiLayout(){chat_content.requestFocus()chat_emoji_layout.visibility = View.VISIBLEchat_emoji.setImageResource(R.drawable.wc_chat_keyboard)}fun hideAddLayout(){TagUtils.d("隐藏addLayout")chat_add_layout.visibility = View.GONE}fun showAddLayout(){chat_add_layout.visibility = View.VISIBLE}fun hideBottomLayout() {//TagUtils.d("隐藏底部")chat_bottom_layout.visibility = View.GONE}fun showBottomLayout() {var softInputHeight: Int = BaseUtils.getDimension(R.dimen.wc_chat_emoji_height)SoftInputUtils.hideSoftInput(chat_content)chat_bottom_layout.getLayoutParams().height = softInputHeightchat_bottom_layout.visibility = View.VISIBLE}//点击底部按钮fun clickAddItem(){showAudioButton()hideEmojiLayout()hideBottomLayout()chat_content.clearFocus()SoftInputUtils.hideSoftInput(chat_content)processScrollToPosition()}override fun onDestroy() {super.onDestroy()EventBus.getDefault().unregister(this)ChatNotificationUtils.setChatFragment(false)SyncUtils.processInsertChatList()}private fun checkNetwork(){if(!NetWorkUtils.isNetworkConnected()){ToastUtils.makeText(R.string.wc_base_network_error)}}/*** 检查vip信息*/private fun checkRenewall(){//view加载完成chat_main_root.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener{override fun onGlobalLayout() {if(!TextUtils.isEmpty(account)){vipViewModel.getVipLocal(account)}initData()chat_main_root.viewTreeObserver.removeOnGlobalLayoutListener(this)}})vipViewModel.vipBeanLiveData.observe(viewLifecycleOwner){if(it == null || !CommonUtils.Vip.isVip(it)){showRenewalView()}}vipViewModel.vipBeanServerLiveData.observe(viewLifecycleOwner){if(it == null){ToastUtils.makeText(R.string.wc_vip_renewal_get_no_data)} else if(!CommonUtils.Vip.isVip(it)){ToastUtils.makeText(R.string.wc_vip_renewal_get_no_vip)} else {basePopupWindow?.baseDismiss()//如果是vip,更新到本地数据库vipViewModel.updateVipLocal(it)}}}private var basePopupWindow : BasePopupWindow? = null/*** 显示续费对话框*/private fun showRenewalView(){var view = LayoutInflater.from(WcApp.getContext()).inflate(R.layout.wc_vip_renewal_view, null)basePopupWindow = BasePopupWindow(requireActivity(), view)basePopupWindow?.let {it.baseSetOnDismissListener(object : BasePopupWindow.IOnDismissListener {override fun onDismiss() {TagUtils.d("dismiss 消失 ")}}).setOnCancelListener(R.id.vip_renewal_cancel,object : BasePopupWindow.IOnCancelListener {override fun onCancelListener() {it.baseDismiss()System.exit(1)}}).setOnConfirmListener(R.id.vip_renewal_get,object : BasePopupWindow.IOnConfirmListener {override fun onConfirmListener() {vipViewModel.getVipServer(account)}}).baseSetFocusable(false).baseShowAtLocation(chat_main_root)}}private var isReallyBack = falseoverride fun onResume() {super.onResume()chat_main_root.isFocusableInTouchMode = truechat_main_root.requestFocus()chat_main_root.setOnKeyListener { view, i, keyEvent ->if (i == KeyEvent.KEYCODE_BACK && keyEvent.getAction() == KeyEvent.ACTION_DOWN) {onBackPressed()}!isReallyBack}}private var exitTime: Long = 0private fun onBackPressed() : Boolean {if(basePopupWindow != null && basePopupWindow?.isShowing!!){if(System.currentTimeMillis() - exitTime > 1000){ToastUtils.makeText(R.string.wc_two_back)exitTime = System.currentTimeMillis()isReallyBack = false} else {//连续点击2次,直接退出appbasePopupWindow?.baseDismiss()isReallyBack = trueSystem.exit(1)}} else {isReallyBack = true}return isReallyBack}//刷新是加载更多数据override fun onRefresh() {TagUtils.d("onRefresh 执行 ${startNum} , ${CHAT_TOTAL}, ${PAGE_SIZE}, ${PAGE_NUM}")CoroutineScope(Dispatchers.Main).launch {delay(200)swipeToLoadLayout.isRefreshing = falseif(startNum >= PAGE_SIZE){startNum = CHAT_TOTAL - PAGE_SIZE * PAGE_NUMchatViewModel.getChatListByAccountPage(account, toUserId, startNum, PAGE_SIZE)} else if(startNum > 0 && startNum < PAGE_SIZE){//不够1页数据,查询全部,然后就不能下一页chatViewModel.getChatListByAccountPage(account, toUserId, 0, startNum)startNum = CHAT_TOTAL - PAGE_SIZE * PAGE_NUM}}}/*** 视频通话、语音通话*/private fun showVideoPopupWindow(){var popupView = layoutInflater.inflate(R.layout.wc_chat_video_pop_view , moment_root, false)var popupWindow = PopupWindow(popupView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, true)var popupRoot = popupView.findViewById<LinearLayout>(R.id.chat_video_pop_root)popupWindow.showAtLocation(popupRoot, Gravity.BOTTOM, 0, 0)var window = requireActivity().window//popupWindow在弹窗的时候背景半透明val params = window.attributesparams.alpha = 0.5fwindow.attributes = paramspopupWindow.setOnDismissListener {params.alpha = 1.0fwindow.attributes = params}//视频通话popupView.findViewById<AppCompatTextView>(R.id.chat_pop_video_call).setOnClickListener {popupWindow.dismiss()CallSingleActivity.openActivity( requireActivity(),toUserId, true, toUserName, false, false)}//语音通话popupView.findViewById<AppCompatTextView>(R.id.chat_pop_voice_call).setOnClickListener {popupWindow.dismiss()CallSingleActivity.openActivity( requireActivity(),toUserId, true, toUserName, true, false)}//取消popupView.findViewById<AppCompatTextView>(R.id.chat_pop_cancel).setOnClickListener {popupWindow.dismiss()}}}

/*** Author : wangning* Email : maoning20080809@163.com* Date : 2022/4/24 16:29* Description :*/
class ChatAdapter(var onClickInterface: WcOnItemClickInterface, var onLongClickInterface : WcOnItemLongClickInterface ) : RecyclerView.Adapter<ChatAdapter.ChatViewHolder>() {//我的头像private var meAvatar = ""//我的其他人private var otherAvatar = ""var chatList : MutableList<ChatBean>? = nullvar account = DataStoreUtils.getAccount()override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ChatViewHolder {var view = LayoutInflater.from(parent.context).inflate(R.layout.wc_chat_item, parent, false)return ChatViewHolder(view)}override fun onBindViewHolder(holder: ChatViewHolder, position: Int) {var chatBean = chatList?.get(position)chatBean?.let {//if(chatBean.userType == ChatBean.USER_TYPE_ME){if(account.equals(chatBean.fromAccount)){//我的holder.meLayout.visibility = View.VISIBLEholder.otherLayout.visibility = View.GONEchatBean.avatarReally = CommonUtils.Base.getReallyImage(meAvatar)holder.meLayout.process(chatBean, onClickInterface)} else {//朋友holder.meLayout.visibility = View.GONEholder.otherLayout.visibility = View.VISIBLEchatBean.avatarReally = CommonUtils.Base.getReallyImage(otherAvatar)holder.otherLayout.process(chatBean, onClickInterface, position)}holder.dateTextView.text = CommonUtils.Date.getCurrentDate(chatBean.addTime)}//长按holder.rootLayout.setOnLongClickListener {onLongClickInterface.onItemLongClick(position)true}}fun addMeAtavar(meAvatar:String){this.meAvatar = meAvatar}fun addOtherAtavar(otherAvatar:String){this.otherAvatar = otherAvatar}//刷新单个fun refresh(chatBean: ChatBean){this.chatList?.add(chatBean)notifyItemInserted(itemCount)}//刷新多个fun refresh(chatList : MutableList<ChatBean>){//this.chatList?.addAll(chatList)this.chatList?.addAll(0, chatList)notifyItemInserted(itemCount)}fun add(chatList : MutableList<ChatBean>){this.chatList = chatListnotifyDataSetChanged()}//删除某个fun remove(position: Int){this.chatList?.removeAt(position)notifyDataSetChanged()}fun getItemObject(position : Int) : ChatBean? = chatList?.get(position)override fun getItemCount() = chatList?.size?:0class ChatViewHolder(itemView : View) : RecyclerView.ViewHolder(itemView){var dateTextView = itemView.findViewById<TextView>(R.id.chat_item_date)var otherLayout = itemView.findViewById<ChatOtherView>(R.id.chat_item_other_layout)var meLayout = itemView.findViewById<ChatMeView>(R.id.chat_item_me_layout)var rootLayout = itemView.findViewById<ConstraintLayout>(R.id.chat_item_root_layout)}
}

<?xml version="1.0" encoding="utf-8"?>
<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:id="@+id/chat_item_root_layout"android:layout_marginTop="16dp"android:layout_width="match_parent"android:layout_height="wrap_content"><TextViewandroid:id="@+id/chat_item_date"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="聊天时间"android:textSize="14sp"android:textStyle="bold"android:textColor="@color/gray_hint"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent" /><!--朋友的聊天信息--><com.wn.wechatclientdemo.view.ChatOtherViewandroid:id="@+id/chat_item_other_layout"app:layout_constraintTop_toBottomOf="@+id/chat_item_date"app:layout_constraintStart_toStartOf="parent"android:layout_width="wrap_content"android:layout_height="wrap_content"/><!--我的聊天信息--><com.wn.wechatclientdemo.view.ChatMeViewandroid:id="@+id/chat_item_me_layout"app:layout_constraintTop_toBottomOf="@+id/chat_item_date"app:layout_constraintEnd_toEndOf="parent"android:visibility="gone"android:layout_width="wrap_content"android:layout_height="wrap_content"/></androidx.constraintlayout.widget.ConstraintLayout>

/*** Author : wangning* Email : maoning20080809@163.com* Date : 2022/5/29 15:41* Description : 聊天内容-其他人*/
class ChatOtherView : LinearLayout {constructor(context: Context) : this(context, null)constructor(context: Context, attributeSet: AttributeSet?) : this(context, attributeSet, 0)constructor(context: Context, attributeSet: AttributeSet?, defStyleAttr: Int) : super(context, attributeSet, defStyleAttr){}init {LayoutInflater.from(context).inflate(R.layout.wc_chat_other_view, this)}fun process(chatBean: ChatBean, onClickInterface : WcOnItemClickInterface, position:Int){GlideUtils.load(chat_item_other_avatar,chatBean.avatarReally, R.drawable.wc_avatar_default)if(chatBean.contentType == ChatBean.CONTENT_TYPE_TEXT){//文字chat_item_other_img.visibility = View.GONEchat_item_other_content_layout.visibility = View.VISIBLEchat_item_other_redpacket.visibility = View.GONEchat_item_other_voice_layout.visibility = View.GONEchat_item_other_video.visibility = View.GONEchat_item_other_mapview.visibility = View.GONEchat_item_other_transfer.visibility = View.GONEchat_item_other_content.text = chatBean.content} else if(chatBean.contentType == ChatBean.CONTENT_TYPE_IMG){//图片chat_item_other_img.visibility = View.VISIBLEchat_item_other_content_layout.visibility = View.GONEchat_item_other_redpacket.visibility = View.GONEchat_item_other_voice_layout.visibility = View.GONEchat_item_other_video.visibility = View.GONEchat_item_other_mapview.visibility = View.GONEchat_item_other_transfer.visibility = View.GONEvar imagePath = chatBean.imgPathLocalif(File(imagePath).exists()){} else {imagePath = CommonUtils.Base.getReallyImage(chatBean.imgPath)}GlideUtils.load(chat_item_other_img, imagePath)chat_item_other_img.setOnClickListener {var bundle = bundleOf(CommonUtils.Moments.TYPE_IMAGE_PATH to imagePath,CommonUtils.Moments.TYPE_NAME to CommonUtils.Moments.TYPE_PICTURE,CommonUtils.Chat.IS_HIDE_CONFIRM to true)Navigation.findNavController(it).navigate(R.id.action_svideo_play, bundle)}} else if(chatBean.contentType == ChatBean.CONTENT_TYPE_VOICE){//语音chat_item_other_img.visibility = View.GONEchat_item_other_content_layout.visibility = View.GONEchat_item_other_redpacket.visibility = View.GONEchat_item_other_voice_layout.visibility = View.VISIBLEchat_item_other_voice_second.text = "${chatBean.second}'"chat_item_other_video.visibility = View.GONEchat_item_other_mapview.visibility = View.GONEchat_item_other_transfer.visibility = View.GONEchat_item_other_voice_layout.setOnClickListener {var voicePath = chatBean.voiceLocalAudioUtils.playChatVoice(ChatBean.USER_TYPE_OTHER, voicePath, chat_item_other_voice)}} else if(chatBean.contentType == ChatBean.CONTENT_TYPE_VIDEO){//小视频chat_item_other_img.visibility = View.GONEchat_item_other_content_layout.visibility = View.GONEchat_item_other_redpacket.visibility = View.GONEchat_item_other_voice_layout.visibility = View.GONEchat_item_other_mapview.visibility = View.GONEchat_item_other_video.visibility = View.VISIBLEchat_item_other_transfer.visibility = View.GONEvar chatVideoUtils = ChatVideoUtils()chat_item_other_video.setSecond(chatBean.second)if(FileUtils.isFileExist(chatBean.videoLocal)){//如果本地小视频存在,直接显示缩略图, 不播放chat_item_other_video.setThumbnail(chatVideoUtils.createVideoThumbnail(chatBean.videoLocal))//chat_item_other_video.initData(chatBean.videoLocal, false)} else {//如果小视频不存在,显示服务器缩略图chat_item_other_video.setThumbnailServer(CommonUtils.Base.getReallyImage(chatBean.imgPath))}chat_item_other_video.setOnClickListener {//如果小视频存在,查看详情if(FileUtils.isFileExist(chatBean.videoLocal)){var bundle = bundleOf(CommonUtils.Moments.TYPE_VIDEO_PATH to chatBean.videoLocal,CommonUtils.Moments.TYPE_NAME to CommonUtils.Moments.TYPE_VIDEO,CommonUtils.Chat.IS_HIDE_CONFIRM to true)Navigation.findNavController(it).navigate(R.id.action_svideo_play, bundle)} else {//如果小视频不存在,网络下载chatVideoUtils.downloadVideo(chat_item_other_video, chatBean)}}} else if(chatBean.contentType == ChatBean.CONTENT_TYPE_LOCATION){//定位chat_item_other_img.visibility = View.GONEchat_item_other_content_layout.visibility = View.GONEchat_item_other_redpacket.visibility = View.GONEchat_item_other_voice_layout.visibility = View.GONEchat_item_other_mapview.visibility = View.VISIBLEchat_item_other_video.visibility = View.GONEchat_item_other_transfer.visibility = View.GONE//点击地图chat_item_other_mapview.setMapOnClick(object : OnMapClickInterface {override fun onMapClick() {var bundle = bundleOf(CommonUtils.Chat.LOCATION_LATITUDE to chatBean.latitude, CommonUtils.Chat.LOCATION_LONGITUDE to chatBean.longitude)Navigation.findNavController(chat_item_other_mapview).navigate(R.id.action_baidu_map_details, bundle)}})chat_item_other_mapview.load(chatBean.latitude, chatBean.longitude)} else if(chatBean.contentType == ChatBean.CONTENT_TYPE_REDPACKET){//红包chat_item_other_img.visibility = View.GONEchat_item_other_content_layout.visibility = View.GONEchat_item_other_redpacket.visibility = View.VISIBLEchat_item_other_voice_layout.visibility = View.GONEchat_item_other_video.visibility = View.GONEchat_item_other_mapview.visibility = View.GONEchat_item_other_transfer.visibility = View.GONEif(chatBean.isClick == 1){chat_item_other_redpacket.setBackgroundResource(R.drawable.wc_redpacket_left_click_normal)other_redpacket_icon.background.alpha = 100chat_item_other_redpacket.setOnClickListener {//已经领取的只能查看红包var redPacketBean = RedPacketBean(position, chatBean.fromAccount, chatBean.content.toFloat(), "恭喜发财,大吉大利", chatBean.isClick)onClickInterface.onItemClick(redPacketBean)}} else {chat_item_other_redpacket.setBackgroundResource(R.drawable.wc_redpacket_left_normal)chat_item_other_redpacket.background.alpha = 255other_redpacket_icon.background.alpha = 255//还没领取红包才可以点击chat_item_other_redpacket.setOnClickListener {TagUtils.d("领取红包:${chatBean.content} , position = ${position}")//var balance = CommonUtils.Chat.getRedpacket(chatBean.content)var redPacketBean = RedPacketBean(position, chatBean.fromAccount, chatBean.content.toFloat(), "恭喜发财,大吉大利", chatBean.isClick)onClickInterface.onItemClick(redPacketBean)}}} else if(chatBean.contentType == ChatBean.CONTENT_TYPE_TRANSFER){//转账chat_item_other_img.visibility = View.GONEchat_item_other_content_layout.visibility = View.GONEchat_item_other_redpacket.visibility = View.GONEchat_item_other_voice_layout.visibility = View.GONEchat_item_other_video.visibility = View.GONEchat_item_other_mapview.visibility = View.GONEchat_item_other_transfer.visibility = View.VISIBLEtransfer_other_balance.text = "${chatBean.content}"if(chatBean.isClick == 1){transfer_other_content.text = "已收款"transfer_tip.setTextColor(BaseUtils.getColor(R.color.white88))chat_item_other_transfer.setBackgroundResource(R.drawable.wc_redpacket_left_click_normal)other_redpacket_icon.background.alpha = 126} else {chat_item_other_transfer.setBackgroundResource(R.drawable.wc_redpacket_left_normal)chat_item_other_transfer.background.alpha = 255chat_item_other_transfer.background.alpha = 255}//不管有没领取转账,点击都会进入详情chat_item_other_transfer.setOnClickListener {var bundle = bundleOf(CommonUtils.QRCommon.TO_USER to chatBean.toAccount,CommonUtils.Chat.MESSAGE_ID to chatBean.messageId,CommonUtils.QRCommon.TRANSFER_BALANCE to chatBean.content)Navigation.findNavController(it).navigate(R.id.action_transfer_details, bundle)}}}}

/*** Author : wangning* Email : maoning20080809@163.com* Date : 2022/5/29 14:59* Description : 聊天内容-我的*/
class ChatMeView : LinearLayout{constructor(context: Context) : this(context, null)constructor(context: Context, attributeSet: AttributeSet?): this(context, attributeSet, 0)constructor(context: Context, attributeSet: AttributeSet?, defStyleAttr :Int) : super(context, attributeSet, defStyleAttr){init(context)}fun init(context: Context){LayoutInflater.from(context).inflate(R.layout.wc_chat_me_view, this)}fun process(chatBean: ChatBean, onClickInterface : WcOnItemClickInterface){//BaseUtils.showAvatar(chatBean.fromAccount, chat_item_me_avatar, chat_item_me_name)GlideUtils.load(chat_item_me_avatar,chatBean.avatarReally, R.drawable.wc_avatar_default)if(chatBean.contentType == ChatBean.CONTENT_TYPE_TEXT){//文本chat_item_me_img.visibility = View.GONEchat_item_me_content_layout.visibility = View.VISIBLEchat_item_me_redpacket.visibility = View.GONEchat_item_me_voice_layout.visibility = View.GONEchat_item_me_video.visibility = View.GONEchat_item_me_mapview.visibility = View.GONEchat_item_me_content.text = chatBean.contentchat_item_me_transfer.visibility = View.GONE} else if(chatBean.contentType == ChatBean.CONTENT_TYPE_IMG){//图片chat_item_me_redpacket.visibility = View.GONEchat_item_me_img.visibility = View.VISIBLEchat_item_me_content_layout.visibility = View.GONEchat_item_me_voice_layout.visibility = View.GONEchat_item_me_video.visibility = View.GONEchat_item_me_mapview.visibility = View.GONEchat_item_me_transfer.visibility = View.GONEvar imagePath = chatBean.imgPathLocalif(File(imagePath).exists()){} else {imagePath = CommonUtils.Base.getReallyImage(chatBean.imgPath)}GlideUtils.load(chat_item_me_img, imagePath)chat_item_me_img.setOnClickListener {var bundle = bundleOf(CommonUtils.Moments.TYPE_IMAGE_PATH to imagePath,CommonUtils.Moments.TYPE_NAME to CommonUtils.Moments.TYPE_PICTURE,CommonUtils.Chat.IS_HIDE_CONFIRM to true)Navigation.findNavController(it).navigate(R.id.action_svideo_play, bundle)}} else if(chatBean.contentType == ChatBean.CONTENT_TYPE_VOICE){//语音chat_item_me_img.visibility = View.GONEchat_item_me_content_layout.visibility = View.GONEchat_item_me_redpacket.visibility = View.GONEchat_item_me_voice_layout.visibility = View.VISIBLEchat_item_me_voice_second.text = "${chatBean.second}'"chat_item_me_video.visibility = View.GONEchat_item_me_mapview.visibility = View.GONEchat_item_me_transfer.visibility = View.GONEchat_item_me_voice_layout.setOnClickListener {var voicePath = chatBean.voiceLocalAudioUtils.playChatVoice(ChatBean.USER_TYPE_ME, voicePath, chat_item_me_voice)}} else if(chatBean.contentType == ChatBean.CONTENT_TYPE_VIDEO){//小视频chat_item_me_img.visibility = View.GONEchat_item_me_content_layout.visibility = View.GONEchat_item_me_redpacket.visibility = View.GONEchat_item_me_voice_layout.visibility = View.GONEchat_item_me_video.visibility = View.VISIBLEchat_item_me_mapview.visibility = View.GONEchat_item_me_transfer.visibility = View.GONEvar chatVideoUtils = ChatVideoUtils()chat_item_me_video.setSecond(chatBean.second)if(FileUtils.isFileExist(chatBean.videoLocal)){//如果本地小视频存在,直接显示缩略图, 不播放chat_item_me_video.setThumbnail(chatVideoUtils.createVideoThumbnail(chatBean.videoLocal))//chat_item_me_video.initData(chatBean.videoLocal, false)} else {//如果小视频不存在,显示服务器缩略图chat_item_me_video.setThumbnailServer(CommonUtils.Base.getReallyImage(chatBean.imgPath))}chat_item_me_video.setOnClickListener {//如果小视频存在,查看详情if(FileUtils.isFileExist(chatBean.videoLocal)){var bundle = bundleOf(CommonUtils.Moments.TYPE_VIDEO_PATH to chatBean.videoLocal,CommonUtils.Moments.TYPE_NAME to CommonUtils.Moments.TYPE_VIDEO,CommonUtils.Chat.IS_HIDE_CONFIRM to true)Navigation.findNavController(it).navigate(R.id.action_svideo_play, bundle)} else {//如果小视频不存在,网络下载chatVideoUtils.downloadVideo(chat_item_me_video, chatBean)}}} else if(chatBean.contentType == ChatBean.CONTENT_TYPE_LOCATION){//定位chat_item_me_img.visibility = View.GONEchat_item_me_content_layout.visibility = View.GONEchat_item_me_redpacket.visibility = View.GONEchat_item_me_voice_layout.visibility = View.GONEchat_item_me_video.visibility = View.GONEchat_item_me_mapview.visibility = View.VISIBLEchat_item_me_transfer.visibility = View.GONE//点击地图chat_item_me_mapview.setMapOnClick(object : OnMapClickInterface {override fun onMapClick() {var bundle = bundleOf(CommonUtils.Chat.LOCATION_LATITUDE to chatBean.latitude, CommonUtils.Chat.LOCATION_LONGITUDE to chatBean.longitude)Navigation.findNavController(chat_item_me_mapview).navigate(R.id.action_baidu_map_details, bundle)}})chat_item_me_mapview.load(chatBean.latitude, chatBean.longitude)} else if(chatBean.contentType == ChatBean.CONTENT_TYPE_REDPACKET){//红包chat_item_me_redpacket.visibility = View.VISIBLEchat_item_me_img.visibility = View.GONEchat_item_me_content_layout.visibility = View.GONEchat_item_me_voice_layout.visibility = View.GONEchat_item_me_video.visibility = View.GONEchat_item_me_mapview.visibility = View.GONEchat_item_me_transfer.visibility = View.GONE//点击红包TagUtils.d("查看自己发送的红包")chat_item_me_redpacket.setOnClickListener {var bundle = bundleOf(CommonUtils.QRCommon.BALANCE to chatBean.content.toFloat(),CommonUtils.QRCommon.TO_USER to chatBean.toAccount,CommonUtils.QRCommon.FROM_ACCOUNT to chatBean.fromAccount)Navigation.findNavController(it)?.navigate(R.id.action_redpacket_success, bundle)}} else if(chatBean.contentType == ChatBean.CONTENT_TYPE_TRANSFER){//转账chat_item_me_redpacket.visibility = View.GONEchat_item_me_img.visibility = View.GONEchat_item_me_content_layout.visibility = View.GONEchat_item_me_voice_layout.visibility = View.GONEchat_item_me_video.visibility = View.GONEchat_item_me_mapview.visibility = View.GONEchat_item_me_transfer.visibility = View.VISIBLEtransfer_me_balance.text = "${chatBean.content}"//点击红包TagUtils.d("查看自己发送的转账")chat_item_me_transfer.setOnClickListener {var bundle = bundleOf(CommonUtils.QRCommon.TO_USER to chatBean.toAccount,CommonUtils.Chat.MESSAGE_ID to chatBean.messageId,CommonUtils.QRCommon.TRANSFER_BALANCE to chatBean.content)Navigation.findNavController(it).navigate(R.id.action_transfer_details, bundle)}}}
}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_38564.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VauditDemo靶场代码审计

靶场搭建 将下载好的VAuditDemo_Debug目录复制到phpstudy的www目录下&#xff0c;然后将其文件名字修改成VAuditDemo&#xff0c;当然你也可以修改成其他的 运行phpstudy并且访问install目录下的install.php&#xff0c;这里我访问的是http://127.0.0.1/VAuditDemo/install/in…

竞赛——【蓝桥杯】2022年12月第十四届蓝桥杯模拟赛第二期C/C++

1、最小的2022 问题描述 请找到一个大于 2022 的最小数&#xff0c;这个数转换成二进制之后&#xff0c;最低的 6 个二进制为全为 0 。 请将这个数的十进制形式作为答案提交。 答案提交 这是一道结果填空的题&#xff0c;你只需要算出结果后提交即可。本题的结果为一个整数…

Java学习之继承练习题

目录 第一题 代码 输出流程分析 运行结果 考察知识点 第二题 代码 流程分析 运行结果 第三题 题目要求 我的代码 代码改进 第一题 代码 package com.hspedu.extends_.exercise;public class ExtendsExercise01 {public static void main(String[] args) {B b new …

Sentinel-2(哨兵2数据介绍)

哥白尼 Sentinel-2&#xff08;哨兵 2&#xff09;计划是一个由两颗相同的 Sentinel-2 极轨卫星组成的星座&#xff0c;两颗卫星相位差 180&#xff0c;运行在平均高度 786 km 的太阳同步轨道上。每颗卫星在其轨道上的位置由双频全球导航卫星系统&#xff08;GNSS&#xff09;接…

ggrcs 包2.4绘制RCS(限制立方样条图)实际操作演示(1)

ggrcs 包2.4版本已经发布一段时间了&#xff0c;大概几个月了吧&#xff0c;收到不少好评&#xff0c; 没听说太大的问题&#xff0c;最主要的问题有两个&#xff1a; 1.是说变量不是数字变量。 2.是说数据超过10万&#xff0c;无法处理 第一个问题非常好处理&#xff0c;这…

R语言MCMC:Metropolis-Hastings采样用于回归的贝叶斯估计

全文链接&#xff1a;http://tecdat.cn/?p19664 MCMC是从复杂概率模型中采样的通用技术。蒙特卡洛马尔可夫链Metropolis-Hastings算法&#xff08;点击文末“阅读原文”获取完整代码数据&#xff09;。问题如果需要计算有复杂后验pdf p&#xff08;θ| y&#xff09;的随机变量…

简单聊聊什么是react-redux,它能解决哪些问题

或许 在大多数人眼中 redux是一个相对复查很多的知识点 但确实如果你熟悉了流程 其实也比较简单的 redux是一个数据管理方案 我们先来举个例子 目前我们知道 react中有两种组件数据通信的方式 分别是 props 父传子 定义事件 子传父 通过事件将自己的数据传给父级 那如果是兄弟…

领悟《信号与系统》之 周期信号的傅里叶变换计算

周期信号的傅里叶变换计算一、周期信号的傅里叶变换存在的条件二、周期信号的傅里叶变换例题&#xff1a;一、周期信号的傅里叶变换存在的条件 典型非周期信号&#xff08;如指数信号&#xff0c;矩形信号等&#xff09;都是满足绝对可积&#xff08;或绝对可和&#xff09;条…

一种高选择性和灵敏的荧光生物标记物,可用于标记碱性磷酸酶 (ALP),5-FAM-Alkyne,510758-19-7,荧光生物标记物

【中文名称】5-羧基荧光素-炔烃【英文名称】 FAM alkyne,5-isomer&#xff0c;5-FAM alkyne【结 构 式】 【CAS号】510758-19-7 【分子式】C24H15NO6【分子量】413.39【基团】炔基基团【纯度】95%【规格标准】5mg&#xff0c;10mg&#xff0c;25mg&#xff0c;包装灵活&#x…

使用PyTorch实现简单的AlphaZero的算法(3):神经网络架构和自学习

神经网络架构和训练、自学习、棋盘对称性、Playout Cap Randomization&#xff0c;结果可视化 从我们之前的文章中&#xff0c;介绍了蒙特卡洛树搜索 (MCTS) 的工作原理以及如何使用它来获得给定棋盘状态的输出策略。我们也理解神经网络在 MCTS 中的两个主要作用&#xff1b;通…

xss-labs/level9

这一关界面感觉跟上一关很像 所以我们注入上一关的为编码的答案 javascript:alert(xss) 没能弹窗 查看源代码 他说我输入的链接不合法 我压根没有输入链接 我觉得后台应该是做了一个条件的判断 应该是要有链接才会在第二处输出点回显我们的输入 根据上面的猜测 我们构造如下…

Java.Integer.bitCount(int)源码解析

bitCount前言一、由易到难&#xff0c;头脑热身二、简单优化&#xff0c;一题多解三、分治优化四、bitCount(int)源码优化总结参考文献前言 如何求解一个二进制中1的个数&#xff1f;有常规的O(N)法&#xff0c;还有基于分治的O(logN)&#xff0c;即Java的bitCount(int)方法。…

我们为什么喜欢看疯狂科学家开飞艇?

很多人可能不是科幻迷&#xff0c;也在日常生活中接触过蒸汽朋克。为什么呢&#xff1f;很简单——蒸汽朋克几乎无处不在。相比其他科幻流派&#xff0c;蒸汽朋克可能算是最“出圈”的一种。简单地说&#xff0c;蒸汽朋克是一种科幻小说类型&#xff0c;由“蒸汽 ”(steam)和“…

《论文阅读》DeepSFM: Structure From Motion Via Deep Bundle Adjustment

留个笔记自用 DeepSFM: Structure From Motion Via Deep Bundle Adjustment 做什么 首先是最基础的&#xff0c;Structure-from-Motion&#xff08;SFM&#xff09;&#xff0c;SFM可以简单翻译成运动估计&#xff0c;是一种基于dui8序列图片进行三维重建的算法。简单来说就…

移动跨平台开发跨家选型参考建议

从 iPhone 诞生至今&#xff0c;智能手机风靡全球已将近20年&#xff0c;智能手机操作系统 iOS 和 Android 也成为当仁不让的顶流般的存在&#xff0c;而作为其背后的灵魂&#xff0c;移动应用也随着技术的发展已经越来越丰富。如果从技术层面来讲&#xff0c;移动 App 也从最开…

(1)点云库PCL学习——点云的格式、PCD文件的打开和显示

1、主要参考 (1)格式说明&#xff1a; 点云库PCL学习——点云的格式、PCD文件的打开和显示 ROS知识&#xff1a;点云文件.pcd格式_无水先生的博客-CSDN博客_pcd文件 &#xff08;2&#xff09;点云滤波&#xff0c;对nan的滤波 Python点云数据处理(三)滤波与RANSAC分割 - …

省 市 县 三级联动

大纲 一、导入省市县数据表(t_region) 二、引入jar包 三、导入所需util类&#xff08;整体框架&#xff09; 四、编写代码 1、配置数据库相关信息(数据库名、用户名、密码) config.propreties #oracle9i #driveroracle.jdbc.driver.OracleDriver #urljdbc:oracle:thin:loca…

jsp393学生宿舍管理系统mysql

两个权限 管理员和 学生 1. 学生信息管理 添加学生信息&#xff08;学生号&#xff0c;姓名 院系 班级入学日期 &#xff09;修改学生信息 学生退宿舍&#xff08;可以删除指定的学生也可以成批删除&#xff09; 2. 宿舍信息管理 宿舍的基本信息&#xff08;公寓数 宿舍…

第五届“强网”拟态防御国际精英挑战赛——特邀战队篇

第五届“强网”拟态防御国际精英挑战赛即将在南京隆重开赛&#xff01;本届大赛面向全球顶尖CTF战队&#xff0c;在创新应用场景与技术的基础上&#xff0c;拓展升级赛道&#xff0c;全面覆盖典型网络设备。大赛汇集国内外60支精英战队&#xff0c;参赛阵容、数量再创新高。 本…

科普下抖音的规则,为什么别人的内容很容易火,而我的很难?

今天给大家科普下抖音的规则&#xff0c;为什么别人的内容很容易火&#xff0c;而我的很难&#xff1f; 上一篇给大家讲了现在做抖音还来得及么&#xff1f;肯定的回答&#xff0c;一直都来得及。 既然来得及&#xff0c;那么我们怎么才能做好抖音呢&#xff1f; 在我看来&a…