仿iOS页面回弹效果

好久没写啦!忙于各种乱七八糟的事。今天是来深圳的第54天,依旧无业游民,浑浑噩噩,不知所措,想想真是可笑,竟然连入行的机会都没有,但是并不想放弃,因为这是我所喜爱的编程!


  回归正题,页面回弹其实是很简单的东西,只是之前没有接触,或者说是缺乏分析的思维,大概练得多了,会好些吧!
先分析下大概的思路,回弹效果分两部分。
 第一,当页面滑至边顶部或底部时,还可以继续滑动。
 第二,滑动完成,也就是手指离开屏幕时,页面回弹至原来的位置 。

 实现起来也比较简单,下面直接贴代码(带详细注释),相信都能够看得懂。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
package com.back.scroll;

import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.TranslateAnimation;
import android.widget.ScrollView;

public class MyScorllview extends ScrollView {
/** 控制滑动的速度 **/
private static int speed = 3;
/** 反弹动画时间 **/
private long time = 500;
/** 存储contentView的位置 **/
private Rect originView = new Rect();
/** ScrollView下的子视图 **/
private View inner;

private int scrollY;
/** 在视图界面中的Y坐标 **/
private float y;

public MyScorllview(Context context) {
super(context);
// TODO Auto-generated constructor stub
}

public MyScorllview(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}

@Override
protected void onFinishInflate() {
// 获取scrollView下子视图
if (getChildCount() > 0) {
inner = getChildAt(0);
}
}

// 用onTouchEvent()方法也是可以的
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (inner == null) {
return super.onTouchEvent(ev);
} else {
commOntouchEvent(ev);
}
return super.onTouchEvent(ev);
}

private void commOntouchEvent(MotionEvent ev) {

int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
y = ev.getY();
break;

case MotionEvent.ACTION_UP:
if (isNeedAnimation()) {
animation();
}
break;
case MotionEvent.ACTION_MOVE:
final float preY = y;
float nowY = ev.getY();
int deltaY = (int) ((preY - nowY) / speed);
y = nowY;

if (isNeedMove()) {
if (originView.isEmpty()) {
originView.set(inner.getLeft(), inner.getTop(),
inner.getRight(), inner.getBottom());
return;
}
int yy = inner.getTop() - deltaY;
inner.layout(inner.getLeft(), yy, inner.getRight(),
inner.getBottom() - deltaY);

}
break;
}
}

// 反弹时的动画
private void animation() {
TranslateAnimation animation = new TranslateAnimation(0, 0,
inner.getTop(), originView.top);
animation.setDuration(time);
inner.startAnimation(animation);
inner.layout(originView.left, originView.top, originView.right, originView.bottom);
originView.setEmpty();
}

public boolean isNeedAnimation() {
return !originView.isEmpty();
}

/**
* 该方法判断页面是否到达顶部或底部,稍微难一点点
* 首先得理解ScrollView 中 scrollY的值代表的是什么?
* scrollY代表的是内容视图在ScrollView上滑动的Y值 也就是如下的offset值
* 当然这个值是不断变化的,前提是内容视图高度大于ScrollView的高度
*
* 后面会贴张图,便于理解
*/

private boolean isNeedMove() {
int offset = inner.getMeasuredHeight() - getHeight();
scrollY = getScrollY();
if (scrollY == 0 || scrollY == offset) {
return true;
}
return false;
}
}





 当然,也有ScrollView的高度大于ContentView的高度,这时的ScrollY值为 0 。