美文网首页
解决ScrollView嵌套RecyclerView时滑动冲突:

解决ScrollView嵌套RecyclerView时滑动冲突:

作者: 梧桐树biu | 来源:发表于2017-08-18 12:33 被阅读0次

    前言:

    在实际的项目开发中,项目需求所需,需要将ScrollView和RecyclerView嵌套使用,在使用过程中发现两者配合使用存在滑动冲突问题,现将解决办法记录在册,以便后续查看。话不多少,直接上,能动手绝不瞎哔哔。

    1.最暴力的办法就是直接禁止recyclerView滑动;

    GridLayoutManager gridLayoutManager = new GridLayoutManager(getContext(), 2) {
           
        @Override
        public boolean canScrollVertically() {
            return false;
        }
    };
    

    2. 重写LayoutManager,重写canScrollVertically()这个方法。

    public class ScrollGridLayoutManagerw extends GridLayoutManager {
        //是否支持滑动
        private boolean isScrollEnabled = true;
    
        public ScrollGridLayoutManagerw(Context context, int spanCount) {
            super(context, spanCount);
        }
    
        public ScrollGridLayoutManagerw(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
            super(context, attrs, defStyleAttr, defStyleRes);
        }
    
        public ScrollGridLayoutManagerw(Context context, int spanCount, int orientation, boolean reverseLayout) {
            super(context, spanCount, orientation, reverseLayout);
        }
    
        /**
         * 是否支持滑动
         *
         * @param flag
         */
        public void setScrollEnabled(boolean flag) {
            this.isScrollEnabled = flag;
        }
    
        @Override
        public boolean canScrollVertically() {
    
            //isScrollEnabled:recyclerview 是否支持滑动
            //super.canScrollVertically():是否为竖直方向滚动
        return isScrollEnabled && super.canScrollVertically();
        }
    }
    

    使用的时候在代码中设置:

    LayoutManager.setScrollEnabled(false);
    

    3. 新建一个类继承LayoutManager,通过重写onMeasure()方法重新测量RecyclerView宽高,在代码中设置RecyclerView.setNestedScrollingEnabled(false)来解决。

    public class ScrollGridLayoutManager extends GridLayoutManager {
        private static final String TAG = ScrollGridLayoutManager.class.getSimpleName();
    
        public ScrollGridLayoutManager(Context context, int spanCount) {
            super(context, spanCount);
        }
    
        private int[] mMeasuredDimension = new int[2];
    
        @Override
        public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state,
                              int widthSpec, int heightSpec) {
    
            final int widthMode = View.MeasureSpec.getMode(widthSpec);
            final int heightMode = View.MeasureSpec.getMode(heightSpec);
            final int widthSize = View.MeasureSpec.getSize(widthSpec);
            final int heightSize = View.MeasureSpec.getSize(heightSpec);
    
            Log.i(TAG, "onMeasure called. \nwidthMode " + widthMode
                    + " \nheightMode " + heightSpec
                    + " \nwidthSize " + widthSize
                    + " \nheightSize " + heightSize
                    + " \ngetItemCount() " + getItemCount());
    
            int width = 0;
            int height = 0;
            for (int i = 0; i < getItemCount(); i++) {
                measureScrapChild(recycler, i,
                        View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
                        View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
                        mMeasuredDimension);
    
                if (getOrientation() == HORIZONTAL) {
                    width = width + mMeasuredDimension[0];
                    if (i == 0) {
                        height = mMeasuredDimension[1];
                    }
                } else {
                    height = height + mMeasuredDimension[1];
                    if (i == 0) {
                        width = mMeasuredDimension[0];
                    }
                }
            }
            switch (widthMode) {
                case View.MeasureSpec.EXACTLY:
                    width = widthSize;
                case View.MeasureSpec.AT_MOST:
                case View.MeasureSpec.UNSPECIFIED:
            }
    
            switch (heightMode) {
                case View.MeasureSpec.EXACTLY:
                    height = heightSize;
                case View.MeasureSpec.AT_MOST:
                case View.MeasureSpec.UNSPECIFIED:
            }
    
            setMeasuredDimension(width, height);
        }
    
        private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec,
                                       int heightSpec, int[] measuredDimension) {
            try {
                View view = recycler.getViewForPosition(0);//fix 动态添加时报IndexOutOfBoundsException
    
                if (view != null) {
                    RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams();
    
                    int childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec,
                            getPaddingLeft() + getPaddingRight(), p.width);
    
                    int childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec,
                            getPaddingTop() + getPaddingBottom(), p.height);
    
                    view.measure(childWidthSpec, childHeightSpec);
                    measuredDimension[0] = view.getMeasuredWidth() + p.leftMargin + p.rightMargin;
                    measuredDimension[1] = view.getMeasuredHeight() + p.bottomMargin + p.topMargin;
                    recycler.recycleView(view);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
            }
        }
    }
    

    使用的时候在代码中设置:

    ScrollGridLayoutManager gridLayoutManager = new ScrollGridLayoutManager(getContext(),2);
    recyclerView.setNestedScrollingEnabled(false);
    

    通过上述三种方法就可以解决ScrollView嵌套RecyclerView时的滑动冲突。

    相关文章

      网友评论

          本文标题:解决ScrollView嵌套RecyclerView时滑动冲突:

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