ScrollView,ListView,GrideView,RecyclerView,ViewPager等多种view嵌套问题

本文主要是介绍ScrollView,ListView,GrideView,RecyclerView,ViewPager等多种view嵌套问题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在开发中各种滑动布局的view如ScrollView,ListView等非常常用,但是你也会发现各种奇怪问题产生。网上的解决方法有很多种,但是杂而不全,根据个人经验现在列出常见问题以及代码最少最简单的解决方法,首先你要了解事件的分发机制及事件冲突,这里不再赘述。(其他继承自AbsListView的类也适用,包括ExpandableListView、GridView等等)

  • ScrollView嵌套ListView冲突问题的最优解决方案

ScrollView嵌套ListVew或者GridView等很常用,下面来说解决版本

问题一 : 嵌套在 ScrollView的 ListVew数据显示不全,我遇到的是最多只显示两条已有的数据。

解决办法:重写 ListVew或者 GridView,网上还有很多若干解决办法,但是都不好用或者很复杂。

     
  1. @Override
  2. /** 只重写该方法,达到使ListView适应ScrollView的效果 */
  3. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  4. int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
  5. MeasureSpec.AT_MOST);
  6. super.onMeasure(widthMeasureSpec, expandSpec);
  7. }

  8. 这个方法有一个同样的毛病,就是默认显示的首项是ListView,需要手动把ScrollView滚动至最顶端


问题二 、打开套有 ListVew的 ScrollView的页面布局 默认 起始位置不是最顶部。

解决办法有两种都挺好用:

一是把套在里面的Gridview 或者 ListVew 不让获取焦点即可。

gridview.setFocusable(false); listview.setFocusable(false);

注意:在xml布局里面设置android:focusable=“false”不生效

方法二:网上还查到说可以设置myScrollView.smoothScrollTo(0,0);

  •    
    1. 看错误的布局代码:
    2. <ScrollView
    3. android:id="@+id/act_solution_1_sv"
    4. android:layout_width="fill_parent"
    5. android:layout_height="fill_parent">
    6. <LinearLayout
    7. android:layout_width="fill_parent"
    8. android:layout_height="wrap_content"
    9. android:orientation="vertical">
    10. <TextView
    11. android:layout_width="fill_parent"
    12. android:layout_height="wrap_content"
    13. android:text="\nListView上方数据\n" />
    14. <ListView
    15. android:id="@+id/act_solution_1_lv"
    16. android:layout_width="fill_parent"
    17. android:layout_height="wrap_content">
    18. </ListView>
    19. <TextView
    20. android:layout_width="fill_parent"
    21. android:layout_height="wrap_content"
    22. android:text="\nListView下方数据\n" />
    23. </LinearLayout>
    24. </ScrollView>
    25. ScrollView中只能放一个控件,一般都放LinearLayout,orientation属性值为vertical。
    26. 在LinearLayout中放需要呈现的内容。ListView也在其中,ListView的高度设为适应自身内容(wrap_content
    27. 原因就是scroll事件的消费处理以及ListView控件的高度设定问题


  • ViewPager和ScrollView嵌套滚动问题解决方案

  •    
    1. 嵌套是ViewPager-->ScrollView-->ViewPager.
    2. public class HorizontalInnerViewPager extends ViewPager {
    3. /** 触摸时按下的点 **/
    4. PointF downP = new PointF();
    5. /** 触摸时当前的点 **/
    6. PointF curP = new PointF();
    7. /** 自定义手势**/
    8. private GestureDetector mGestureDetector;
    9. public HorizontalInnerViewPager(Context context, AttributeSet attrs) {
    10. super(context, attrs);
    11. mGestureDetector = new GestureDetector(context, new XScrollDetector());
    12. }
    13. public HorizontalInnerViewPager(Context context) {
    14. super(context);
    15. mGestureDetector = new GestureDetector(context, new XScrollDetector());
    16. }
    17. @Override
    18. public boolean onInterceptTouchEvent(MotionEvent ev) {
    19. return super.onInterceptTouchEvent(ev);//default
    20. //当拦截触摸事件到达此位置的时候,返回true,
    21. //说明将onTouch拦截在此控件,进而执行此控件的onTouchEvent
    22. // return true;
    23. //接近水平滑动时子控件处理该事件,否则交给父控件处理
    24. // return mGestureDetector.onTouchEvent(ev);
    25. }
    26. @Override
    27. public boolean onTouchEvent(MotionEvent ev) {
    28. //每次进行onTouch事件都记录当前的按下的坐标
    29. curP.x = ev.getX();
    30. curP.y = ev.getY();
    31. if(ev.getAction() == MotionEvent.ACTION_DOWN){
    32. //记录按下时候的坐标
    33. //切记不可用 downP = curP ,这样在改变curP的时候,downP也会改变
    34. downP.x = ev.getX();
    35. downP.y = ev.getY();
    36. //此句代码是为了通知他的父ViewPager现在进行的是本控件的操作,不要对我的操作进行干扰
    37. getParent().requestDisallowInterceptTouchEvent(true);
    38. }
    39. if(ev.getAction() == MotionEvent.ACTION_MOVE){
    40. float distanceX = curP.x - downP.x;
    41. float distanceY = curP.y - downP.y;
    42. //接近水平滑动,ViewPager控件捕获手势,水平滚动
    43. if(Math.abs(distanceX) > Math.abs(distanceY)){
    44. //此句代码是为了通知他的父ViewPager现在进行的是本控件的操作,不要对我的操作进行干扰
    45. getParent().requestDisallowInterceptTouchEvent(true);
    46. }else{
    47. //接近垂直滑动,交给父控件处理
    48. getParent().requestDisallowInterceptTouchEvent(false);
    49. }
    50. }
    51. return super.onTouchEvent(ev);
    52. }
    53. private class XScrollDetector extends GestureDetector.SimpleOnGestureListener{
    54. @Override
    55. public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
    56. // return super.onScroll(e1, e2, distanceX, distanceY);
    57. //接近水平滑动时子控件处理该事件,否则交给父控件处理
    58. return (Math.abs(distanceX) > Math.abs(distanceY));
    59. }
    60. }
    61. }
  • ScrollView里嵌套ScrollView

  •    
    1. 两个相同方向的ScrollView是不能嵌套的,所以尽量避免这种情况; 如果不能避免,则看下面
    2. 目前做的这个只支持两个ScrollView嵌套,两个以上还有待改进,能套两个就已经能满足很多需求了目前为纵向scrollview的支持.直接看代码:
    3. public class InnerScrollView extends ScrollView {
    4. /**
    5. */
    6. public ScrollView parentScrollView;
    7. public InnerScrollView(Context context, AttributeSet attrs) {
    8. super(context, attrs);
    9. }
    10. private int lastScrollDelta = 0;
    11. public void resume() {
    12. overScrollBy(0, -lastScrollDelta, 0, getScrollY(), 0, getScrollRange(), 0, 0, true);
    13. lastScrollDelta = 0;
    14. }
    15. int mTop = 10;
    16. /**
    17. * 将targetView滚到最顶端
    18. */
    19. public void scrollTo(View targetView) {
    20. int oldScrollY = getScrollY();
    21. int top = targetView.getTop() - mTop;
    22. int delatY = top - oldScrollY;
    23. lastScrollDelta = delatY;
    24. overScrollBy(0, delatY, 0, getScrollY(), 0, getScrollRange(), 0, 0, true);
    25. }
    26. private int getScrollRange() {
    27. int scrollRange = 0;
    28. if (getChildCount() > 0) {
    29. View child = getChildAt(0);
    30. scrollRange = Math.max(0, child.getHeight() - (getHeight()));
    31. }
    32. return scrollRange;
    33. }
    34. int currentY;
    35. @Override
    36. public boolean onInterceptTouchEvent(MotionEvent ev) {
    37. if (parentScrollView == null) {
    38. return super.onInterceptTouchEvent(ev);
    39. } else {
    40. if (ev.getAction() == MotionEvent.ACTION_DOWN) {
    41. // 将父scrollview的滚动事件拦截
    42. currentY = (int)ev.getY();
    43. setParentScrollAble(false);
    44. return super.onInterceptTouchEvent(ev);
    45. } else if (ev.getAction() == MotionEvent.ACTION_UP) {
    46. // 把滚动事件恢复给父Scrollview
    47. setParentScrollAble(true);
    48. } else if (ev.getAction() == MotionEvent.ACTION_MOVE) {
    49. }
    50. }
    51. return super.onInterceptTouchEvent(ev);
    52. }
    53. @Override
    54. public boolean onTouchEvent(MotionEvent ev) {
    55. View child = getChildAt(0);
    56. if (parentScrollView != null) {
    57. if (ev.getAction() == MotionEvent.ACTION_MOVE) {
    58. int height = child.getMeasuredHeight();
    59. height = height - getMeasuredHeight();
    60. // System.out.println("height=" + height);
    61. int scrollY = getScrollY();
    62. // System.out.println("scrollY" + scrollY);
    63. int y = (int)ev.getY();
    64. // 手指向下滑动
    65. if (currentY < y) {
    66. if (scrollY <= 0) {
    67. // 如果向下滑动到头,就把滚动交给父Scrollview
    68. setParentScrollAble(true);
    69. return false;
    70. } else {
    71. setParentScrollAble(false);
    72. }
    73. } else if (currentY > y) {
    74. if (scrollY >= height) {
    75. // 如果向上滑动到头,就把滚动交给父Scrollview
    76. setParentScrollAble(true);
    77. return false;
    78. } else {
    79. setParentScrollAble(false);
    80. }
    81. }
    82. currentY = y;
    83. }
    84. }
    85. return super.onTouchEvent(ev);
    86. }
    87. /**
    88. * 是否把滚动事件交给父scrollview
    89. *
    90. * @param flag
    91. */
    92. private void setParentScrollAble(boolean flag) {
    93. parentScrollView.requestDisallowInterceptTouchEvent(!flag);
    94. }
    95. }
  • RecyclerView嵌套滚动问题

     

    在 Android 应用中,大部分情况下都会使用一个垂直滚动的 View 来显示内容(比如 ListView、RecyclerView 等)。但是有时候你还希望垂直滚动的View 里面的内容可以水平滚动。如果直接在垂直滚动的 View 里面使用水平滚动的 View,则滚动操作并不是很流畅。

    比如下图中的示例:

    为什么会出现这个问题呢?

    上图中的布局为一个 RecyclerView 使用的是垂直滚动的 LinearLayoutManager 布局管理器,而里面每个 Item 为另外一个 RecyclerView 使用的是水平滚动的 LinearLayoutManager。而在 Android系统的事件分发 中,即使最上层的 View 只能垂直滚动,当用户水平拖动的时候,最上层的 View 依然会拦截点击事件。下面是 RecyclerView.java 中 onInterceptTouchEvent 的相关代码:

    @Override
    public boolean onInterceptTouchEvent(MotionEvent e) {  ...switch (action) {case MotionEvent.ACTION_DOWN:...case MotionEvent.ACTION_MOVE: {...if (mScrollState != SCROLL_STATE_DRAGGING) {boolean startScroll = false;if (canScrollHorizontally && Math.abs(dx) > mTouchSlop) {...startScroll = true;}if (canScrollVertically && Math.abs(dy) > mTouchSlop) {...startScroll = true;}if (startScroll) {setScrollState(SCROLL_STATE_DRAGGING);}}} break;...}return mScrollState == SCROLL_STATE_DRAGGING;
    }

    注意上面的 if 判断:

    if(canScrollVertically && Math.abs(dy) > mTouchSlop) {...}  

    RecyclerView 并没有判断用户拖动的角度, 只是用来判断拖动的距离是否大于滚动的最小尺寸。 如果是一个只能垂直滚动的 View,这样实现是没有问题的。如果我们在里面再放一个 水平滚动的 RecyclerView ,则就出现问题了。

    可以通过如下的方式来修复该问题:

    if(canScrollVertically && Math.abs(dy) > mTouchSlop && (canScrollHorizontally || Math.abs(dy) > Math.abs(dx))) {...}  

    下面是一个完整的实现 BetterRecyclerView.java :

    public class BetterRecyclerView extends RecyclerView{private static final int INVALID_POINTER = -1;private int mScrollPointerId = INVALID_POINTER;private int mInitialTouchX, mInitialTouchY;private int mTouchSlop;public BetterRecyclerView(Contextcontext) {this(context, null);}public BetterRecyclerView(Contextcontext, @Nullable AttributeSetattrs) {this(context, attrs, 0);}public BetterRecyclerView(Contextcontext, @Nullable AttributeSetattrs, int defStyle) {super(context, attrs, defStyle);final ViewConfigurationvc = ViewConfiguration.get(getContext());mTouchSlop = vc.getScaledTouchSlop();}@Overridepublic void setScrollingTouchSlop(int slopConstant) {super.setScrollingTouchSlop(slopConstant);final ViewConfigurationvc = ViewConfiguration.get(getContext());switch (slopConstant) {case TOUCH_SLOP_DEFAULT:mTouchSlop = vc.getScaledTouchSlop();break;case TOUCH_SLOP_PAGING:mTouchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(vc);break;default:break;}}@Overridepublic boolean onInterceptTouchEvent(MotionEvent e) {final int action = MotionEventCompat.getActionMasked(e);final int actionIndex = MotionEventCompat.getActionIndex(e);switch (action) {case MotionEvent.ACTION_DOWN:mScrollPointerId = MotionEventCompat.getPointerId(e, 0);mInitialTouchX = (int) (e.getX() + 0.5f);mInitialTouchY = (int) (e.getY() + 0.5f);return super.onInterceptTouchEvent(e);case MotionEventCompat.ACTION_POINTER_DOWN:mScrollPointerId = MotionEventCompat.getPointerId(e, actionIndex);mInitialTouchX = (int) (MotionEventCompat.getX(e, actionIndex) + 0.5f);mInitialTouchY = (int) (MotionEventCompat.getY(e, actionIndex) + 0.5f);return super.onInterceptTouchEvent(e);case MotionEvent.ACTION_MOVE: {final int index = MotionEventCompat.findPointerIndex(e, mScrollPointerId);if (index < 0) {return false;}final int x = (int) (MotionEventCompat.getX(e, index) + 0.5f);final int y = (int) (MotionEventCompat.getY(e, index) + 0.5f);if (getScrollState() != SCROLL_STATE_DRAGGING) {final int dx = x - mInitialTouchX;final int dy = y - mInitialTouchY;final boolean canScrollHorizontally = getLayoutManager().canScrollHorizontally();final boolean canScrollVertically = getLayoutManager().canScrollVertically();boolean startScroll = false;if (canScrollHorizontally && Math.abs(dx) > mTouchSlop && (Math.abs(dx) >= Math.abs(dy) || canScrollVertically)) {startScroll = true;}if (canScrollVertically && Math.abs(dy) > mTouchSlop && (Math.abs(dy) >= Math.abs(dx) || canScrollHorizontally)) {startScroll = true;}return startScroll && super.onInterceptTouchEvent(e);}return super.onInterceptTouchEvent(e);}default:return super.onInterceptTouchEvent(e);}}
    }

    其他问题

    当用户快速滑动(fling)RecyclerView 的时候, RecyclerView 需要一段时间来确定其最终位置。 如果用户在快速滑动一个子的水平 RecyclerView,在子 RecyclerView 还在滑动的过程中,如果用户垂直滑动,则是无法垂直滑动的。原因是子 RecyclerView 依然处理了这个垂直滑动事件。

    所以,在快速滑动后的滚动到静止的状态中,子 View 不应该响应滑动事件了,再次看看 RecyclerView 的 onInterceptTouchEvent() 代码:

    @Override
    public boolean onInterceptTouchEvent(MotionEvent e) {  ...switch (action) {case MotionEvent.ACTION_DOWN:...if (mScrollState == SCROLL_STATE_SETTLING) {getParent().requestDisallowInterceptTouchEvent(true);setScrollState(SCROLL_STATE_DRAGGING);}...}return mScrollState == SCROLL_STATE_DRAGGING;
    }

    可以看到,当 RecyclerView 的状态为 SCROLL_STATE_SETTLING (快速滑动后到滑动静止之间的状态)时, RecyclerView 告诉父控件不要拦截事件。

    同样的,如果只有一个方向固定,这样处理是没问题的。

    针对我们这个嵌套的情况,父 RecyclerView 应该只拦截垂直滚动事件,所以可以这么修改父 RecyclerView:

    public class FeedRootRecyclerView extends BetterRecyclerView{  public FeedRootRecyclerView(Contextcontext) {this(context, null);}public FeedRootRecyclerView(Contextcontext, @Nullable AttributeSetattrs) {this(context, attrs, 0);}public FeedRootRecyclerView(Contextcontext, @Nullable AttributeSetattrs, int defStyle) {super(context, attrs, defStyle);}@Overridepublic void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {/* do nothing */}
    }

    下图为最终的结果:



  • recycleview跟scrollview嵌套问题

    scrollview 嵌套recyclerview 时,recyclerview不显示,这就需要我们自己计算recyclerview的高度,比如:


           
    1. ViewGroup.LayoutParams mParams = recyclerView.getLayoutParams();
    2. mParams.height = (CommonUtils.getScreenWidthPX(getActivity()) * 480 / 720 + CommonUtils.dipToPixels(40)) * num + CommonUtils.dipToPixels(8);
    3. mParams.width = CommonUtils.getScreenWidthPX(getActivity());
    4. recyclerView.setLayoutParams(mParams);



    这中方法适合item高度比较好计算的情形,但要遇到里面的item高度不一定这就需要我们重写recyclerview的高度了,以前嵌套listview的时候我们只需重写listview 然后重写



           
    1. @Override
    2. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    3. // TODO Auto-generated method stub
    4. int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
    5. MeasureSpec.AT_MOST);
    6. super.onMeasure(widthMeasureSpec, expandSpec);
    7. }


    但是这种方法在recyclerview重写不管用。 

    我们此时要重写的的是LinearLayoutManager或GridLayoutManager

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




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


    重写完之后,用就好说了,在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);

    或者再activity中设置一样的



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


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

这篇关于ScrollView,ListView,GrideView,RecyclerView,ViewPager等多种view嵌套问题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/1020426

相关文章

如何解决mmcv无法安装或安装之后报错问题

《如何解决mmcv无法安装或安装之后报错问题》:本文主要介绍如何解决mmcv无法安装或安装之后报错问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录mmcv无法安装或安装之后报错问题1.当我们运行YOwww.chinasem.cnLO时遇到2.找到下图所示这里3.

浅谈配置MMCV环境,解决报错,版本不匹配问题

《浅谈配置MMCV环境,解决报错,版本不匹配问题》:本文主要介绍浅谈配置MMCV环境,解决报错,版本不匹配问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录配置MMCV环境,解决报错,版本不匹配错误示例正确示例总结配置MMCV环境,解决报错,版本不匹配在col

Vue3使用router,params传参为空问题

《Vue3使用router,params传参为空问题》:本文主要介绍Vue3使用router,params传参为空问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录vue3使用China编程router,params传参为空1.使用query方式传参2.使用 Histo

SpringBoot首笔交易慢问题排查与优化方案

《SpringBoot首笔交易慢问题排查与优化方案》在我们的微服务项目中,遇到这样的问题:应用启动后,第一笔交易响应耗时高达4、5秒,而后续请求均能在毫秒级完成,这不仅触发监控告警,也极大影响了用户体... 目录问题背景排查步骤1. 日志分析2. 性能工具定位优化方案:提前预热各种资源1. Flowable

springboot循环依赖问题案例代码及解决办法

《springboot循环依赖问题案例代码及解决办法》在SpringBoot中,如果两个或多个Bean之间存在循环依赖(即BeanA依赖BeanB,而BeanB又依赖BeanA),会导致Spring的... 目录1. 什么是循环依赖?2. 循环依赖的场景案例3. 解决循环依赖的常见方法方法 1:使用 @La

Java枚举类实现Key-Value映射的多种实现方式

《Java枚举类实现Key-Value映射的多种实现方式》在Java开发中,枚举(Enum)是一种特殊的类,本文将详细介绍Java枚举类实现key-value映射的多种方式,有需要的小伙伴可以根据需要... 目录前言一、基础实现方式1.1 为枚举添加属性和构造方法二、http://www.cppcns.co

SpringBoot启动报错的11个高频问题排查与解决终极指南

《SpringBoot启动报错的11个高频问题排查与解决终极指南》这篇文章主要为大家详细介绍了SpringBoot启动报错的11个高频问题的排查与解决,文中的示例代码讲解详细,感兴趣的小伙伴可以了解一... 目录1. 依赖冲突:NoSuchMethodError 的终极解法2. Bean注入失败:No qu

MySQL新增字段后Java实体未更新的潜在问题与解决方案

《MySQL新增字段后Java实体未更新的潜在问题与解决方案》在Java+MySQL的开发中,我们通常使用ORM框架来映射数据库表与Java对象,但有时候,数据库表结构变更(如新增字段)后,开发人员可... 目录引言1. 问题背景:数据库与 Java 实体不同步1.1 常见场景1.2 示例代码2. 不同操作

Java 中实现异步的多种方式

《Java中实现异步的多种方式》文章介绍了Java中实现异步处理的几种常见方式,每种方式都有其特点和适用场景,通过选择合适的异步处理方式,可以提高程序的性能和可维护性,感兴趣的朋友一起看看吧... 目录1. 线程池(ExecutorService)2. CompletableFuture3. ForkJoi

mss32.dll文件丢失怎么办? 电脑提示mss32.dll丢失的多种修复方法

《mss32.dll文件丢失怎么办?电脑提示mss32.dll丢失的多种修复方法》最近,很多电脑用户可能遇到了mss32.dll文件丢失的问题,导致一些应用程序无法正常启动,那么,如何修复这个问题呢... 在电脑常年累月的使用过程中,偶尔会遇到一些问题令人头疼。像是某个程序尝试运行时,系统突然弹出一个错误提