實現 ViewPager 回彈效果
在開發過程中,遇到產品需要實現回彈效果,我通過繼承V4中的ViewPager來實現,
具體代碼如下:
mport android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import cn.wps.moffice.main.scan.util.DeviceInfoUtils;
public class ZoomViewPager extends ScanViewPager {
private float preX = 0f;
private static final float RATIO = 0.5f;//摩擦係數
private int maxOffset;
private boolean isScrollable = true;
private boolean isEnableSpringBack = true;
private int mActivePointerId;
private int screenWidth;
public void setEnableSpringBack(boolean isEnableSpringBack) {
this.isEnableSpringBack = isEnableSpringBack;
}
public ZoomViewPager(Context context) {
super(context);
init(context);
}
public ZoomViewPager(final Context context, final AttributeSet attrs) {
super(context, attrs);
init(context);
}
private void init(Context context) {
screenWidth = DeviceInfoUtils.getScreenInfo(getContext()).width;
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
if (isScrollable == false) {
return false;
}
if (handleSpringBackEvent(ev)) {
return true;
} else {
try {
return super.onTouchEvent(ev);
} catch (Exception e) {
return false;
}
}
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (isScrollable == false) {
return false;
} else {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
handleActionDown(ev);
}
try {
return super.onInterceptTouchEvent(ev);
} catch (Exception e) {
return false;
}
}
}
private void handleActionDown(MotionEvent ev) {
mActivePointerId = ev.getPointerId(0);
int pointerIndex = ev.findPointerIndex(mActivePointerId);
preX = ev.getX(pointerIndex);
maxOffset = screenWidth / 2 + getScrollX();
}
/**
* 處理回彈效果
*
* @param ev
* @return
*/
public boolean handleSpringBackEvent(MotionEvent ev) {
if (!isEnableSpringBack) return false;
if (getAdapter() == null) return false;
int action = ev.getActionMasked();
switch (action) {
case MotionEvent.ACTION_DOWN:
handleActionDown(ev);
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
handleActionUp();
break;
case MotionEvent.ACTION_POINTER_UP:
int index = ev.getActionIndex();
int id = ev.getPointerId(index);
if (mActivePointerId == id) {
final int newIndex = index == 0 ? 1 : 0;
mActivePointerId = ev.getPointerId(newIndex);
preX = ev.getX(newIndex);
}
break;
case MotionEvent.ACTION_MOVE:
float nowX = getActiveX(ev);
float offset = nowX - preX;
preX = nowX;
if (getCurrentItem() == 0 && getAdapter().getCount() > 1) {
if (!isCheck) {
isCheck = true;
if (offset > 0) {
isEnableBounce = true;
}
}
if (isEnableBounce) { //處理回彈效果
if (Math.abs(getScrollX()) <= maxOffset || offset < 0) {
scrollBy((int) -(offset * RATIO), 0);
invalidate();
}
return true;
}
}
if (getCurrentItem() == getAdapter().getCount() - 1 && getAdapter().getCount() > 1) {
if (!isCheck) { //
isCheck = true;
if (offset < 0) {
isEnableBounce = true;
}
}
if (isEnableBounce) { //處理回彈效果
if (Math.abs(getScrollX()) <= maxOffset || offset > 0) {
scrollBy((int) -(offset * RATIO), 0);
invalidate();
}
return true;
}
}
break;
}
return false;
}
private float getActiveX(MotionEvent ev) {
try {
final int pointerIndex = ev.findPointerIndex(mActivePointerId);
return ev.getX(pointerIndex);
} catch (Exception e) {
return ev.getX();
}
}
private boolean isEnableBounce = false;
private boolean isCheck = false;
private void handleActionUp() {
if (isCheck && isEnableBounce) {
setIsBeingDragged(true);
}
isCheck = false;
isEnableBounce = false;
}
public boolean isScrollable() {
return isScrollable;
}
public void setScrollable(boolean isScrollable) {
this.isScrollable = isScrollable;
}
}