Как реализовать жест Fling в viewpager
Я разрабатываю одно приложение для Android, в котором приложение работает отлично, я хочу реализовать жест FLING также для того, чтобы сделать его эффективным, я получил пример кода для горизонтального перемещения, мне нужно изменить его на жест вертикального перемещения, может кто-нибудь помочь в этом, спасибо заблаговременно
public class VerticalViewPager extends ViewPager implements GestureDetector.OnGestureListener {
private GestureDetector mGestureDetector;
private FlingRunnable mFlingRunnable = new FlingRunnable();
private boolean mScrolling = false;
public VerticalViewPager(Context context) {
super(context);
init();
//setMyScroller();
}
public VerticalViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
mGestureDetector = new GestureDetector(context, this);
init();
}
private void init() {
// The majority of the magic happens here
setPageTransformer(true, new VerticalPageTransformer());
// The easiest way to get rid of the overscroll drawing that happens on the left and right
setOverScrollMode(OVER_SCROLL_NEVER);
}
private static class VerticalPageTransformer implements ViewPager.PageTransformer {
private static float MIN_SCALE = 0.95f;
@Override
public void transformPage(View view, float position) {
if (position < -1) { // [-Infinity,-1)
// This page is way off-screen to the left.
view.setAlpha(0);
}
else if (position <= 0) { // [-1,0]
view.setAlpha(1);
//view.setTranslationX(1);
view.setScaleX(1);
view.setScaleY(1);
float yPosition = position * view.getHeight();
view.setTranslationY(yPosition);
view.setTranslationX(-1 * view.getWidth() * position);
}
else if (position <= 1) { // [-1,1]
view.setAlpha(1-position);//fade in value
view.setTranslationX(-1 * view.getWidth() * position);
float scaleFactor=MIN_SCALE
+ (1 - MIN_SCALE) * (1 - Math.abs(position));
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
} else { // (1,+Infinity]
// This page is way off-screen to the right.
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;
//return super.onInterceptTouchEvent(swapXY(ev));
}
private void setMyScroller() {
try {
Class<?> viewpager = ViewPager.class;
Field scroller = viewpager.getDeclaredField("mScroller");
scroller.setAccessible(true);
scroller.set(this, new MyScroller(getContext()));
} catch (Exception e) {
e.printStackTrace();
}
}
public class MyScroller extends Scroller {
public MyScroller(Context context) {
super(context, new DecelerateInterpolator());
}
@Override
public void startScroll(int startX, int startY, int dx, int dy, int duration) {
super.startScroll(startX, startY, dx, dy, 200);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// give all the events to the gesture detector. I'm returning true here so the viewpager doesn't
// get any events at all, I'm sure you could adjust this to make that not true.
mGestureDetector.onTouchEvent(event);
return true;
//return false;
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velX, float velY) {
mFlingRunnable.startUsingVelocity((int)velX);
return false;
}
private void trackMotion(float distX) {
// The following mimics the underlying calculations in ViewPager
float scrollX = getScrollX() - distX;
final int width = getWidth();
final int widthWithMargin = width + this.getPageMargin();
final float leftBound = Math.max(0, (this.getCurrentItem() - 1) * widthWithMargin);
final float rightBound = Math.min(this.getCurrentItem() + 1, this.getAdapter().getCount() - 1) * widthWithMargin;
if (scrollX < leftBound) {
scrollX = leftBound;
// Now we know that we've hit the bound, flip the page
if (this.getCurrentItem() > 0) {
this.setCurrentItem(this.getCurrentItem() - 1, false);
}
}
else if (scrollX > rightBound) {
scrollX = rightBound;
// Now we know that we've hit the bound, flip the page
if (this.getCurrentItem() < (this.getAdapter().getCount() - 1) ) {
this.setCurrentItem(this.getCurrentItem() + 1, false);
}
}
// Do the fake dragging
if (mScrolling) {
this.fakeDragBy(distX);
}
else {
this.beginFakeDrag();
this.fakeDragBy(distX);
mScrolling = true;
}
}
private void endFlingMotion() {
mScrolling = false;
this.endFakeDrag();
}
private class FlingRunnable implements Runnable {
private Scroller mScroller; // use this to store the points which will be used to create the scroll
private int mLastFlingX;
private FlingRunnable() {
mScroller = new Scroller(getContext());
}
public void startUsingVelocity(int initialVel) {
Log.e("touch","touch");
if (initialVel == 0) {
// there is no velocity to fling!
return;
}
removeCallbacks(this); // stop pending flings
int initialX = initialVel < 0 ? Integer.MAX_VALUE : 0;
mLastFlingX = initialX;
// setup the scroller to calulate the new x positions based on the initial velocity. Impose no cap on the min/max x values.
mScroller.fling(initialX, 0, initialVel, 0, 0, Integer.MAX_VALUE, 0, Integer.MAX_VALUE);
post(this);
}
private void endFling() {
mScroller.forceFinished(true);
endFlingMotion();
}
@Override
public void run() {
final Scroller scroller = mScroller;
boolean animationNotFinished = scroller.computeScrollOffset();
final int x = scroller.getCurrX();
int delta = x - mLastFlingX;
trackMotion(delta);
if (animationNotFinished) {
mLastFlingX = x;
post(this);
}
else {
endFling();
}
}
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distX, float distY) {
trackMotion(-distX);
return false;
}
// Unused Gesture Detector functions below
@Override
public boolean onDown(MotionEvent event) {
return false;
}
@Override
public void onLongPress(MotionEvent event) {
// we don't want to do anything on a long press, though you should probably feed this to the page being long-pressed.
}
@Override
public void onShowPress(MotionEvent event) {
// we don't want to show any visual feedback
}
@Override
public boolean onSingleTapUp(MotionEvent event) {
// we don't want to snap to the next page on a tap so ignore this
return false;
}