美文网首页Android开发经验谈Android开发
当item超过一定数量,如何正确的设置RecyclerView的

当item超过一定数量,如何正确的设置RecyclerView的

作者: 一个老码农 | 来源:发表于2021-01-15 22:14 被阅读0次

    有时候,我们会遇到这种需求:一个线性的列表布局,当item量很少的时候,就是wrap_content直接展示完所有item,但是当item数量超过某个数时就要固定高度,让其变成可滑动展示更多的item。所以我们第一个想法就是用RecyclerView,应该没人会用ListView或自己写个自定义ViewGroup吧。

    但是当我们使用RecyclerView+maxHeight的时候,会发现其实maxHeight是不起作用的。

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recyclerView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:maxHeight="100dp" />
    复制代码
    
    image

    那么为什么会造成这种原因呢?其实在我之前写的一篇博客也提到过:RecyclerViewonMeasure的转交给了LayoutManager,并且LayoutManager里面有个isAutoMeasureEnabled()方法用来配置LayoutManager是否开启自测量。我们常用的LinearLayoutManagerGridLayoutManager都是默认返回true的。

    博客地址

    实现思路

    所以实现思路就很简单了:设定一个maxLine参数,当RecyclerViewitemCount小于这个值isAutoMeasureEnabled()都是返回true,让LayoutManager自测量。当itemCount大于maxLine时就重写onMeasure方法,在里面去设置RecyclerView限定宽高

    代码实现

    class MaxLineLinearLayoutManager : LinearLayoutManager {
    
        private var mMaxLine = 0
    
        constructor(
            context: Context?,
            maxLine: Int
        ) : super(context) {
            Helper.checkMaxCount(maxLine)
            this.mMaxLine = maxLine
        }
    
        constructor(
            context: Context?,
            orientation: Int,
            reverseLayout: Boolean,
            maxLine: Int
        ) : super(context, orientation, reverseLayout) {
            Helper.checkMaxCount(maxLine)
            this.mMaxLine = maxLine
        }
    
        override fun onMeasure(
            recycler: RecyclerView.Recycler,
            state: RecyclerView.State,
            widthSpec: Int,
            heightSpec: Int
        ) {
            if (itemCount <= mMaxLine || itemCount == 0) {
                super.onMeasure(recycler, state, widthSpec, heightSpec)
                return
            }
    
            val child = recycler.getViewForPosition(0)
    
            //
            addView(child)
            measureChildWithMargins(child, 0, 0)
            val itemWidth = getDecoratedMeasuredWidth(child)
            val itemHeight = getDecoratedMeasuredHeight(child)
            removeAndRecycleView(child, recycler)
    
            val widthMode = View.MeasureSpec.getMode(widthSpec)
            val heightMode = View.MeasureSpec.getMode(heightSpec)
            var width = 0
            var height = 0
    
            if (orientation == HORIZONTAL) {
                height = if (heightMode == View.MeasureSpec.EXACTLY) {
                    View.MeasureSpec.getSize(heightSpec)
                } else {
                    itemHeight
                }
                width = itemWidth * mMaxLine
            } else {
                width = if (widthMode == View.MeasureSpec.EXACTLY) {
                    View.MeasureSpec.getSize(widthSpec)
                } else {
                    itemWidth
                }
                height = itemHeight * mMaxLine
            }
    
            setMeasuredDimension(width, height)
        }
    
        override fun isAutoMeasureEnabled(): Boolean {
            if (itemCount <= mMaxLine) {
                return super.isAutoMeasureEnabled()
            }
            return false
        }
    
    }
    复制代码
    

    代码很简单,应该不加注释也能看懂。如果看不懂的可以去看看我之前的那篇分析自定义LayoutManager的文章。

    博客地址

     recyclerView.layoutManager = MaxLineLinearLayoutManager(this, maxLine = 3)
    复制代码
    
    image

    作者:simplepeng
    链接:https://juejin.cn/post/6891899635296632846

    相关文章

      网友评论

        本文标题:当item超过一定数量,如何正确的设置RecyclerView的

        本文链接:https://www.haomeiwen.com/subject/tnkgaktx.html