Xigong93/ExpandableRecyclerView

新版本显示不全,旧版本没这个问题

smallgirl opened this issue · 6 comments

71612163741_ pic
81612163742_ pic
如图,旧版本完全正常

方便提供一下adapter的伪代码吗?

adapter 的每个item 高度不一样,是不是这个导致的?

//最终小节的父节点,可以有视频
private class ParentFinalVH(val itemBinding: ItemSegmentChildBinding) :
    RecyclerView.ViewHolder(itemBinding.root)

//普通父节点,可折叠
private class ParentNotFinalVH(val itemBinding: ItemSegmentParentBinding) :
    RecyclerView.ViewHolder(itemBinding.root)

//最终小节子节点,没有下一级,可能没有视频
private class ChildFinalVH(val itemBinding: ItemSegmentChildBinding) :
    RecyclerView.ViewHolder(itemBinding.root)

//非最终小节子节点,没有视频,有下一级
private class ChildNotFinalVH(val itemBinding: ItemSegmentMiddleBinding) :
    RecyclerView.ViewHolder(itemBinding.root)

class SegmentAdapter(
    var onItemClick: (
        lesson: Lesson, itemShowDownload: Boolean, groupPosition: Int,
        childPosition: Int
    ) -> Unit
) : ExpandableAdapter<RecyclerView.ViewHolder>() {

    companion object {
        private const val PARENT_FINAL_NODE = 11//父节点最终小节
        private const val PARENT_NOT_FINAL_NODE = 12//父节点不是最终小节
        private const val CHILD_FINAL_NODE = -11
        private const val CHILD_NOT_FINAL_NODE = -12
    }


    //数据结构为两层树结构,第二层一下都会扁平按顺序放在第一层的children中
    /**
     *  parent1
     *   |- child1.1
     *   |- child1.1.1
     *   |- child1.1.2
     *  parent2
     *   |- child2.1
     *   |- child2.2
     *   |- child2.2.1
     *   ...
     */
    var list: MutableList<SegmentWrappedLesson> = mutableListOf()
    var itemShowDownload: Boolean = false//是否下载标记
    fun setSegments(list: List<SegmentWrappedLesson>) {
        this.list.clear()
        this.list.addAll(list)
        setDataInternal()
        notifyDataSetChanged()
    }

    override fun getGroupItemViewType(groupPosition: Int) =
        if (list[groupPosition].lesson.type == 1)//判断是否是最终小节
            PARENT_FINAL_NODE
        else
            PARENT_NOT_FINAL_NODE

    override fun getChildItemViewType(groupPosition: Int, childPosition: Int) =
        if (list[groupPosition].children?.get(childPosition)?.type ?: 0 == 1)
            CHILD_FINAL_NODE
        else
            CHILD_NOT_FINAL_NODE


    //父目录vh
    override fun onCreateGroupViewHolder(
        viewGroup: ViewGroup,
        viewType: Int
    ): RecyclerView.ViewHolder {
        val inflater = LayoutInflater.from(viewGroup.context)
        return if (viewType == PARENT_NOT_FINAL_NODE)
            ParentNotFinalVH(
                ItemSegmentParentBinding.inflate(inflater, viewGroup, false)
            )
        else
            ParentFinalVH(ItemSegmentChildBinding.inflate(inflater, viewGroup, false))
    }


    //子目录vh
    override fun onCreateChildViewHolder(
        viewGroup: ViewGroup,
        viewType: Int
    ): RecyclerView.ViewHolder {
        val inflater = LayoutInflater.from(viewGroup.context)
        return if (viewType == CHILD_NOT_FINAL_NODE)
            ChildNotFinalVH(
                ItemSegmentMiddleBinding.inflate(inflater, viewGroup, false)
            )
        else
            ChildFinalVH(ItemSegmentChildBinding.inflate(inflater, viewGroup, false))
    }


    override fun onBindChildViewHolder(
        holder: RecyclerView.ViewHolder,
        groupPosition: Int,
        childPosition: Int,
        payloads: List<Any>
    ) {
        val lesson = list[groupPosition].children?.get(childPosition)
        lesson?.let {
            (holder as? ChildNotFinalVH)?.apply {//非最终小节,只展示标题
                setIndentation(itemBinding.lessonName, lesson.treeLevel)//子节点设置层级缩进
                itemBinding.lessonName.text = lesson.lessonName
            }
            (holder as? ChildFinalVH)?.apply {//最终小节,可能有视频,可能没视频
                setIndentation(itemBinding.lessonName, lesson.treeLevel)//子节点设置层级缩进
                setSegmentInfo(holder.itemBinding, lesson, groupPosition, childPosition)
            }
        }
    }


    override fun onBindGroupViewHolder(
        holder: RecyclerView.ViewHolder,
        groupPosition: Int,
        expand: Boolean,
        payloads: List<Any>
    ) {

        val lesson = list[groupPosition].lesson
        (holder as? ParentNotFinalVH)?.apply {//普通父节点
            itemBinding.lessonName.text = lesson.lessonName
            if (payloads.isEmpty()) {
                itemBinding.lessonExpandIv.rotation =
                    if (isExpand(groupPosition)) 0f
                    else 180f
            }
        }
        (holder as? ParentFinalVH)?.apply {//最终父节点,可能有视频,
            setSegmentInfo(holder.itemBinding, lesson, groupPosition, -1)
        }
    }

    //最终小节,可能是父节点,可能是子节点,设置lesson信息
    @SuppressLint("SetTextI18n")
    private fun setSegmentInfo(
        binding: ItemSegmentChildBinding,
        lesson: Lesson,
        groupPosition: Int,
        childPosition: Int,
    ) {
        binding.lesson = lesson
        //有视频
        if (lesson.isHasVideo) {
            //播放,下载状态
            binding.lessonPlayIv.visibility = View.VISIBLE
            binding.lessonProgressBar.progress = lesson.rate.toInt()
            binding.lessonProgress.text = "${
                TimeUtils.getPlayTimeHour(lesson.playTime.toLong(), false, true)
            },已学${lesson.rate.toInt()}%"

            if (itemShowDownload) {
                setDownloadState(lesson.downloadState, binding.lessonPlayIv)
            } else {
                binding.lessonPlayIv.setImageResource(R.drawable.ic_catalog_play)
            }
            //最近学习标记
            binding.studyHere.visibility =
                if (lesson.lastListen == 1 && !itemShowDownload) View.VISIBLE else View.GONE
            //又是视频的才可以点击下载和播放
            binding.itemSegmentLayout.setOnClickListener {
                onItemClick(
                    lesson,
                    itemShowDownload,
                    groupPosition,
                    childPosition
                )
            }

        } else {//没有视频
            //隐藏播放,下载状态
            binding.lessonPlayIv.visibility = View.GONE
            //最近学习标记
            binding.studyHere.visibility = View.GONE
            binding.itemSegmentLayout.setOnClickListener(null)
        }
        binding.executePendingBindings()
    }


    //设置下载状态
    private fun setDownloadState(state: Int, downImg: AppCompatImageView) {
        when (state) {
            DownloadConst.DownloadState.TASK_STATE_WAITING -> {
                downImg.setImageResource(R.drawable.ic_download_waiting)
            }
            DownloadConst.DownloadState.TASK_STATE_DOWNLOADING -> {
                downImg.setImageResource(R.drawable.ic_download_ing)
            }
            DownloadConst.DownloadState.TASK_STATE_PAUSE -> {
                downImg.setImageResource(R.drawable.ic_download_pause)
            }
            DownloadConst.DownloadState.TASK_STATE_FAIL -> {
                downImg.setImageResource(R.drawable.ic_download_fail)
            }
            DownloadConst.DownloadState.TASK_STATE_COMPLETE -> {
                downImg.setImageResource(R.drawable.ic_download_success)
            }
            else -> {
                downImg.setImageResource(R.drawable.ic_download_none)
            }
        }
    }

    //父布局必须ConstraintLayout的textview
//    <!--根据不同的层级标题缩进-->
//    <!--根据UI图:第x章不缩进,x.x不缩进,x.x.x直到最终节都缩进-->
    private fun setIndentation(lessonNameTv: TextView, indentation: Int) {
        //设置层级缩进
        with(lessonNameTv.layoutParams as ConstraintLayout.LayoutParams) {
            this.marginStart = PixelUtils.dp2px(
                lessonNameTv.context,
                if (indentation > 1) (indentation - 1) * 14f else 0f
            )
            lessonNameTv.layoutParams = this
        }
    }

    override fun onGroupViewHolderExpandChange(
        holder: RecyclerView.ViewHolder,
        groupPosition: Int,
        animDuration: Long,
        expand: Boolean
    ) {
        val arrowImage = when {
            holder as? ParentNotFinalVH != null -> holder.itemBinding.lessonExpandIv
            else -> return
        }
        setArrowSpin(arrowImage, expand, animDuration, true)
    }

    //设置目录折叠的三角方向
    private fun setArrowSpin(
        view: View?,
        isExpand: Boolean,
        animDuration: Long,
        isAnimate: Boolean
    ) {
        view ?: return

        if (isExpand) {
            if (isAnimate) {
                ObjectAnimator.ofFloat(view, View.ROTATION, 0f)
                    .setDuration(animDuration)
                    .start()
            } else {
                view.rotation = 0f
            }
            // 不要使用这种动画,Item离屏之后,动画会取消
//            arrowImage.animate()
//                .setDuration(animDuration)
//                .rotation(0f)
//                .start()
        } else {
            if (isAnimate) {
                ObjectAnimator.ofFloat(view, View.ROTATION, 180f)
                    .setDuration(animDuration)
                    .start()
            } else {
                view.rotation = 180f
            }
        }
    }

    override fun getGroupCount(): Int {
        return list.size
    }

    override fun getChildCount(groupPosition: Int): Int {
        return list[groupPosition].children?.size ?: 0
    }
}

上面是旧版本的adapter显示正常,新版的是只是把RecyclerView.ViewHolder 换成ExpandableAdapter.ViewHolder 就显示不全,有大片空白,还有文字显示一半的情况。

谢谢,我已经复现了,马上改一下

你好,刚刚发了一下0.8.6已经修复了这个问题,请再试一下。

可以了 谢谢。