我正在使用VerticalViewPager和两个片段。
此片段中的一个包含RecyclerView,只有常规垂直列表。 问题是我需要这个列表来结束然后在视图寻呼机上更改页面,现在查看寻呼机总是试图拦截RecyclerView滚动。
我的VerticalViewPager类:
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));
}
}
我的布局树:
我已经尝试过不同的
组合.setNestedScrollingEnabled(false/true);
.requestDisallowInterceptTouchEvent(false/true);
尝试使用NestedScrollView包装RecyclerView,但滚动仍然很混乱且滞后,ViewPager在列表的开头或中间更改其页面。
感谢您的帮助!
答案 0 :(得分:0)
我通过为RecyclerView编写自定义OnTouchListener来实现它:
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:
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());
}
}
}
这repo对我有所帮助。