• Kotlin高仿微信-第25篇-朋友圈-显示列表


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

    Kotlin高仿微信-项目实践58篇,点击查看详情

    效果图:

    实现代码:

    
    
    
        
    
    
            
    
                
    
                
    
                
            
    
        
    

    /**
     * Author : wangning
     * Email : maoning20080809@163.com
     * Date : 2022/5/23 16:00
     * Description : 朋友圈
     */
    class DiscoverMomentsFragment : BaseDataBindingFragment(), OnRefreshListener, OnLoadMoreListener {
    
        override fun getLayoutRes() = R.layout.wc_discover_moments
    
        private val momentsViewModel : MomentsViewModel by viewModels()
        private val userViewModel : UserViewModel by viewModels()
        private var navController: NavController? = null
        private val REQ_PICTURE_CODE = 101
        private val REQ_VIDEO_CODE = 102
    
        private var momentsAdapter : DiscoverMomentsAdapter? = null
    
        override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)
    
            if(!EventBus.getDefault().isRegistered(this)){
                EventBus.getDefault().register(this)
            }
    
            swipeToLoadLayout.setOnRefreshListener(this)
            swipeToLoadLayout.setOnLoadMoreListener(this)
    
            var account = DataStoreUtils.getAccount()
            userViewModel.getUserLocal(account)
            navController = findNavController()
    
            navController?.currentBackStackEntry?.savedStateHandle?.getLiveData(CommonUtils.Moments.PUBLISH_SUCCESS)?.observe(viewLifecycleOwner){
                TagUtils.d("朋友圈发布返回")
                if(it){
                    momentsViewModel.getMomentsListLocalEvent()
                }
            }
    
            TagUtils.d("朋友圈重新主页 ")
            var momentsList = mutableListOf()
            //第一行默认写入个人信息
            momentsList.add(MomentsBean())
            momentsAdapter = DiscoverMomentsAdapter(momentsList, PopupWindowClick())
    
            userViewModel.userBeanLocal.observe(viewLifecycleOwner){
                TagUtils.d("4朋友圈返回用户$it")
                if(it == null) return@observe
                momentsAdapter?.setUserBean(it)
            }
    
            //使用EventBus刷新数据
            momentsViewModel.getMomentsListLocalEvent()
            var linearLayoutManager = LinearLayoutManager(requireActivity())
            linearLayoutManager.orientation = LinearLayoutManager.VERTICAL
            swipe_target.layoutManager = linearLayoutManager
            swipe_target.adapter = momentsAdapter
    
            //先加载本地,然后刷新服务器的数据
            momentsViewModel.getMomentsListServerEvent()
        }
    
        @Subscribe(threadMode = ThreadMode.MAIN)
        fun onMessageCallback(momentsEventBean: MomentsEventBean) {
    
            if(momentsEventBean == null){
                return
            }
    
            if(momentsEventBean.list == null || momentsEventBean.list.size < 1){
                return
            }
    
            var list: MutableList = momentsEventBean.list
            if(momentsEventBean.type == MomentsEventBean.TYPE_LOCAL_LIST){
                var momentsList = mutableListOf()
                //第一行默认写入个人信息
                momentsList.add(MomentsBean())
                TagUtils.d("DiscoverFragment onMessageCallback 个数${list.size} ")
                momentsList.addAll(list)
                momentsAdapter?.refresh(momentsList)
            } else {
                CoroutineScope(Dispatchers.IO).launch {
                    //从服务器获取到数据,插入本地数据库
                    MomentsRepository.insertMomentListLocal(list)
                    //查询最新的刷新页面
                    momentsViewModel.getMomentsListLocalEvent()
                }
            }
        }
    
        override fun onDestroyView() {
            super.onDestroyView()
            TagUtils.d("DiscoverFragment onDestroyView")
            EventBus.getDefault().unregister(this)
        }
    
        inner class PopupWindowClick : WcOnItemClickInterface {
            override fun onItemClick(obj: Any) {
                showPopupWindow()
            }
        }
    
        private fun showPopupWindow(){
            var popupView = layoutInflater.inflate(R.layout.wc_moments_pop_view , moment_root, false)
            var popupWindow = PopupWindow(popupView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, true)
            popupWindow.showAtLocation(moment_root, Gravity.BOTTOM, 0, 0)
    
            var window = requireActivity().window
            //popupWindow在弹窗的时候背景半透明
            val params = window.attributes
            params.alpha = 0.5f
            window.attributes = params
            popupWindow.setOnDismissListener {
                params.alpha = 1.0f
                window.attributes = params
            }
    
            //拍照小视频
            popupView.findViewById(R.id.moments_pop_video).setOnClickListener {
                popupWindow.dismiss()
                var bundle = bundleOf(CameraFragment.TYPE_ENTER to CameraFragment.TYPE_MOMENT)
                navController?.navigate(R.id.action_svideo_camera, bundle)
            }
    
            //选择相册
            popupView.findViewById(R.id.moments_pop_album).setOnClickListener {
                popupWindow.dismiss()
                openAblum()
            }
    
            //选择小视频
            popupView.findViewById(R.id.moments_pop_svideo).setOnClickListener {
                popupWindow.dismiss()
                openVideo()
            }
    
            //取消
            popupView.findViewById(R.id.moments_pop_cancel).setOnClickListener {
                popupWindow.dismiss()
            }
    
        }
    
        override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
            super.onActivityResult(requestCode, resultCode, data)
    
            if (requestCode == REQ_PICTURE_CODE && data != null) {
                val images = data.getStringArrayListExtra(ImageSelector.SELECT_RESULT)
                val isCameraImage = data.getBooleanExtra(ImageSelector.IS_CAMERA_IMAGE, false)
                TagUtils.d("ImageSelector", "是否是拍照图片:" + isCameraImage)
                images?.map {
                    TagUtils.d("返回图片:${it}")
                }
                if(images != null && images.size > 0) {
                    var bundle = bundleOf(CommonUtils.Moments.TYPE_NAME to CommonUtils.Moments.TYPE_PICTURE, CommonUtils.Moments.TYPE_IMAGE_PATH to images)
                    navController?.navigate(R.id.action_moments_publish, bundle)
                } else {
                    TagUtils.d("请选择图片")
                }
            } else if (requestCode == REQ_VIDEO_CODE && resultCode == RESULT_OK && null != data) {
                var selectedVideo = data.getData()!!
                var filePathColumn = arrayOf(MediaStore.Video.Media.DATA)
                var cursor : Cursor? = requireActivity().contentResolver.query(selectedVideo, filePathColumn, null, null, null);
                cursor?.moveToFirst();
    
                var columnIndex : Int? = cursor?.getColumnIndex(filePathColumn[0]);
                var videoPath = cursor?.getString(columnIndex!!);
                cursor?.close();
                TagUtils.d("选择小视频路径:${videoPath}")
                var bundle = bundleOf(CommonUtils.Moments.TYPE_NAME to CommonUtils.Moments.TYPE_VIDEO, CommonUtils.Moments.TYPE_VIDEO_PATH to videoPath)
                navController?.navigate(R.id.action_moments_publish, bundle)
            }
        }
    
        fun openAblum(){
            // 打开相册
            ImageSelector.builder()
                .useCamera(false) // 设置是否使用拍照
                .setSingle(false) //设置是否单选
                .canPreview(true) //是否点击放大图片查看,,默认为true
                .start(this,REQ_PICTURE_CODE)
    
        }
    
        //选择小视频
        fun openVideo(){
            val i = Intent(Intent.ACTION_PICK, MediaStore.Video.Media.EXTERNAL_CONTENT_URI)
            startActivityForResult(i, REQ_VIDEO_CODE)
        }
    
        override fun onRefresh() {
            CoroutineScope(Dispatchers.Main).launch {
                delay(200)
                swipeToLoadLayout.isRefreshing = false
            }
        }
    
        override fun onLoadMore() {
            CoroutineScope(Dispatchers.Main).launch {
                delay(200)
                swipeToLoadLayout.isLoadingMore = false
            }
        }
    
    
    }

    /**
     * Author : wangning
     * Email : maoning20080809@163.com
     * Date : 2022/5/26 17:55
     * Description : 朋友圈适配器
     */
    class DiscoverMomentsAdapter(var list : MutableList, var userClick : WcOnItemClickInterface) : RecyclerView.Adapter(){
    
        private var userBean : UserBean? = null
    
        override fun getItemCount() = list.size
    
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DiscoverMomentsHolder {
            var view = LayoutInflater.from(parent.context).inflate(R.layout.wc_discover_moments_item, parent, false)
            return DiscoverMomentsHolder(view)
        }
    
        override fun onBindViewHolder(holder: DiscoverMomentsHolder, position: Int) {
    
            //TagUtils.d("朋友圈position = ${position} , ${userBean}" )
            if(position == 0){
                //朋友圈个人头像信息
                holder.personalView.visibility = View.VISIBLE
                holder.momentsView.visibility = View.GONE
                userBean?.let {
                    holder.personalView.process(it, userClick)
                }
            } else {
                holder.personalView.visibility = View.GONE
                holder.momentsView.visibility = View.VISIBLE
                holder.momentsView.process(list.get(position))
            }
        }
    
        fun setUserBean(userBean: UserBean) {
            this.userBean = userBean
            notifyDataSetChanged()
        }
    
        //下拉刷新
        fun refresh(list : MutableList){
            this.list = list
            notifyDataSetChanged()
        }
    
        //加载更多
        fun add(list : MutableList){
            this.list.addAll(list)
            notifyDataSetChanged()
        }
    
        class DiscoverMomentsHolder(itemView : View) : RecyclerView.ViewHolder(itemView) {
    
            var momentsView  = itemView.findViewById(R.id.discover_moments_item_view)
            var personalView  = itemView.findViewById(R.id.discover_moments_item_personal_view)
    
        }
    }
    /**
     * Author : wangning
     * Email : maoning20080809@163.com
     * Date : 2022/5/26 15:29
     * Description : 朋友圈自定义view
     */
    class DiscoverMomentsView : RelativeLayout{
    
        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_discover_moments_view, this)
        }
    
    
        fun process(momentsBean: MomentsBean){
            momentsBean?.let {
                discover_moments_content.text = it.content
                discover_moments_time.text = CommonUtils.Date.getCurrentDate(it.addTime)
                BaseUtils.showAvatar(momentsBean.account, discover_moments_icon, discover_moments_name)
    
                if(it.type == CommonUtils.Moments.TYPE_PICTURE){
                    //图片
                    discover_moments_recyclerview.visibility = View.VISIBLE
                    discover_moments_video.visibility = View.GONE
                    discover_moments_video_icon.visibility = View.GONE
    
                    //TagUtils.d("朋友圈图片:" + it.images)
                    var imagesList = it.images.split(CommonUtils.Moments.FILE_PATH_MARK)
                    var adapter = MomentsPublishAdapter(2, imagesList, object : WcOnItemClickInterface{
                        override fun onItemClick(obj: Any) {
                            TagUtils.d("点击:${obj}")
                            var imagePath = obj as String
                            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(discover_moments_recyclerview).navigate(R.id.action_svideo_play, bundle)
                        }
                    })
                    var linearLayoutManager = GridLayoutManager(context , 3)
                    //linearLayoutManager.orientation = LinearLayoutManager.HORIZONTAL
                    discover_moments_recyclerview.layoutManager = linearLayoutManager
                    discover_moments_recyclerview.adapter = adapter
    
    
                } else if(it.type == CommonUtils.Moments.TYPE_VIDEO){
                    //小视频
                    discover_moments_recyclerview.visibility = View.GONE
                    if(File(momentsBean.videoLocal).exists()){
                        TagUtils.d("本地小视频存在:${momentsBean.videoLocal}")
                        //小视频文件存在, 直接显示播放
                        discover_moments_video_icon.visibility = View.GONE
                        discover_moments_video.visibility = View.VISIBLE
                        playVideo(momentsBean.videoLocal)
    
                        discover_moments_video.setOnClickListener {
                            showVideo(discover_moments_video, momentsBean.videoLocal)
                        }
    
                    } else {
                        //小视频文件不存在, 默认先显示缩略图, 然后下载
                        discover_moments_video_icon.visibility = View.VISIBLE
                        discover_moments_video.visibility = View.GONE
                        GlideUtils.load(discover_moments_video_icon, CommonUtils.Base.getReallyImage(momentsBean.images))
    
                        var videoUrl = CommonUtils.Moments.getReallyImageUrl(momentsBean.video)
                        TagUtils.d("小视频地址:${momentsBean.video} , ${videoUrl}")
                        TagUtils.d("小视频缩略图:${momentsBean.images} , ${CommonUtils.Base.getReallyImage(momentsBean.images)}")
                        var  videoFile = FileUtils.getBaseFile(momentsBean.video)
                        VideoDownloadManager.download(videoUrl, videoFile, object : VideoDownloadInter{
                            override fun onDone(filePath: String) {
                                TagUtils.d("小视频下载完成:${filePath}")
                                CoroutineScope(Dispatchers.Main).launch {
                                    discover_moments_video_icon.visibility = View.GONE
                                    discover_moments_video.visibility = View.VISIBLE
                                    momentsBean.videoLocal = filePath
                                    playVideo(filePath)
    
                                    CoroutineScope(Dispatchers.IO).launch {
                                        //更新到本地数据库
                                        MomentsRepository.updateMomentLocal(momentsBean)
                                    }
    
                                    discover_moments_video.setOnClickListener {
                                        showVideo(discover_moments_video, momentsBean.videoLocal)
                                    }
    
                                }
                            }
    
                            override fun onError() {
                                CoroutineScope(Dispatchers.Main).launch {
                                    TagUtils.d("小视频下载失败:${momentsBean.video}")
                                }
                            }
    
                            override fun onProgress(process: Int) {
    
                            }
                        })
                    }
    
                } else {
                    //文字
                    discover_moments_recyclerview.visibility = View.GONE
                    discover_moments_video.visibility = View.GONE
                }
            }
        }
    
        //点击查看小视频
        private fun showVideo(view: View, videoPath : String){
            var bundle = bundleOf(CommonUtils.Moments.TYPE_VIDEO_PATH to videoPath,
                CommonUtils.Moments.TYPE_NAME to CommonUtils.Moments.TYPE_VIDEO,
                CommonUtils.Chat.IS_HIDE_CONFIRM to true)
            Navigation.findNavController(view).navigate(R.id.action_svideo_play, bundle)
        }
    
        /**
         * 播放小视频
         * @param filePath String
         */
        private fun playVideo(filePath : String){
            discover_moments_video.setVideoPath(filePath)
            discover_moments_video.requestFocus()
            discover_moments_video.start()
            discover_moments_video.setOnCompletionListener {
                discover_moments_video.start()
            }
        }
    
    }

  • 相关阅读:
    screen对象
    FinOps能力成熟度模型启动,灵雀云助力云原生降本增效标准制定
    java 多excel下载 打成zip压缩包 程序中创建文件 响应到浏览器
    DP好题分类
    云IDE开发环境和使用体验
    kotlin 转 Java
    华融湘江银行正式更名湖南银行,周晖将出任该行行长一职
    Qt编写物联网管理平台45-采集数据转发
    Redis的数据删除策略
    面试逻辑题,有8个小球和一个天平,一个小球偏重,其它小球一样重,问最少称几次可以找出那个重球?
  • 原文地址:https://blog.csdn.net/maoning20080808/article/details/128117104