• RecyclerView 加入一个滑动控件bug处理 GridView只显示第一行


    如果RecyclerView 多样式布局,比如要加入一个展示多个图看的需求。自然想到用gridview给嵌套一下。

    想法当然是可以的,但是发现,嵌套出来的效果是,gridview只显示一行。

    想想原因 应该是给的高度不够,自然,计算高度肯定要从onMeasure入手。

    看下onMeasure计算过程。

    specMode中决定的,specMode一共有三种可能:

    MeasureSpec.EXACTLY:父视图希望子视图的大小应该是specSize中指定的。

    MeasureSpec.AT_MOST:子视图的大小最多是specSize中指定的值,也就是说不建议子视图的大小超过specSize中给定的值。

    MeasureSpec.UNSPECIFIED:我们可以随意指定视图的大小。

    那么,gridview的父节点是RecyclerView 自然他本身高度就是不确定的。

    我们再看一下源码

     @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            // Sets up mListPadding
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    
            int widthMode = MeasureSpec.getMode(widthMeasureSpec);
            int heightMode = MeasureSpec.getMode(heightMeasureSpec);
            int widthSize = MeasureSpec.getSize(widthMeasureSpec);
            int heightSize = MeasureSpec.getSize(heightMeasureSpec);
    
            if (widthMode == MeasureSpec.UNSPECIFIED) {
                if (mColumnWidth > 0) {
                    widthSize = mColumnWidth + mListPadding.left + mListPadding.right;
                } else {
                    widthSize = mListPadding.left + mListPadding.right;
                }
                widthSize += getVerticalScrollbarWidth();
            }
            
            int childWidth = widthSize - mListPadding.left - mListPadding.right;
            boolean didNotInitiallyFit = determineColumns(childWidth);
    
            int childHeight = 0;
            int childState = 0;
    
            mItemCount = mAdapter == null ? 0 : mAdapter.getCount();
            final int count = mItemCount;
            if (count > 0) {
                final View child = obtainView(0, mIsScrap);
    
                AbsListView.LayoutParams p = (AbsListView.LayoutParams) child.getLayoutParams();
                if (p == null) {
                    p = (AbsListView.LayoutParams) generateDefaultLayoutParams();
                    child.setLayoutParams(p);
                }
                p.viewType = mAdapter.getItemViewType(0);
                p.isEnabled = mAdapter.isEnabled(0);
                p.forceAdd = true;
    
                int childHeightSpec = getChildMeasureSpec(
                        MeasureSpec.makeSafeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec),
                                MeasureSpec.UNSPECIFIED), 0, p.height);
                int childWidthSpec = getChildMeasureSpec(
                        MeasureSpec.makeMeasureSpec(mColumnWidth, MeasureSpec.EXACTLY), 0, p.width);
                child.measure(childWidthSpec, childHeightSpec);
    
                childHeight = child.getMeasuredHeight();
                childState = combineMeasuredStates(childState, child.getMeasuredState());
    
                if (mRecycler.shouldRecycleViewType(p.viewType)) {
                    mRecycler.addScrapView(child, -1);
                }
            }
            
            if (heightMode == MeasureSpec.UNSPECIFIED) {
                heightSize = mListPadding.top + mListPadding.bottom + childHeight +
                        getVerticalFadingEdgeLength() * 2;
            }
    
            if (heightMode == MeasureSpec.AT_MOST) {
                int ourSize =  mListPadding.top + mListPadding.bottom;
               
                final int numColumns = mNumColumns;
                for (int i = 0; i < count; i += numColumns) {
                    ourSize += childHeight;
                    if (i + numColumns < count) {
                        ourSize += mVerticalSpacing;
                    }
                    if (ourSize >= heightSize) {
                        ourSize = heightSize;
                        break;
                    }
                }
                heightSize = ourSize;
            }
    
            if (widthMode == MeasureSpec.AT_MOST && mRequestedNumColumns != AUTO_FIT) {
                int ourSize = (mRequestedNumColumns*mColumnWidth)
                        + ((mRequestedNumColumns-1)*mHorizontalSpacing)
                        + mListPadding.left + mListPadding.right;
                if (ourSize > widthSize || didNotInitiallyFit) {
                    widthSize |= MEASURED_STATE_TOO_SMALL;
                }
            }
    
            setMeasuredDimension(widthSize, heightSize);
            mWidthMeasureSpec = widthMeasureSpec;
        }

    看代码我们很容知道需要这个

    if (heightMode == MeasureSpec.AT_MOST) {
    int ourSize = mListPadding.top + mListPadding.bottom;

    final int numColumns = mNumColumns;
    for (int i = 0; i < count; i += numColumns) {
    ourSize += childHeight;
    if (i + numColumns < count) {
           //累加垂直高度。
    ourSize += mVerticalSpacing;
    }
    if (ourSize >= heightSize) {
    ourSize = heightSize;
    break;
    }
    }
    heightSize = ourSize;
    }

    因此我们可以重写gridView的onMeseaure方法
    告诉父类我们要用AT_MOST模式去计算高度。
    int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
    super.onMeasure(widthMeasureSpec, expandSpec);
    结果如图:
    
    







  • 相关阅读:
    StructuredStreaming整合Kafka
    StructuredStreaming-Sink
    ValueError: max() arg is an empty sequence
    StructuredStreaming
    学习进度报告08
    SparkSQL+Hive
    SparkSQL花式查询
    RDD-DF-DS相互转换
    SparkSQL学习
    学习进度报告07
  • 原文地址:https://www.cnblogs.com/mamamia/p/7903754.html
Copyright © 2020-2023  润新知