将RecyclerView的行为滚动到垂直视图寻呼机中
我正在使用VerticalViewPager和其中的两个片段.
I am using VerticalViewPager and two fragments in it.
其中一个片段包含带有常规垂直列表的RecyclerView. 问题是我需要此列表才能结束,然后在视图分页器中更改页面,现在视图分页器始终尝试拦截RecyclerView滚动.
One of this fragment contains RecyclerView with just regular vertical list. The problem is that I need this list to get to end and then change page at view pager and now view pager always try to intercept RecyclerView scroll.
我的VerticalViewPager类:
My VerticalViewPager class:
public class VerticalViewPager extends ViewPager {
public VerticalViewPager(Context context) {
super(context);
init();
}
public VerticalViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
setPageTransformer(true, new VerticalPageTransformer());
setOverScrollMode(OVER_SCROLL_NEVER);
requestDisallowInterceptTouchEvent(false);
}
private class VerticalPageTransformer implements ViewPager.PageTransformer {
@Override
public void transformPage(View view, float position) {
if (position < -1) {
view.setAlpha(0);
} else if (position <= 1) {
view.setAlpha(1);
view.setTranslationX(view.getWidth() * -position);
float yPosition = position * view.getHeight();
view.setTranslationY(yPosition);
} else {
view.setAlpha(0);
}
}
}
private MotionEvent swapXY(MotionEvent ev) {
float width = getWidth();
float height = getHeight();
float newX = (ev.getY() / height) * width;
float newY = (ev.getX() / width) * height;
ev.setLocation(newX, newY);
return ev;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean intercepted = super.onInterceptTouchEvent(swapXY(ev));
swapXY(ev);
return intercepted;
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
return super.onTouchEvent(swapXY(ev));
}
}
还有我的布局树:
- -片段
- -ViewPager
- --- Fragment_A
- ---- RecyclerView
- --- Fragment_B
我已经尝试过
.setNestedScrollingEnabled(false/true);
.requestDisallowInterceptTouchEvent(false/true);
试图用NestedScrollView包装RecyclerView,但是滚动仍然杂乱无章,ViewPager会在列表的开头或中间更改其页面.
Tried to wrap RecyclerView with NestedScrollView, but scroll is still messy and laggy, ViewPager change its page at the list beginning or in the middle.
感谢您的帮助!
我通过为RecyclerView编写自定义OnTouchListener来解决这个问题:
I figure it with writing custom OnTouchListener for my RecyclerView:
public class VerticalTouchListener implements View.OnTouchListener {
private float lastMotionY = Float.MIN_VALUE;
private float downY = Float.MIN_VALUE;
private final OnScrollableViewPager scrollableViewPager;
public VerticalTouchListener(@NonNull OnScrollableViewPager scrollableViewPager) {
this.scrollableViewPager = scrollableViewPager;
}
@Override
public boolean onTouch(@NonNull View v, @NonNull MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
downY = event.getRawY();
break;
case MotionEvent.ACTION_MOVE:
if (downY == Float.MIN_VALUE && lastMotionY == Float.MIN_VALUE) {
downY = event.getRawY();
break;
}
float diff = event.getRawY() - (lastMotionY == Float.MIN_VALUE ? downY : lastMotionY);
lastMotionY = event.getRawY();
if (scrollableViewPager.getScrollX() != scrollableViewPager.getBaseScrollX()) {
if (fakeDragVp(v, event, diff)) return true;
} else {
if (ViewCompat.canScrollVertically(v, (-diff) > 0 ? 1 : -1)) {
break;
} else {
scrollableViewPager.beginFakeDrag();
fakeDragVp(v, event, diff);
adjustDownMotion(v, event);
return true;
}
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
if (scrollableViewPager.isFakeDragging()) {
try {
scrollableViewPager.endFakeDrag();
} catch (Exception e) {
e.printStackTrace();
}
}
reset();
break;
}
return false;
}
private boolean fakeDragVp(@NonNull View v, @NonNull MotionEvent e, float diff) {
if (scrollableViewPager.isFakeDragging()) {
float step = diff;
int expScrollX = (int) (scrollableViewPager.getScrollX() - step);
if (isDiffSign(expScrollX - scrollableViewPager.getBaseScrollX(), scrollableViewPager.getScrollX() - scrollableViewPager.getBaseScrollX())) {
step = scrollableViewPager.getScrollX() - scrollableViewPager.getBaseScrollX();
}
scrollableViewPager.fakeDragBy(step);
adjustDownMotion(v, e);
return true;
}
return false;
}
private void adjustDownMotion(@NonNull View v, @NonNull MotionEvent e) {
MotionEvent fakeDownEvent = MotionEvent.obtain(e);
fakeDownEvent.setAction(MotionEvent.ACTION_DOWN);
v.dispatchTouchEvent(fakeDownEvent);
}
private boolean isDiffSign(float a, float b) {
return Math.abs(a + b) < Math.abs(a - b);
}
private void reset() {
downY = Float.MIN_VALUE;
lastMotionY = Float.MIN_VALUE;
}
public interface OnScrollableViewPager {
int getScrollX();
int getBaseScrollX();
boolean isFakeDragging();
boolean beginFakeDrag();
void fakeDragBy(float step);
void endFakeDrag();
}
}
并更改了我的VerticalViewPager:
and changed my VerticalViewPager:
public class VerticalViewPager extends ViewPager implements VerticalTouchListener.OnScrollableViewPager {
private int baseScrollX;
public VerticalViewPager(@NonNull Context context) {
super(context);
init();
}
public VerticalViewPager(@NonNull Context context, @NonNull AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
setPageTransformer(false, new VerticalTransformer());
setOverScrollMode(OVER_SCROLL_NEVER);
addOnPageChangeListener(new SimpleOnPageChangeListener() {
@Override
public void onPageScrollStateChanged(int state) {
super.onPageScrollStateChanged(state);
if (state == ViewPager.SCROLL_STATE_IDLE) {
baseScrollX = getScrollX();
}
}
});
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
return false;
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
return super.onTouchEvent(swapXY(ev));
}
@Override
public int getBaseScrollX() {
return baseScrollX;
}
private MotionEvent swapXY(MotionEvent ev) {
float width = getWidth();
float height = getHeight();
float newX = (ev.getY() / height) * width;
float newY = (ev.getX() / width) * height;
ev.setLocation(newX, newY);
return ev;
}
private class VerticalTransformer implements ViewPager.PageTransformer {
@Override
public void transformPage(@NonNull View view, float position) {
float alpha = 0;
if (0 <= position && position <= 1) {
alpha = 1 - position;
} else if (-1 < position && position < 0) {
alpha = position + 1;
}
view.setAlpha(alpha);
view.setTranslationX(view.getWidth() * -position);
view.setTranslationY(position * view.getHeight());
}
}
}
此回购对我有一点帮助.