1 public class BounceBackViewPager extends ViewPager {
2
3 private int currentPosition = 0;
4 private Rect mRect = new Rect();//用来记录初始位置
5 private boolean handleDefault = true;
6 private float preX = 0f;
7 private static final float RATIO = 0.5f;//摩擦系数
8 private static final float SCROLL_WIDTH = 10f;
9
10 public BounceBackViewPager(Context context) {
11 super(context);
12 }
13
14 public BounceBackViewPager(Context context, AttributeSet attrs) {
15 super(context, attrs);
16 }
17
18 @Override
19 public boolean dispatchKeyEvent(KeyEvent event) {
20 return super.dispatchKeyEvent(event);
21 }
22
23 @Override
24 public boolean onInterceptTouchEvent(MotionEvent ev) {
25 if (ev.getAction() == MotionEvent.ACTION_DOWN) {
26 preX = ev.getX();//记录起点
27 currentPosition = getCurrentItem();
28 }
29 return super.onInterceptTouchEvent(ev);
30 }
31
32 @Override
33 public boolean onTouchEvent(MotionEvent ev) {
34 switch (ev.getAction()) {
35 case MotionEvent.ACTION_UP:
36 onTouchActionUp();
37 break;
38 case MotionEvent.ACTION_MOVE:
39 if (getAdapter().getCount() == 1) {
40 float nowX = ev.getX();
41 float offset = nowX - preX;
42 preX = nowX;
43
44 if (offset > SCROLL_WIDTH) {//手指滑动的距离大于设定值
45 whetherConditionIsRight(offset);
46 } else if (offset < -SCROLL_WIDTH) {
47 whetherConditionIsRight(offset);
48 } else if (!handleDefault) {//这种情况是已经出现缓冲区域了,手指慢慢恢复的情况
49 if (getLeft() + (int) (offset * RATIO) != mRect.left) {
50 layout(getLeft() + (int) (offset * RATIO), getTop(), getRight() + (int) (offset * RATIO), getBottom());
51 }
52 }
53 } else if ((currentPosition == 0 || currentPosition == getAdapter().getCount() - 1)) {
54 float nowX = ev.getX();
55 float offset = nowX - preX;
56 preX = nowX;
57
58 if (currentPosition == 0) {
59 if (offset > SCROLL_WIDTH) {//手指滑动的距离大于设定值
60 whetherConditionIsRight(offset);
61 } else if (!handleDefault) {//这种情况是已经出现缓冲区域了,手指慢慢恢复的情况
62 if (getLeft() + (int) (offset * RATIO) >= mRect.left) {
63 layout(getLeft() + (int) (offset * RATIO), getTop(), getRight() + (int) (offset * RATIO), getBottom());
64 }
65 }
66 } else {
67 if (offset < -SCROLL_WIDTH) {
68 whetherConditionIsRight(offset);
69 } else if (!handleDefault) {
70 if (getRight() + (int) (offset * RATIO) <= mRect.right) {
71 layout(getLeft() + (int) (offset * RATIO), getTop(), getRight() + (int) (offset * RATIO), getBottom());
72 }
73 }
74 }
75 } else {
76 handleDefault = true;
77 }
78
79 if (!handleDefault) {
80 return true;
81 }
82 break;
83
84 default:
85 break;
86 }
87 return super.onTouchEvent(ev);
88 }
89
90 private void whetherConditionIsRight(float offset) {
91 if (mRect.isEmpty()) {
92 mRect.set(getLeft(), getTop(), getRight(), getBottom());
93 }
94 handleDefault = false;
95 layout(getLeft() + (int) (offset * RATIO), getTop(), getRight() + (int) (offset * RATIO), getBottom());
96 }
97
98 private void onTouchActionUp() {
99 if (!mRect.isEmpty()) {
100 recoveryPosition();
101 }
102 }
103
104 private void recoveryPosition() {
105 TranslateAnimation ta = new TranslateAnimation(getLeft(), mRect.left, 0, 0);
106 ta.setDuration(300);
107 startAnimation(ta);
108 layout(mRect.left, mRect.top, mRect.right, mRect.bottom);
109 mRect.setEmpty();
110 handleDefault = true;
111 }
112
113 }