我想谷歌工程师在设计recycleview时,肯定不希望上级布局是个scrollview,不符合他们的设计精神吧。不过现实开发中,有些情况不是程序员可以左右的,只有按照产品经理的思路实现才是王道,而且是快速开发情况下,没有比scrollview嵌套recyclerview来的更方便了。
问题一:scrollview中嵌套多个recyclerview,有的全部展开了,有的不能全部展开的情况。
处理方式::1. 重写scrollview
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
import android.widget.ScrollView;
/**
* @author hahaliu
* @date 2018/12/13 0013
* @annotate 嵌套Recycleview的Scrollview
*/
public class RecyclerScrollView extends ScrollView {
private int slop;
private int touch;
public RecyclerScrollView(Context context) {
super(context);
setSlop(context);
}
public RecyclerScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
setSlop(context);
}
public RecyclerScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setSlop(context);
}
/**
* 是否intercept当前的触摸事件
* @param ev 触摸事件
* @return true:调用onMotionEvent()方法,并完成滑动操作
*/
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
// 保存当前touch的纵坐标值
touch = (int) ev.getRawY();
break;
case MotionEvent.ACTION_MOVE:
// 滑动距离大于slop值时,返回true
if (Math.abs((int) ev.getRawY() - touch) > slop) return true;
break;
}
return super.onInterceptTouchEvent(ev);
}
/**
* 获取相应context的touch slop值(即在用户滑动之前,能够滑动的以像素为单位的距离)
* @param context ScrollView对应的context
*/
private void setSlop(Context context) {
slop = ViewConfiguration.get(context).getScaledTouchSlop();
}
}
2. 在recyclerview外面加一层relativelayout布局
问题二:recyleview不仅可以竖向滑动,也可以横向滑动,一般处理方式是在竖向的recyclerview外面加一层HorizontalScrollView,但是在很多手机上面还是不能横向滑动
处理方式:复写HorizontalScrollView
import android.content.Context;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.HorizontalScrollView;
/**
* @author hahaliu
* @ClassName MyHorizontalScrollView
* @Description
* @date 2018-10-08
*/
public class MyHorizontalScrollView extends HorizontalScrollView {
public MyHorizontalScrollView(Context context) {
super(context);
}
public MyHorizontalScrollView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public MyHorizontalScrollView(Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
private float lastX, lastY;
@Override
public boolean onInterceptTouchEvent(MotionEvent e) {
boolean intercept = super.onInterceptTouchEvent(e);
switch (e.getAction()) {
case MotionEvent.ACTION_DOWN:
lastX = e.getX();
lastY = e.getY();
break;
case MotionEvent.ACTION_MOVE:
// 只要横向大于竖向,就拦截掉事件。
// 部分机型点击事件(slopx==slopy==0),会触发MOVE事件。
// 所以要加判断(slopX > 0 || sloy > 0)
float slopX = Math.abs(e.getX() - lastX);
float slopY = Math.abs(e.getY() - lastY);
if((slopX > 0 || slopY > 0) && slopX >= slopY){
requestDisallowInterceptTouchEvent(true);
intercept = true;
}
break;
case MotionEvent.ACTION_UP:
intercept = false;
break;
}
return intercept;
}
}
本人项目中就是这么解决的这些问题的,不知道你的项目中怎样处理这些问题?
原理有兴趣的同学自己看一下代码,没有时间的直接copy开车