• ScrollView嵌套recyclerView出现的滑动问题


    各类it学习视频,大家都可以看看哦!我自己本人都是通过这些来学习it只知识的!下面是视频链接
    https://shop61408405.taobao.com/?spm=a1z10.5-c.0.0.cAfZMN&qq-pf-to=pcqq.group

    记得以前在解决scrollView与ListView嵌套问题时,那个时候是自定义了listView去测量listView高度,今天项目中刚 好碰到了要用recycerView,同样也是嵌套在scrollView中,但是按照以前listView方法居然不显示了,后来发现原来是要重写的是 LayoutManager...

    在此说明,这是copy大神的,我只是为了学习啊!大神真的很牛啊!

    原创博客:http://blog.csdn.net/u010623588/article/details/50262367

    重写的LinearLayoutManager

     1     public class FullyLinearLayoutManager extends LinearLayoutManager {  
     2       
     3         private static final String TAG = FullyLinearLayoutManager.class.getSimpleName();  
     4       
     5         public FullyLinearLayoutManager(Context context) {  
     6             super(context);  
     7         }  
     8       
     9         public FullyLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {  
    10             super(context, orientation, reverseLayout);  
    11         }  
    12       
    13         private int[] mMeasuredDimension = new int[2];  
    14       
    15         @Override  
    16         public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state,  
    17                               int widthSpec, int heightSpec) {  
    18       
    19             final int widthMode = View.MeasureSpec.getMode(widthSpec);  
    20             final int heightMode = View.MeasureSpec.getMode(heightSpec);  
    21             final int widthSize = View.MeasureSpec.getSize(widthSpec);  
    22             final int heightSize = View.MeasureSpec.getSize(heightSpec);  
    23       
    24             Log.i(TAG, "onMeasure called. 
    widthMode " + widthMode  
    25                     + " 
    heightMode " + heightSpec  
    26                     + " 
    widthSize " + widthSize  
    27                     + " 
    heightSize " + heightSize  
    28                     + " 
    getItemCount() " + getItemCount());  
    29       
    30             int width = 0;  
    31             int height = 0;  
    32             for (int i = 0; i < getItemCount(); i++) {  
    33                 measureScrapChild(recycler, i,  
    34                         View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),  
    35                         View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),  
    36                         mMeasuredDimension);  
    37       
    38                 if (getOrientation() == HORIZONTAL) {  
    39                     width = width + mMeasuredDimension[0];  
    40                     if (i == 0) {  
    41                         height = mMeasuredDimension[1];  
    42                     }  
    43                 } else {  
    44                     height = height + mMeasuredDimension[1];  
    45                     if (i == 0) {  
    46                         width = mMeasuredDimension[0];  
    47                     }  
    48                 }  
    49             }  
    50             switch (widthMode) {  
    51                 case View.MeasureSpec.EXACTLY:  
    52                     width = widthSize;  
    53                 case View.MeasureSpec.AT_MOST:  
    54                 case View.MeasureSpec.UNSPECIFIED:  
    55             }  
    56       
    57             switch (heightMode) {  
    58                 case View.MeasureSpec.EXACTLY:  
    59                     height = heightSize;  
    60                 case View.MeasureSpec.AT_MOST:  
    61                 case View.MeasureSpec.UNSPECIFIED:  
    62             }  
    63       
    64             setMeasuredDimension(width, height);  
    65         }  
    66       
    67         private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec,  
    68                                        int heightSpec, int[] measuredDimension) {  
    69             try {  
    70                 View view = recycler.getViewForPosition(0);//fix 动态添加时报IndexOutOfBoundsException  
    71       
    72                 if (view != null) {  
    73                     RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams();  
    74       
    75                     int childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec,  
    76                             getPaddingLeft() + getPaddingRight(), p.width);  
    77       
    78                     int childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec,  
    79                             getPaddingTop() + getPaddingBottom(), p.height);  
    80       
    81                     view.measure(childWidthSpec, childHeightSpec);  
    82                     measuredDimension[0] = view.getMeasuredWidth() + p.leftMargin + p.rightMargin;  
    83                     measuredDimension[1] = view.getMeasuredHeight() + p.bottomMargin + p.topMargin;  
    84                     recycler.recycleView(view);  
    85                 }  
    86             } catch (Exception e) {  
    87                 e.printStackTrace();  
    88             } finally {  
    89             }  
    90         }  
    91     }  

    以及重写的GridViewLayout:

      1     public class FullyGridLayoutManager extends GridLayoutManager {  
      2       
      3         private int mwidth = 0;  
      4         private int mheight = 0;  
      5       
      6         public FullyGridLayoutManager(Context context, int spanCount) {  
      7             super(context, spanCount);  
      8         }  
      9       
     10         public FullyGridLayoutManager(Context context, int spanCount, int orientation, boolean reverseLayout) {  
     11             super(context, spanCount, orientation, reverseLayout);  
     12         }  
     13       
     14         private int[] mMeasuredDimension = new int[2];  
     15       
     16         public int getMwidth() {  
     17             return mwidth;  
     18         }  
     19       
     20         public void setMwidth(int mwidth) {  
     21             this.mwidth = mwidth;  
     22         }  
     23       
     24         public int getMheight() {  
     25             return mheight;  
     26         }  
     27       
     28         public void setMheight(int mheight) {  
     29             this.mheight = mheight;  
     30         }  
     31       
     32         @Override  
     33         public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state, int widthSpec, int heightSpec) {  
     34             final int widthMode = View.MeasureSpec.getMode(widthSpec);  
     35             final int heightMode = View.MeasureSpec.getMode(heightSpec);  
     36             final int widthSize = View.MeasureSpec.getSize(widthSpec);  
     37             final int heightSize = View.MeasureSpec.getSize(heightSpec);  
     38       
     39             int width = 0;  
     40             int height = 0;  
     41             int count = getItemCount();  
     42             int span = getSpanCount();  
     43             for (int i = 0; i < count; i++) {  
     44                 measureScrapChild(recycler, i,  
     45                         View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),  
     46                         View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),  
     47                         mMeasuredDimension);  
     48       
     49                 if (getOrientation() == HORIZONTAL) {  
     50                     if (i % span == 0) {  
     51                         width = width + mMeasuredDimension[0];  
     52                     }  
     53                     if (i == 0) {  
     54                         height = mMeasuredDimension[1];  
     55                     }  
     56                 } else {  
     57                     if (i % span == 0) {  
     58                         height = height + mMeasuredDimension[1];  
     59                     }  
     60                     if (i == 0) {  
     61                         width = mMeasuredDimension[0];  
     62                     }  
     63                 }  
     64             }  
     65       
     66             switch (widthMode) {  
     67                 case View.MeasureSpec.EXACTLY:  
     68                     width = widthSize;  
     69                 case View.MeasureSpec.AT_MOST:  
     70                 case View.MeasureSpec.UNSPECIFIED:  
     71             }  
     72       
     73             switch (heightMode) {  
     74                 case View.MeasureSpec.EXACTLY:  
     75                     height = heightSize;  
     76                 case View.MeasureSpec.AT_MOST:  
     77                 case View.MeasureSpec.UNSPECIFIED:  
     78             }  
     79             setMheight(height);  
     80             setMwidth(width);  
     81             setMeasuredDimension(width, height);  
     82         }  
     83       
     84         private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec,  
     85                                        int heightSpec, int[] measuredDimension) {  
     86             if (position < getItemCount()) {  
     87                 try {  
     88                     View view = recycler.getViewForPosition(0);//fix 动态添加时报IndexOutOfBoundsException  
     89                     if (view != null) {  
     90                         RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams();  
     91                         int childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec,  
     92                                 getPaddingLeft() + getPaddingRight(), p.width);  
     93                         int childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec,  
     94                                 getPaddingTop() + getPaddingBottom(), p.height);  
     95                         view.measure(childWidthSpec, childHeightSpec);  
     96                         measuredDimension[0] = view.getMeasuredWidth() + p.leftMargin + p.rightMargin;  
     97                         measuredDimension[1] = view.getMeasuredHeight() + p.bottomMargin + p.topMargin;  
     98                         recycler.recycleView(view);  
     99                     }  
    100                 } catch (Exception e) {  
    101                     e.printStackTrace();  
    102                 }  
    103             }  
    104         }  
    105     }  

     还有一个瀑布流StaggeredGridLayoutManager和ScrollView进行嵌套

      1 StaggeredGridLayoutManager和ScrollView进行嵌套  3 
      4 package com.kale.waterfalldemo.extra.RecyclerView;
      5 
      6 import android.support.v7.widget.RecyclerView;
      7 import android.support.v7.widget.StaggeredGridLayoutManager;
      8 import android.view.View;
      9 import android.view.ViewGroup;
     10 
     11 /**
     12  * @author Jack Tony
     13  * @brief 不规则排列(类似于瀑布流)的布局管理器
     14  * @date 2015/4/6
     15  */
     16 public class ExStaggeredGridLayoutManager extends StaggeredGridLayoutManager {
     17 
     18     public ExStaggeredGridLayoutManager(int spanCount, int orientation) {
     19         super(spanCount, orientation);
     20     }
     21 
     22     // 尺寸的数组,[0]是宽,[1]是高
     23     private int[] measuredDimension = new int[2];
     24 
     25     // 用来比较同行/列那个item罪宽/高
     26     private int[] dimension;
     27 
     28 
     29     @Override
     30 
     31     public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state, int widthSpec, int heightSpec) {
     32         // 宽的mode+size
     33         final int widthMode = View.MeasureSpec.getMode(widthSpec);
     34         final int widthSize = View.MeasureSpec.getSize(widthSpec);
     35         // 高的mode + size
     36         final int heightMode = View.MeasureSpec.getMode(heightSpec);
     37         final int heightSize = View.MeasureSpec.getSize(heightSpec);
     38 
     39         // 自身宽高的初始值
     40         int width = 0;
     41         int height = 0;
     42         // item的数目
     43         int count = getItemCount();
     44         // item的列数
     45         int span = getSpanCount();
     46         // 根据行数或列数来创建数组
     47         dimension = new int[span];
     48 
     49         for (int i = 0; i < count; i++) {
     50             measureScrapChild(recycler, i,
     51                     View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
     52                     View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED), measuredDimension);
     53 
     54            // 如果是竖直的列表,计算item的高,否则计算宽度
     55             //Log.d("LISTENER", "position " + i + " height = " + measuredDimension[1]);
     56             if (getOrientation() == VERTICAL) {
     57                 dimension[findMinIndex(dimension)] += measuredDimension[1];
     58             } else {
     59                 dimension[findMinIndex(dimension)] += measuredDimension[0];
     60             }
     61         }
     62         if (getOrientation() == VERTICAL) {
     63             height = findMax(dimension);
     64         } else {
     65             width = findMax(dimension);
     66         }
     67         
     68 
     69         switch (widthMode) {
     70             // 当控件宽是match_parent时,宽度就是父控件的宽度
     71             case View.MeasureSpec.EXACTLY:
     72                 width = widthSize;
     73                 break;
     74             case View.MeasureSpec.AT_MOST:
     75                 break;
     76             case View.MeasureSpec.UNSPECIFIED:
     77                 break;
     78         }
     79         switch (heightMode) {
     80             // 当控件高是match_parent时,高度就是父控件的高度
     81             case View.MeasureSpec.EXACTLY:
     82                 height = heightSize;
     83                 break;
     84             case View.MeasureSpec.AT_MOST:
     85                 break;
     86             case View.MeasureSpec.UNSPECIFIED:
     87                 break;
     88         }
     89         // 设置测量尺寸  
     90         setMeasuredDimension(width, height);
     91     }
     92 
     93     private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec,
     94             int heightSpec, int[] measuredDimension) {
     95 
     96         // 挨个遍历所有item
     97         if (position < getItemCount()) {
     98             try {
     99                 View view = recycler.getViewForPosition(position);//fix 动态添加时报IndexOutOfBoundsException
    100 
    101                 if (view != null) {
    102                     RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams) view.getLayoutParams();
    103                     int childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec, getPaddingLeft() + getPaddingRight(), lp.width);
    104                     int childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec, getPaddingTop() + getPaddingBottom(), lp.height);
    105                     // 子view进行测量,然后可以通过getMeasuredWidth()获得测量的宽,高类似
    106                     view.measure(childWidthSpec, childHeightSpec);
    107                     // 将item的宽高放入数组中
    108                     measuredDimension[0] = view.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
    109                     measuredDimension[1] = view.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
    110                     recycler.recycleView(view);
    111                 }
    112             } catch (Exception e) {
    113                 e.printStackTrace();
    114             }
    115         }
    116     }
    117 
    118     private int findMax(int[] array) {
    119         int max = array[0];
    120         for (int value : array) {
    121             if (value > max) {
    122                 max = value;
    123             }
    124         }
    125         return max;
    126     }
    127 
    128     /**
    129      * 得到最数组中最小元素的下标
    130      *
    131      * @param array
    132      * @return
    133      */
    134     private int findMinIndex(int[] array) {
    135         int index = 0;
    136         int min = array[0];
    137         for (int i = 0; i < array.length; i++) {
    138             if (array[i] < min) {
    139                 min = array[i];
    140                 index = i;
    141             }
    142         }
    143         return index;
    144     }
    145    
    146 }

    重写完之后,用就好说了,在adapter的onBindview和平常一样用就可以了

    1     final FullyGridLayoutManager manager = new FullyGridLayoutManager(context.getActivity(), 3);  
    2            manager.setOrientation(GridLayoutManager.VERTICAL);  
    3            manager.setSmoothScrollbarEnabled(true);  
    4            viewHolder.recyclerView.setLayoutManager(manager);  

     

    关键是,还有个坑爹的问题:

    此种方法在4.x系统上好用,能显示滑动也流畅,但是在5.x上虽然显示正常,但是滑动的时候好像被粘住了,没有惯性效果。。。。
    最后解决方法是重写最外层的Scrollview

     1     **  
     2      * 屏蔽 滑动事件  
     3      */  
     4     public class MyScrollview extends ScrollView {  
     5         private int downX;  
     6         private int downY;  
     7         private int mTouchSlop;  
     8       
     9         public MyScrollview(Context context) {  
    10             super(context);  
    11             mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();  
    12         }  
    13       
    14         public MyScrollview(Context context, AttributeSet attrs) {  
    15             super(context, attrs);  
    16             mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();  
    17         }  
    18       
    19         public MyScrollview(Context context, AttributeSet attrs, int defStyleAttr) {  
    20             super(context, attrs, defStyleAttr);  
    21             mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();  
    22         }  
    23       
    24         @Override  
    25         public boolean onInterceptTouchEvent(MotionEvent e) {  
    26             int action = e.getAction();  
    27             switch (action) {  
    28                 case MotionEvent.ACTION_DOWN:  
    29                     downX = (int) e.getRawX();  
    30                     downY = (int) e.getRawY();  
    31                     break;  
    32                 case MotionEvent.ACTION_MOVE:  
    33                     int moveY = (int) e.getRawY();  
    34                     if (Math.abs(moveY - downY) > mTouchSlop) {  
    35                         return true;  
    36                     }  
    37             }  
    38             return super.onInterceptTouchEvent(e);  
    39         }  
    40     }  

    这样就可以了,暴力屏蔽。。。。5以上的事件直接传递给了内层的recyclerview,所以我们把滑动事件拦截就好了。。。

  • 相关阅读:
    java并发:简单面试问题集锦
    Java:泛型
    Java:注解(元数据)
    Java:反射
    Java:静态代理 and 动态代理
    华为机试题——该警醒了,骚年
    java并发:线程同步机制之Lock
    java并发:中断一个正在运行的线程
    java中String类型变量的赋值问题
    java中的自增问题
  • 原文地址:https://www.cnblogs.com/wangying222/p/5842438.html
Copyright © 2020-2023  润新知