参考了几篇代码,自己弄了一个带滑动反弹效果的ViewPager。
代码非常简单,主要原理就是随着手指的移动改变View的X坐标。
那么直接就简单粗暴地上代码了:
public class BounceBackViewPager extends ViewPager {
private int currentPosition = 0;
private boolean handleMove = false; //是否拦截并处理了滑动
private float preX = 0f;
private static final float RATIO = 0.25f;//摩擦系数
private boolean animPlaying = false;
private float translationX;
private static final int MIN_SCROLL_DISTANCE = 4;
public BounceBackViewPager(Context context) {
this(context, null);
}
public BounceBackViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
setOverScrollMode(View.OVER_SCROLL_NEVER);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch (ev.getAction()){
case MotionEvent.ACTION_DOWN:
preX = ev.getX();
currentPosition = getCurrentItem();
translationX = getTranslationX();
break;
case MotionEvent.ACTION_MOVE:
if(isOverScroll(ev)){
return true;
}
break;
}
return super.onInterceptTouchEvent(ev);
}
private boolean isOverScroll(MotionEvent event){
return (currentPosition == 0 && event.getX() > preX)
|| (getAdapter() != null && currentPosition == getAdapter().getCount() - 1 && event.getX() < preX);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
if (animPlaying || getAdapter() == null) {
return super.onTouchEvent(ev);
}
switch (ev.getAction()) {
case MotionEvent.ACTION_UP:
recoverPosition();
handleMove = false;
break;
case MotionEvent.ACTION_MOVE:
if(isOverScroll(ev)){
handleOverScrollMove(ev);
}
default:
break;
}
return handleMove || super.onTouchEvent(ev);
}
private void handleOverScrollMove(MotionEvent ev){
float nowX = ev.getX();
float offset = nowX - preX;
if (Math.abs(offset) > MIN_SCROLL_DISTANCE) {
handleScroll(offset);
preX = nowX;
}
}
private void handleScroll(float offset) {
handleMove = true;
float tranX = getTranslationX() + offset * RATIO;
setTranslationX(tranX);
}
private void recoverPosition() {
if (getTranslationX() == translationX || !handleMove) {
return;
}
ValueAnimator animator = ValueAnimator.ofFloat(getTranslationX(), translationX).setDuration(240);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float leftPosition = (float)animation.getAnimatedValue();
setTranslationX(leftPosition);
}
});
animator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
animPlaying = false;
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
animator.start();
animPlaying = true;
}
}
如果需要Kotlin
版本的代码,可以看 这里
ps: 使用中如果有任何问题,欢迎讨论。