Android RecyclerView和ScrollView嵌套使用
我们的recyclerView有多个layoutmanager,通过重写layoutmanager的方法就可以让recyclerView和ScrollView嵌套了。但是请注意,如果recyclerView很长那么强烈不建议去做嵌套,因为这样recyclerView会在展示的时候立刻展示所有内容,效率极低。
本文的两部分代码来自一个博主的博客,另一个是我自己写的,正好可以完全适用于现有的layoutmanager。大家需要的话可以试试,应该问题不大。
原博主的demo:https://github.com/Frank-Zhu/AndroidRecyclerViewDemo
1.LinearLayoutManager和ScrollView嵌套
package com.frankzhu.recyclerviewdemo;import android.content.Context; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.util.Log; import android.view.View; import android.view.ViewGroup;/*** Author: ZhuWenWu* Version V1.0* Date: 2015/2/26 14:15.* Description:* Modification History:* Date Author Version Description* -----------------------------------------------------------------------------------* 2015/2/26 ZhuWenWu 1.0 1.0* Why & What is modified:*/ public class FullyLinearLayoutManager extends LinearLayoutManager {private static final String TAG = FullyLinearLayoutManager.class.getSimpleName();public FullyLinearLayoutManager(Context context) {super(context);}public FullyLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {super(context, orientation, reverseLayout);}private int[] mMeasuredDimension = new int[2];@Overridepublic 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 动态添加时报IndexOutOfBoundsExceptionif (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 {}} }
2.GridLayoutManager和ScrollView进行嵌套
package com.frankzhu.recyclerviewdemo;import android.content.Context; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.View; import android.view.ViewGroup;/*** Author: ZhuWenWu* Version V1.0* Date: 2015/2/26 14:14.* Description:* Modification History:* Date Author Version Description* -----------------------------------------------------------------------------------* 2015/2/26 ZhuWenWu 1.0 1.0* Why & What is modified:*/ public class FullyGridLayoutManager extends GridLayoutManager {public FullyGridLayoutManager(Context context, int spanCount) {super(context, spanCount);}public FullyGridLayoutManager(Context context, int spanCount, int orientation, boolean reverseLayout) {super(context, spanCount, orientation, reverseLayout);}private int[] mMeasuredDimension = new int[2];@Overridepublic 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);int width = 0;int height = 0;int count = getItemCount();int span = getSpanCount();for (int i = 0; i < count; i++) {measureScrapChild(recycler, i,View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),mMeasuredDimension);if (getOrientation() == HORIZONTAL) {if (i % span == 0) {width = width + mMeasuredDimension[0];}if (i == 0) {height = mMeasuredDimension[1];}} else {if (i % span == 0) {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) {if (position < getItemCount()) {try {View view = recycler.getViewForPosition(0);//fix 动态添加时报IndexOutOfBoundsExceptionif (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();}}} }
3.StaggeredGridLayoutManager和ScrollView进行嵌套
package com.kale.waterfalldemo.extra.RecyclerView;import android.support.v7.widget.RecyclerView; import android.support.v7.widget.StaggeredGridLayoutManager; import android.view.View; import android.view.ViewGroup;/*** @author Jack Tony* @brief 不规则排列(类似于瀑布流)的布局管理器* @date 2015/4/6*/ public class ExStaggeredGridLayoutManager extends StaggeredGridLayoutManager {public ExStaggeredGridLayoutManager(int spanCount, int orientation) {super(spanCount, orientation);}// 尺寸的数组,[0]是宽,[1]是高private int[] measuredDimension = new int[2];// 用来比较同行/列那个item罪宽/高private int[] dimension;@Overridepublic void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state, int widthSpec, int heightSpec) {// 宽的mode+sizefinal int widthMode = View.MeasureSpec.getMode(widthSpec);final int widthSize = View.MeasureSpec.getSize(widthSpec);// 高的mode + sizefinal int heightMode = View.MeasureSpec.getMode(heightSpec);final int heightSize = View.MeasureSpec.getSize(heightSpec);// 自身宽高的初始值int width = 0;int height = 0;// item的数目int count = getItemCount();// item的列数int span = getSpanCount();// 根据行数或列数来创建数组dimension = new int[span];for (int i = 0; i < count; i++) {measureScrapChild(recycler, i,View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED), measuredDimension);// 如果是竖直的列表,计算item的高,否则计算宽度//Log.d("LISTENER", "position " + i + " height = " + measuredDimension[1]);if (getOrientation() == VERTICAL) {dimension[findMinIndex(dimension)] += measuredDimension[1];} else {dimension[findMinIndex(dimension)] += measuredDimension[0];}}if (getOrientation() == VERTICAL) {height = findMax(dimension);} else {width = findMax(dimension);}switch (widthMode) {// 当控件宽是match_parent时,宽度就是父控件的宽度case View.MeasureSpec.EXACTLY:width = widthSize;break;case View.MeasureSpec.AT_MOST:break;case View.MeasureSpec.UNSPECIFIED:break;}switch (heightMode) {// 当控件高是match_parent时,高度就是父控件的高度case View.MeasureSpec.EXACTLY:height = heightSize;break;case View.MeasureSpec.AT_MOST:break;case View.MeasureSpec.UNSPECIFIED:break;}// 设置测量尺寸 setMeasuredDimension(width, height);}private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec,int heightSpec, int[] measuredDimension) {// 挨个遍历所有itemif (position < getItemCount()) {try {View view = recycler.getViewForPosition(position);//fix 动态添加时报IndexOutOfBoundsExceptionif (view != null) {RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams) view.getLayoutParams();int childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec, getPaddingLeft() + getPaddingRight(), lp.width);int childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec, getPaddingTop() + getPaddingBottom(), lp.height);// 子view进行测量,然后可以通过getMeasuredWidth()获得测量的宽,高类似 view.measure(childWidthSpec, childHeightSpec);// 将item的宽高放入数组中measuredDimension[0] = view.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;measuredDimension[1] = view.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;recycler.recycleView(view);}} catch (Exception e) {e.printStackTrace();}}}private int findMax(int[] array) {int max = array[0];for (int value : array) {if (value > max) {max = value;}}return max;}/*** 得到最数组中最小元素的下标** @param array* @return*/private int findMinIndex(int[] array) {int index = 0;int min = array[0];for (int i = 0; i < array.length; i++) {if (array[i] < min) {min = array[i];index = i;}}return index;}}
Android RecyclerView和ScrollView嵌套使用相关推荐
- Android之解决ScrollView嵌套RecycleView导致滑动冲突或者显示不全的问题
1 问题 ScrollView嵌套RecycleView导致滑动冲突或者显示不全的问题 2 解决办法 1).ScrollView替换成普通布局,然后RecycleView用的BaseMultiItem ...
- [转]Android笔记:ScrollView嵌套ViewPager的滚动冲突解决方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 /** * ...
- android list嵌套list,Android开发日常-listVIiew嵌套webView回显阅读位置
详情页布局结构 需求是回显webview展示网页的阅读位置 方案1: 使用webview.getScrollY()获取滑动到的位置,用setScrollY()回显设置, 但是两个方法都出现了问题,ge ...
- 【Android】ListView、RecyclerView、ScrollView里嵌套ListView 相对优雅的解决方案:NestFullListView
一 背景概述: ScrollView里嵌套ListView,一直是Android开发者(反正至少是我们组)最讨厌的设计之一,完美打破ListView(RecyclerView)的复用机制,成功的将Na ...
- Android Scrollview嵌套RecyclerView导致滑动卡顿问题解决(屡试不爽)
今天开发的一个项目首页,布局还是比较复杂的,各种滑动冲突,(Banner+横向RecyclerView+纵向RecyclerView(item又是横向的RecyclerView)), 最外面的框架用 ...
- NestedScrollView/ScrollView嵌套Recyclerview,导致Recyclerview抢占焦点,置顶了, 修改好后,引起Edittext又不能点击问题处理
NestedScrollView/ScrollView嵌套Recyclerview,导致Recyclerview抢占焦点,置顶了, 修改好后,引起Edittext又不能点击问题处理 NestedScr ...
- 【Android 手势冲突】Colin带你彻底解决RecyclerView与ScrollView滑动冲突问题,并实现RecyclerView悬停导航栏(附demo哦)
在新一期的需求中,产品要求我们做出和美团某个页面类似的功能,即一个页面包含在scrollView中,上面一个部分放置一些常用的广告banner.宫格tab等,下面放置一个RecyclerView用于展 ...
- android中ScrollView嵌套ListView或GridView显示位置问题
Android中ScrollView中嵌套ListView或GridView时在开始进入界面时总是显示中间位置,开头的位置显示不出来.这种情况下只需要在ScrollView的父控件中添加以下两行代码即 ...
- 在android中ScrollView嵌套ScrollView解决方案
文章转载自:http://www.jb51.net/article/33054.htm 大家好,众所周知,android里两个相同方向的ScrollView是不能嵌套的,那要是有这样的需求怎么办,接下 ...
最新文章
- 查看磁盘空间,清理缓存
- c#后台修改前台DOM的css属性
- struts2 action重定向
- 《大话操作系统——做坚实的project实践派》(6)
- 2019最新 Java商城秒杀系统的设计与实战视频教程(SpringBoot版)
- 微信开发实现一键拨号出现屏蔽问题的解决方案
- 恒大汽车向技术人员等授出3.24亿股购股权:占公司股本的3.31%
- Err:error occurred at recursive SQL level 1
- JavaEye被CSDN收购
- c语言编程技术列表,C语言系统编程技术点
- 删除讨厌的4199流氓软件
- 1 0.99999的悖论_天文学科普:带你了解反物质、费米悖论和黑洞
- 怎么恢复360删除的文件?360文件恢复,快速完成
- System.DllNotFoundException: Unable to load DLL 'XX.dll': 找不到指定的模块。 (Exception from HRESULT:
- IPv6的TSO/GRO/GSO及其Linux实现的不妥
- Endnote下载的pdf文件合并到同一个文件夹
- 助力中国“智”造,携客云SRM“好产品”是如何炼成的?
- 计算机类专业中对数学物理要求低的,哪些专业对数学和物理要求比较高
- 谈一谈网络编程学习经验(陈硕)
- win10 smb共享硬盘
热门文章
- echarts中x轴文字过长换行处理和倾斜处理。
- Vue采用input实现文件上传与删除
- 终端报错xcrun: error: unable to find utility “xcodebuild”, not a developer tool or
- React+Redux仿Web追书神器
- commons-csv 使用记叙
- MySql字符串函数使用技巧
- asp.net(c#)将彩色图片变灰阶图片
- 搭建discuz论坛
- 推荐一款生成SQL插入语句的软件
- catboost进行分类并开启GPU模式