我们的recyclerView有多个layoutmanager,通过重写layoutmanager的方法就可以让recyclerView和ScrollView嵌套了。但是请注意,如果recyclerView很长那么强烈不建议去做嵌套,因为这样recyclerView会在展示的时候立刻展示所有内容,效率极低。

本文的两部分代码来自一个博主的博客,另一个是我自己写的,正好可以完全适用于现有的layoutmanager。大家需要的话可以试试,应该问题不大。

原博主的demo:https://github.com/Frank-Zhu/AndroidRecyclerViewDemo

1.LinearLayoutManager和ScrollView嵌套

  1. package com.frankzhu.recyclerviewdemo;
  2.  
  3. import android.content.Context;
  4. import android.support.v7.widget.LinearLayoutManager;
  5. import android.support.v7.widget.RecyclerView;
  6. import android.util.Log;
  7. import android.view.View;
  8. import android.view.ViewGroup;
  9.  
  10. /**
  11. * Author: ZhuWenWu
  12. * Version V1.0
  13. * Date: 2015/2/26 14:15.
  14. * Description:
  15. * Modification History:
  16. * Date Author Version Description
  17. * -----------------------------------------------------------------------------------
  18. * 2015/2/26 ZhuWenWu 1.0 1.0
  19. * Why & What is modified:
  20. */
  21. public class FullyLinearLayoutManager extends LinearLayoutManager {
  22.  
  23. private static final String TAG = FullyLinearLayoutManager.class.getSimpleName();
  24.  
  25. public FullyLinearLayoutManager(Context context) {
  26. super(context);
  27. }
  28.  
  29. public FullyLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
  30. super(context, orientation, reverseLayout);
  31. }
  32.  
  33. private int[] mMeasuredDimension = new int[2];
  34.  
  35. @Override
  36. public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state,
  37. int widthSpec, int heightSpec) {
  38.  
  39. final int widthMode = View.MeasureSpec.getMode(widthSpec);
  40. final int heightMode = View.MeasureSpec.getMode(heightSpec);
  41. final int widthSize = View.MeasureSpec.getSize(widthSpec);
  42. final int heightSize = View.MeasureSpec.getSize(heightSpec);
  43.  
  44. Log.i(TAG, "onMeasure called. \nwidthMode " + widthMode
  45. + " \nheightMode " + heightSpec
  46. + " \nwidthSize " + widthSize
  47. + " \nheightSize " + heightSize
  48. + " \ngetItemCount() " + getItemCount());
  49.  
  50. int width = 0;
  51. int height = 0;
  52. for (int i = 0; i < getItemCount(); i++) {
  53. measureScrapChild(recycler, i,
  54. View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
  55. View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
  56. mMeasuredDimension);
  57.  
  58. if (getOrientation() == HORIZONTAL) {
  59. width = width + mMeasuredDimension[0];
  60. if (i == 0) {
  61. height = mMeasuredDimension[1];
  62. }
  63. } else {
  64. height = height + mMeasuredDimension[1];
  65. if (i == 0) {
  66. width = mMeasuredDimension[0];
  67. }
  68. }
  69. }
  70. switch (widthMode) {
  71. case View.MeasureSpec.EXACTLY:
  72. width = widthSize;
  73. case View.MeasureSpec.AT_MOST:
  74. case View.MeasureSpec.UNSPECIFIED:
  75. }
  76.  
  77. switch (heightMode) {
  78. case View.MeasureSpec.EXACTLY:
  79. height = heightSize;
  80. case View.MeasureSpec.AT_MOST:
  81. case View.MeasureSpec.UNSPECIFIED:
  82. }
  83.  
  84. setMeasuredDimension(width, height);
  85. }
  86.  
  87. private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec,
  88. int heightSpec, int[] measuredDimension) {
  89. try {
  90. View view = recycler.getViewForPosition(0);//fix 动态添加时报IndexOutOfBoundsException
  91.  
  92. if (view != null) {
  93. RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams();
  94.  
  95. int childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec,
  96. getPaddingLeft() + getPaddingRight(), p.width);
  97.  
  98. int childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec,
  99. getPaddingTop() + getPaddingBottom(), p.height);
  100.  
  101. view.measure(childWidthSpec, childHeightSpec);
  102. measuredDimension[0] = view.getMeasuredWidth() + p.leftMargin + p.rightMargin;
  103. measuredDimension[1] = view.getMeasuredHeight() + p.bottomMargin + p.topMargin;
  104. recycler.recycleView(view);
  105. }
  106. } catch (Exception e) {
  107. e.printStackTrace();
  108. } finally {
  109. }
  110. }
  111. }

2.GridLayoutManager和ScrollView进行嵌套

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

3.StaggeredGridLayoutManager和ScrollView进行嵌套

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

RecyclerView和ScrollView嵌套使用的更多相关文章

  1. Android RecyclerView和ScrollView嵌套使用

    我们的recyclerView有多个layoutmanager,通过重写layoutmanager的方法就可以让recyclerView和ScrollView嵌套了.但是请注意,如果recyclerV ...

  2. ScrollView嵌套RecyclerView、ScrollView嵌套Listview、ScrollView嵌套各种布局,默认不在顶部和回到顶部的解决方法;

    如果: ScrollView.scrollTo(0,0): ScrollView.fullScroll(View.FOCUS_UP) : ScrollView.smoothScrollTo(0, 0) ...

  3. scrollview嵌套下拉控件嵌套recyclerview(不动第三方原基础自定义)

    相信会碰到很多类似的需求,一个列表控件,然后控件上方的一个头部需要自定义,这样就不好有时候也不能加在列表控件的头部了,那必须得嵌套一层scrollview了,没毛病,那么一般的列表控件都是有上拉下拉的 ...

  4. ScrollView嵌套RecyclerView时滑动出现的卡顿

    原文连接:http://zhanglu0574.blog.163.com/blog/static/113651073201641853532259/   现象: 一个界面有多个RecyclerView ...

  5. [Android Pro] ScrollView嵌套RecyclerView时滑动出现的卡顿

    reference to : http://zhanglu0574.blog.163.com/blog/static/113651073201641853532259/ ScrollView嵌套Rec ...

  6. Scrollview 嵌套 RecyclerView 及在Android 5.1版本滑动时 惯性消失问题

    标签:scrollview   android   滑动   嵌套 scrollview 嵌套recyclerview 时,recyclerview不显示,这就需要我们自己计算recyclerview ...

  7. 解决Scrollview 嵌套recyclerview不能显示,高度不正常的问题

    我们先看一个效果,问题说的就是中间的Grid效果在Scrollview 嵌套recyclerview显示问题,在Android Api 24是好的,不过在5,1,1版本(api 22)缺出现了问题 最 ...

  8. 解决ScrollView嵌套RecyclerView出现item显示不全的问题

      问题:ScrollView嵌套RecyclerView时,RecyclerView的item显示不全 出现问题不要慌,耐心解决才是王道,哈哈.首先说下出现这个问题的情景吧,首先声明这个问题在23版 ...

  9. 解决ScrollView嵌套RecyclerView的显示及滑动问题

        项目中时常需要实现在ScrollView中嵌入一个或多个RecyclerView.这一做法通常会导致如下几个问题 页面滑动卡顿 ScrollView高度显示不正常 RecyclerView内容 ...

随机推荐

  1. 解决访问StackOverFlow太慢的问题

    Stackoverflow加载时访问了被屏蔽的站点ajax.googleapis.com,导致加载缓慢,把这个站点加到Hosts里,指向127.0.0.1即可

  2. 搭建WebRtc环境

    0.前言 这次的需求,准备做的是一个类似与QQ视频一样的点对点视频聊天.这几天了解了一些知识后,决定使用HTML5新支持的WebRtc来作为视频通讯.客户端使用支持HTML5浏览器即可.服务器段需要提 ...

  3. css3 画圆记录

    <style> .radar-wrapper * { -moz-box-sizing: border-box; box-sizing: border-box; margin:; paddi ...

  4. Asp.net Mvc4 使用Cas单点登录

    因项目需要,使用了耶鲁大学的Cas单点登录方案,在java中使用一直正常,但是在.Net中碰到了循环重定向的问题,反复测试后,总算解决了,最终的配置如下: <?xml version=" ...

  5. 快乐的JS正则表达式(一)

    上一篇介绍了为什么需要正则,那从这一篇开始我们就去学习如何使用正则. 在js中有两种方式创建正则表达式: var reg = new RegExp("表达式","可选规则 ...

  6. eclipse开发web应用程序步骤(图解)

    *运行环境(也就是服务器的选择) 环境搭建好之后开始编写web程序!然后右键->Run as -> Run on Server!

  7. keepalived程序包

    keepalived自带两个程序包 1. keepalived守护进程 [root@lvs /root]# keepalived –-helpkeepalived Version 0.6.1 (06/ ...

  8. 链表的实现(Java语言描述)

    代码如下: public interface ListInterface<T> { public T getElem(int i); public boolean insertElem(i ...

  9. SQL Server里的INTERSECT ALL

    在上一篇文章里,我讨论了INTERSECT设置操作的基础,它和INNER JOIN的区别,还有为什么需要好的索引设计支持.今天我想谈下SQL Server里并未实现的INTERSECT ALL操作. ...

  10. .NET C# 使用S22.Imap.dll接收邮件 并且指定收取的文件夹的未读邮件,并且更改未读准态

    string host = Conf.ConfigInfo.POP_Host; int port = Conf.ConfigInfo.POP_Port; string username =Conf.C ...