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都是滑动控件 ...
随机推荐
- Default Document <defaultDocument> IIS中的默认页面
https://docs.microsoft.com/en-us/iis/configuration/system.webserver/defaultdocument/index Default do ...
- window如何在命令行关掉端口
欢迎加入前端交流群来py:749539640 进入cmd netstat -ano | findstr :yourPortNumber taskkill /PID typeyourPIDhere ...
- SQL控制语句基础
SQL变量 全局变量: 全局变量是由系统定义和维护的使用两个@作为前缀,不能由用户声明和赋值! 常用的全局变量如下 @@version :获取当前使用的SQL Server版本号 EG: select ...
- asp.net HTTP请求过程
http://blog.csdn.net/zxxSsdsd/article/details/51909860
- POJ 2029 Get Many Persimmon Trees 【 二维树状数组 】
题意:给出一个h*w的矩形,再给出n个坐标,在这n个坐标种树,再给出一个s*t大小的矩形,问在这个s*t的矩形里面最多能够得到多少棵树 二维的树状数组,求最多能够得到的树的时候,因为h,w都不超过50 ...
- RMAN删除归档脚本
crosscheck archivelog all; delete noprompt expired archivelog all; delete noprompt archivelog un ...
- 解决vuex刷新页面数据丢失
1.前言 vue构建的项目中,vuex的状态存储是响应式的,当vue组件从store中读取状态的时候,若store中的状态发生变化,那么相应的组件也会得到高效刷新,问题来了,vuex存储的数据只是在页 ...
- 滴滴云安装mysql数据库
Linux CentOS安装配置MySQL数据库 没什么好说的,直接正面刚吧. 安装mysql数据库 a)下载mysql源安装包:wget http://dev.mysql.com/get/mys ...
- Url 简单讲解
eg: http://sb.test.com/login?name=liming&password=twotigers 协议 http https ftp 域名 sb.test.com 则是域 ...
- 【PRML学习笔记】第四章:分类的线性模型
一.基础概念 线性分类模型:决策面(decision boundary)是输入向量的线性函数 目标类别的表示"1 of K" :$ t = (0,1,0,0,0)^T$ 二.分类问 ...