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

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

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

   

        android:id="@+id/recyclerView"

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        android:maxHeight="100dp" />


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

实现思路

所以实现思路就很简单了:设定一个maxLine参数,当RecyclerView的itemCount小于这个值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

    }

}

代码很简单,应该不加注释也能看懂。


当item超过一定数量,如何正确的设置RecyclerView的maxHeight_第1张图片

你可能感兴趣的:(当item超过一定数量,如何正确的设置RecyclerView的maxHeight)