RecyclerView进阶(1)
2016-05-20 14:37
288 查看
在之前用ListView的时候,如果ListView和ScrollView混着用的时候,就会产生滑动冲突,通常的解决措施是通过自定义ListView,重写其onMeasure,测量其高度让其不能滑动,然后就可以使用ScrollView的滑动了。
就像下边这样
那么问题来了,在RecyclerView中你是否依然可以这么做呢,当然不能,我么知道,RecyclerView是一种高度解耦的空间,出了适配器之外,他有一个布局管理器LayoutManager来管理
对于LayoutManager,RecyclerView本身提供了三个实现类,分别为:
1:LinearLayoutManger 水平/横屏布局
实现ListView和HorizontalListView的效果
manager.setOrientation(LinearLayoutManager.HORIZONTAL);
manager.setOrientation(LinearLayoutManager.VERTICAL);
2:GridLayoutManger 网格布局
实现类似GridView一样的功能
3:StagerGridLayoutManger 瀑布流布局
我们可以通过自定义布局管理器的方式来解决ScrollView和RecyclerView的滑动冲突
同时对ScrollView的事件分发时间进行处理onInterceptTouchEvent
Demo下载
就像下边这样
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE>>2, MeasureSpec.AT_MOST); super.onMeasure(widthMeasureSpec, expandSpec); }
那么问题来了,在RecyclerView中你是否依然可以这么做呢,当然不能,我么知道,RecyclerView是一种高度解耦的空间,出了适配器之外,他有一个布局管理器LayoutManager来管理
对于LayoutManager,RecyclerView本身提供了三个实现类,分别为:
1:LinearLayoutManger 水平/横屏布局
实现ListView和HorizontalListView的效果
manager.setOrientation(LinearLayoutManager.HORIZONTAL);
manager.setOrientation(LinearLayoutManager.VERTICAL);
2:GridLayoutManger 网格布局
实现类似GridView一样的功能
mRecyclerView.setLayoutManager(new GridLayoutManager(this,4)); //设置一行4列
3:StagerGridLayoutManger 瀑布流布局
mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL)); //设置RecyclerView布局管理器为2列垂直排布
我们可以通过自定义布局管理器的方式来解决ScrollView和RecyclerView的滑动冲突
package com.longyue.recyclerviewdemo2; import android.content.Context; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.util.AttributeSet; import android.util.Log; import android.view.View; import android.view.ViewGroup; /** * 计算适应高度 */ public class CustomLinearLayoutManager extends LinearLayoutManager { private int[] mMeasuredDimension = new int[2]; public CustomLinearLayoutManager(Context context) { super(context); } public CustomLinearLayoutManager(Context context, int orientation, boolean reverseLayout) { super(context, orientation, reverseLayout); } public CustomLinearLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } @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 = 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 动态添加时报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[0] = view.getMeasuredWidth() + p.leftMargin + p.rightMargin; measuredDimension[1] = view.getMeasuredHeight() + p.bottomMargin + p.topMargin; recycler.recycleView(view); } } catch (Exception e) { e.printStackTrace(); } finally { } } }
同时对ScrollView的事件分发时间进行处理onInterceptTouchEvent
package com.longyue.recyclerviewdemo2; import android.content.Context; import android.support.v4.widget.NestedScrollView; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.ViewConfiguration; /** * 自定义NestedScrollView */ public class CustomNestScrollView extends NestedScrollView{ private int downX; private int downY; private int mTouchSlop; public CustomNestScrollView(Context context) { super(context); mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); } public CustomNestScrollView(Context context, AttributeSet attrs) { super(context, attrs); mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); } public CustomNestScrollView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { int action = ev.getAction(); switch (action) { case MotionEvent.ACTION_DOWN: downX = (int) ev.getRawX(); downY = (int) ev.getRawY(); break; case MotionEvent.ACTION_MOVE: int moveY = (int) ev.getRawY(); if (Math.abs(moveY - downY) > mTouchSlop) { return true; } } return super.onInterceptTouchEvent(ev); } }
Demo下载
相关文章推荐
- bzoj3309: DZY Loves Math
- 机器人
- [转]THINKPHP--MVC模式
- LESS框架笔记
- Java 静态语句块、语句块、构造函数
- 欢迎使用CSDN-markdown编辑器
- UI
- 三、kafka主要配置
- VS2010+Opencv-2.4.10环境配置
- 搭建私有云的5大主流方案
- Android Studio在连接手机时候,出现"Instant Run requires 'Tools..."不能安装软件的问题
- 运行tomcat6w.exe ,提示 指定的服务未安装 unable to open the service 'tomcat6'
- 关于线程同步(5种同步方式)
- 数据库乱码问题
- HDFS文件存储组织
- Abdroid ScrollView镶嵌ListView
- demo_电话录音_Service
- OGNL中$、%、#、{}、^、$ 标签的使用简介
- shareSDK2.x第三方登录遇到的坑
- ehcache 缓存使用