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[]; @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 = ;
int height = ;
for (int i = ; 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[];
if (i == ) {
height = mMeasuredDimension[];
}
} else {
height = height + mMeasuredDimension[];
if (i == ) {
width = mMeasuredDimension[];
}
}
}
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();//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[] = view.getMeasuredWidth() + p.leftMargin + p.rightMargin;
measuredDimension[] = 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[]; @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); int width = ;
int height = ;
int count = getItemCount();
int span = getSpanCount();
for (int i = ; 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 == ) {
width = width + mMeasuredDimension[];
}
if (i == ) {
height = mMeasuredDimension[];
}
} else {
if (i % span == ) {
height = height + mMeasuredDimension[];
}
if (i == ) {
width = mMeasuredDimension[];
}
}
} 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();//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[] = view.getMeasuredWidth() + p.leftMargin + p.rightMargin;
measuredDimension[] = 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[]; // 用来比较同行/列那个item罪宽/高
private int[] dimension; @Override public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state, int widthSpec, int heightSpec) {
// 宽的mode+size
final int widthMode = View.MeasureSpec.getMode(widthSpec);
final int widthSize = View.MeasureSpec.getSize(widthSpec);
// 高的mode + size
final int heightMode = View.MeasureSpec.getMode(heightSpec);
final int heightSize = View.MeasureSpec.getSize(heightSpec); // 自身宽高的初始值
int width = ;
int height = ;
// item的数目
int count = getItemCount();
// item的列数
int span = getSpanCount();
// 根据行数或列数来创建数组
dimension = new int[span]; for (int i = ; 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[];
} else {
dimension[findMinIndex(dimension)] += measuredDimension[];
}
}
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) { // 挨个遍历所有item
if (position < getItemCount()) {
try {
View view = recycler.getViewForPosition(position);//fix 动态添加时报IndexOutOfBoundsException if (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[] = view.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
measuredDimension[] = view.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
recycler.recycleView(view);
}
} catch (Exception e) {
e.printStackTrace();
}
}
} private int findMax(int[] array) {
int max = array[];
for (int value : array) {
if (value > max) {
max = value;
}
}
return max;
} /**
* 得到最数组中最小元素的下标
*
* @param array
* @return
*/
private int findMinIndex(int[] array) {
int index = ;
int min = array[];
for (int i = ; i < array.length; i++) {
if (array[i] < min) {
min = array[i];
index = i;
}
}
return index;
} }
Android RecyclerView和ScrollView嵌套使用的更多相关文章
- RecyclerView和ScrollView嵌套使用
我们的recyclerView有多个layoutmanager,通过重写layoutmanager的方法就可以让recyclerView和ScrollView嵌套了.但是请注意,如果recyclerV ...
- Android开发:ScrollView嵌套GridView的解决办法
Android开发:ScrollView嵌套GridView的解决办法 前些日子在开发中用到了需要ScrollView嵌套GridView的情况,由于这两款控件都自带滚动条,当他们碰到一起的时候便 ...
- ScrollView嵌套RecyclerView、ScrollView嵌套Listview、ScrollView嵌套各种布局,默认不在顶部和回到顶部的解决方法;
如果: ScrollView.scrollTo(0,0): ScrollView.fullScroll(View.FOCUS_UP) : ScrollView.smoothScrollTo(0, 0) ...
- scrollview嵌套下拉控件嵌套recyclerview(不动第三方原基础自定义)
相信会碰到很多类似的需求,一个列表控件,然后控件上方的一个头部需要自定义,这样就不好有时候也不能加在列表控件的头部了,那必须得嵌套一层scrollview了,没毛病,那么一般的列表控件都是有上拉下拉的 ...
- Scrollview 嵌套 RecyclerView 及在Android 5.1版本滑动时 惯性消失问题
标签:scrollview android 滑动 嵌套 scrollview 嵌套recyclerview 时,recyclerview不显示,这就需要我们自己计算recyclerview ...
- Android在开发中的使用技巧之解决ScrollView嵌套RecyclerView出现的系列问题
根据已上线的app里总结出来的实用小技巧 相信大家都遇到过ScrollView嵌套RecyclerView或者RecyclerView嵌套RecyclerView来使用, 也会遇到一堆奇奇怪怪的问题, ...
- (转载) Scrollview 嵌套 RecyclerView 及在Android 5.1版本滑动时 惯性消失问题
Scrollview 嵌套 RecyclerView 及在Android 5.1版本滑动时 惯性消失问题 标签: scrollviewandroid滑动嵌套 2015-07-16 17:24 1112 ...
- [Android Pro] ScrollView嵌套RecyclerView时滑动出现的卡顿
reference to : http://zhanglu0574.blog.163.com/blog/static/113651073201641853532259/ ScrollView嵌套Rec ...
- Android Scrollview嵌套RecyclerView导致滑动卡顿问题解决
一个比较长的界面一般都是Scrollview嵌套RecyclerView来解决.不过这样的UI并不是我们开发人员想看到的,实际上嵌套之后.因为Scrollview和RecyclerView都是滑动控件 ...
随机推荐
- hdu1525 Euclid's Game , 基础博弈
http://acm.hdu.edu.cn/showproblem.php?pid=1525 题意: 两人博弈,给出两个数a和b, 较大数减去较小数的随意倍数.结果不能小于0,将两个数随意一个数减到0 ...
- android 处理Back键按下事件
package com.example.keyevent; import android.os.Bundle; import android.view.KeyEvent; import android ...
- (四)Hystrix容错保护
Feign默认是整合了Ribbon和Hystrix这两个框架,所以代码我们在上一篇的基础上进行修改,启动Eureka,service-hello,Feign 所谓的熔断机制和日常生活中见到电路保险丝是 ...
- webpack的像素转vw loader插件
这是一款针对webpack的像素转vw单位的loader插件. 笔者公司中,h5 rem的开发方案目前已经渐渐开始转向vw方案,因此本工具应运而生. 目前所制作的h5,大部分设计稿分辨率都是750的宽 ...
- python中的json
import json# dumps #一般处理字符串# dump #一般处理文件 #字符串和json之间的转换test_dict={"name":"fxh", ...
- iF.svnadmin 安装遇到的坑
iF.svnadmin 官网:http://svnadmin.insanefactory.com/ 安装配置iF.svnadmin : http://blog.linhere.com/archives ...
- CF666E Forensic Examination 广义后缀自动机_线段树合并_树上倍增
题意: 给定一个串 $S$ 和若干个串 $T_{i}$每次询问 $S[pl..pr]$ 在 $Tl..Tr$ 中出现的最多次数,以及出现次数最多的那个串的编号. 数据范围: 需要离线 题解:首先,很常 ...
- luogu P4018 Roy&October之取石子(博弈论)
题意 题解 如果n是6的倍数,先手必败,否则先手必胜. 因为6*x一定不是pk 所以取得话会变成6*y+a的形式a=1,2,3,4,5: 然后a一定为质数.我们把a取完就又成为了6*x的形式. 又因为 ...
- 2015 Multi-University Training Contest 2 hdu 5303 Delicious Apples
Delicious Apples Time Limit: 5000/3000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Other ...
- 低价购买 洛谷1108 codevs4748 dp
首先,,我相信第一问是可以做出来的,,,做不出来自行面壁思过,,, 第二问,我们可以发现,如果f[i]为1时应该将其g[i]初始化为1,当初就是因为这个wa了一个世纪,之后先考虑不需要判重时的情况,如 ...