Skip to content

Commit e6c573c

Browse files
committed
对安卓弹性动画进行了优化。
1 parent d9fd181 commit e6c573c

File tree

4 files changed

+287
-258
lines changed

4 files changed

+287
-258
lines changed

Examples/Test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* @Author: 石破天惊
33
* @email: shanshang130@gmail.com
44
* @Date: 2021-07-16 17:29:37
5-
* @LastEditTime: 2021-07-23 08:59:51
5+
* @LastEditTime: 2021-07-27 18:23:18
66
* @LastEditors: 石破天惊
77
* @Description:
88
*/
@@ -67,7 +67,7 @@ export class Test extends React.Component {
6767
<View style={cs.mainScroll}>
6868
<SpringScrollView
6969
{...this.state}
70-
inputToolBarHeight={200}
70+
inputToolBarHeight={Platform.select({ ios: 44, android: 200 })}
7171
textInputRefs={[this._contentStyleRef, this._pageSizeRef]}
7272
ref={(ref) => (this._main = ref)}
7373
onScroll={this._onScroll}

src/android/src/main/java/com/bolan9999/DecelerateAnimation.java

Lines changed: 228 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -5,94 +5,258 @@
55
import android.animation.ValueAnimator;
66
import android.view.animation.DecelerateInterpolator;
77

8-
interface DecelerateListener {
9-
void onDecelerateUpdate(DecelerateAnimation animation, float value);
8+
interface SpringAnimatorListener {
9+
void onUpdate(SpringAnimator animation, float value);
1010

11-
void onDecelerateEnd(DecelerateAnimation animation);
12-
}
11+
void onInnerEnd(SpringAnimator animation, float stopVelocity);
1312

14-
class DecelerateAnimation {
15-
protected ValueAnimator animator;
16-
public boolean animating;
17-
private DecelerateListener listener;
18-
private DecelerateListener extraListener;
19-
private boolean shouldCompete;
13+
void onOuterEnd(SpringAnimator animation);
2014

21-
public DecelerateAnimation(final DecelerateListener listener) {
22-
animator = new ValueAnimator();
23-
this.listener = listener;
24-
animator.setInterpolator(new DecelerateInterpolator(1.5f));
25-
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
26-
@Override
27-
public void onAnimationUpdate(ValueAnimator animator) {
28-
listener.onDecelerateUpdate(DecelerateAnimation.this,
29-
(float) animator.getAnimatedValue());
30-
if (DecelerateAnimation.this.extraListener != null)
31-
DecelerateAnimation.this.extraListener.onDecelerateUpdate(
32-
DecelerateAnimation.this, (float) animator.getAnimatedValue());
15+
void onReboundEnd(SpringAnimator animation);
16+
}
3317

34-
}
35-
});
36-
animator.addListener(new Animator.AnimatorListener() {
37-
@Override
38-
public void onAnimationStart(Animator animation) {
39-
DecelerateAnimation.this.animating = true;
40-
}
18+
class SpringAnimator implements ValueAnimator.AnimatorUpdateListener, Animator.AnimatorListener {
19+
protected ValueAnimator inner;
20+
protected ValueAnimator outer;
21+
protected ValueAnimator rebound;
22+
protected float initialVelocity;
23+
protected float dampingCoefficient;
24+
protected float from;
25+
protected float innerStopVelocity;
26+
public boolean animating, canceling;
27+
private SpringAnimatorListener listener;
4128

42-
@Override
43-
public void onAnimationEnd(Animator animation) {
44-
DecelerateAnimation.this.animating = false;
45-
if (DecelerateAnimation.this.extraListener != null)
46-
DecelerateAnimation.this.extraListener.onDecelerateEnd(
47-
DecelerateAnimation.this);
48-
if (DecelerateAnimation.this.shouldCompete)
49-
DecelerateAnimation.this.listener.onDecelerateEnd(DecelerateAnimation.this);
29+
void startInner(float f, final float v0, final float d, float lower, float upper, boolean pagingEnabled, float pageSize) {
30+
from = f;
31+
initialVelocity = v0;
32+
dampingCoefficient = d;
33+
float displacement = 0;
34+
float v = initialVelocity;
35+
int duration = 0;
36+
while (Math.abs(v) > 0.1f) {
37+
v *= dampingCoefficient;
38+
displacement += v;
39+
duration++;
40+
if (from + displacement >= upper) {
41+
displacement = upper - from;
42+
break;
43+
} else if (from + displacement <= lower) {
44+
displacement = lower - from;
45+
break;
5046
}
47+
}
48+
innerStopVelocity = v;
49+
if (pagingEnabled) {
50+
float end = Math.round((f + displacement) / pageSize) * pageSize;
51+
if (end > upper) end = upper;
52+
if (end < lower) end = lower;
53+
this.startRebound(f, end, 500);
54+
} else {
55+
inner.setFloatValues(0, displacement);
56+
inner.setDuration(duration);
57+
if (duration > 0) inner.start();
58+
else listener.onInnerEnd(this, v);
59+
}
60+
}
5161

52-
@Override
53-
public void onAnimationCancel(Animator animation) {
54-
DecelerateAnimation.this.animating = false;
55-
}
62+
void startOuter(float f, float v0, float d) {
63+
from = f;
64+
initialVelocity = v0;
65+
dampingCoefficient = d;
66+
float displacement = 0;
67+
float v = initialVelocity;
68+
int duration = 0;
69+
while (Math.abs(v) > 0.1f) {
70+
v *= dampingCoefficient;
71+
displacement += v;
72+
duration++;
73+
}
74+
outer.setFloatValues(from, from + displacement);
75+
outer.setDuration(duration);
76+
outer.start();
77+
}
5678

57-
@Override
58-
public void onAnimationRepeat(Animator animation) {
59-
}
60-
});
79+
void startRebound(float f, float t, long d) {
80+
rebound.setFloatValues(f, t);
81+
rebound.setDuration(d);
82+
rebound.start();
6183
}
6284

63-
public void config(float from, float to, long duration) {
64-
config(from, to, duration, true);
85+
public SpringAnimator(SpringAnimatorListener listener) {
86+
inner = new ValueAnimator();
87+
this.listener = listener;
88+
inner.setInterpolator(new DecelerateInterpolator(1.5f));
89+
inner.addUpdateListener(this);
90+
inner.addListener(this);
91+
outer = new ValueAnimator();
92+
outer.setInterpolator(new DecelerateInterpolator(1.5f));
93+
outer.addUpdateListener(this);
94+
outer.addListener(this);
95+
rebound = new ValueAnimator();
96+
rebound.setInterpolator(new DecelerateInterpolator(1.5f));
97+
rebound.addUpdateListener(this);
98+
rebound.addListener(this);
6599
}
66100

67-
public void config(float from, float to, long duration, boolean shouldCompete) {
68-
animator.setFloatValues(from, to);
69-
animator.setDuration(duration);
70-
this.shouldCompete = shouldCompete;
101+
@Override
102+
public void onAnimationUpdate(ValueAnimator animator) {
103+
if (animator == inner) {
104+
float v = initialVelocity;
105+
float displacement = 0;
106+
long currentTime = animator.getCurrentPlayTime();
107+
do {
108+
displacement += v;
109+
v *= dampingCoefficient;
110+
currentTime--;
111+
} while (currentTime > 0);
112+
if (!canceling) listener.onUpdate(this, from + displacement);
113+
} else {
114+
if (!canceling) listener.onUpdate(this, (float) animator.getAnimatedValue());
115+
}
71116
}
72117

73-
public void configFromSpeed(float base, float v, float dampingCoefficient, boolean shouldCompete) {
74-
int duration = 0;
75-
float displacement = 0;
76-
while (Math.abs(v) > 0.001f) {
77-
displacement += v;
78-
v *= dampingCoefficient;
79-
duration++;
118+
@Override
119+
public void onAnimationStart(Animator animation) {
120+
animating = true;
121+
}
122+
123+
@Override
124+
public void onAnimationEnd(Animator animation) {
125+
animating = false;
126+
if (animation == inner) {
127+
if (!canceling) listener.onInnerEnd(this, this.innerStopVelocity);
128+
} else if (animation == outer) {
129+
if (!canceling) listener.onOuterEnd(this);
130+
} else if (animation == rebound) {
131+
if (!canceling) listener.onReboundEnd(this);
80132
}
81-
config(base, base - displacement, duration, shouldCompete);
82133
}
83134

84-
public void setExtraListener(DecelerateListener listener) {
85-
this.extraListener = listener;
135+
@Override
136+
public void onAnimationCancel(Animator animation) {
137+
animating = false;
138+
}
139+
140+
@Override
141+
public void onAnimationRepeat(Animator animation) {
86142
}
87143

88144
public void start() {
89-
animator.start();
145+
// animator.end(); //适配安卓API 25及以下
146+
inner.start();
90147
}
91148

92149
public boolean cancel() {
93150
boolean cancel = this.animating;
94-
animator.cancel();
151+
canceling = true;
152+
if (inner.isRunning()) {
153+
inner.cancel();
154+
// inner.end();
155+
}
156+
if (outer.isRunning()) {
157+
outer.cancel();
158+
// outer.end();
159+
}
160+
if (rebound.isRunning()) {
161+
rebound.cancel();
162+
// rebound.end();
163+
}
164+
canceling = false;
95165
return cancel;
96166
}
97-
98167
}
168+
169+
//interface DecelerateListener {
170+
// void onDecelerateUpdate(DecelerateAnimation animation, float value);
171+
//
172+
// void onDecelerateEnd(DecelerateAnimation animation);
173+
//}
174+
175+
176+
//class DecelerateAnimation {
177+
// protected ValueAnimator animator;
178+
// public boolean animating;
179+
// private DecelerateListener listener;
180+
// private DecelerateListener extraListener;
181+
// private boolean shouldCompete;
182+
//
183+
// public DecelerateAnimation(final DecelerateListener listener) {
184+
// animator = new ValueAnimator();
185+
// this.listener = listener;
186+
// animator.setInterpolator(new DecelerateInterpolator(1.5f));
187+
// animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
188+
// @Override
189+
// public void onAnimationUpdate(ValueAnimator animator) {
190+
// listener.onDecelerateUpdate(DecelerateAnimation.this,
191+
// (float) animator.getAnimatedValue());
192+
// if (DecelerateAnimation.this.extraListener != null)
193+
// DecelerateAnimation.this.extraListener.onDecelerateUpdate(
194+
// DecelerateAnimation.this, (float) animator.getAnimatedValue());
195+
//
196+
// }
197+
// });
198+
// animator.addListener(new Animator.AnimatorListener() {
199+
// @Override
200+
// public void onAnimationStart(Animator animation) {
201+
// DecelerateAnimation.this.animating = true;
202+
// }
203+
//
204+
// @Override
205+
// public void onAnimationEnd(Animator animation) {
206+
// DecelerateAnimation.this.animating = false;
207+
// if (DecelerateAnimation.this.extraListener != null)
208+
// DecelerateAnimation.this.extraListener.onDecelerateEnd(
209+
// DecelerateAnimation.this);
210+
// if (DecelerateAnimation.this.shouldCompete)
211+
// DecelerateAnimation.this.listener.onDecelerateEnd(DecelerateAnimation.this);
212+
// }
213+
//
214+
// @Override
215+
// public void onAnimationCancel(Animator animation) {
216+
// DecelerateAnimation.this.animating = false;
217+
// }
218+
//
219+
// @Override
220+
// public void onAnimationRepeat(Animator animation) {
221+
// }
222+
// });
223+
// }
224+
//
225+
// public void config(float from, float to, long duration) {
226+
// config(from, to, duration, true);
227+
// }
228+
//
229+
// public void config(float from, float to, long duration, boolean shouldCompete) {
230+
// animator.setFloatValues(from, to);
231+
// animator.setDuration(duration);
232+
// this.shouldCompete = shouldCompete;
233+
// }
234+
//
235+
// public void configFromSpeed(float base, float v, float dampingCoefficient, boolean shouldCompete) {
236+
// int duration = 0;
237+
// float displacement = 0;
238+
// while (Math.abs(v) > 0.001f) {
239+
// displacement += v;
240+
// v *= dampingCoefficient;
241+
// duration++;
242+
// }
243+
// config(base, base - displacement, duration, shouldCompete);
244+
// }
245+
//
246+
// public void setExtraListener(DecelerateListener listener) {
247+
// this.extraListener = listener;
248+
// }
249+
//
250+
// public void start() {
251+
//
252+
// animator.start();
253+
// }
254+
//
255+
// public boolean cancel() {
256+
// boolean cancel = this.animating;
257+
// animator.cancel();
258+
//// animator.end(); //适配安卓API 25及以下
259+
// return cancel;
260+
// }
261+
//
262+
//}

0 commit comments

Comments
 (0)