feat:Android implement FillMode
This commit is contained in:
parent
359e974424
commit
7f278073f3
@ -46,6 +46,7 @@ import com.github.pengfeizhou.jscore.JSDecoder;
|
|||||||
import com.github.pengfeizhou.jscore.JSObject;
|
import com.github.pengfeizhou.jscore.JSObject;
|
||||||
import com.github.pengfeizhou.jscore.JSValue;
|
import com.github.pengfeizhou.jscore.JSValue;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -663,9 +664,46 @@ public abstract class ViewNode<T extends View> extends DoricContextHolder {
|
|||||||
JSValue animations = value.asObject().getProperty("animations");
|
JSValue animations = value.asObject().getProperty("animations");
|
||||||
if (animations.isArray()) {
|
if (animations.isArray()) {
|
||||||
AnimatorSet animatorSet = new AnimatorSet();
|
AnimatorSet animatorSet = new AnimatorSet();
|
||||||
|
|
||||||
for (int i = 0; i < animations.asArray().size(); i++) {
|
for (int i = 0; i < animations.asArray().size(); i++) {
|
||||||
animatorSet.play(parseAnimator(animations.asArray().get(i)));
|
animatorSet.play(parseAnimator(animations.asArray().get(i)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JSValue delayJS = value.asObject().getProperty("delay");
|
||||||
|
if (delayJS.isNumber()) {
|
||||||
|
animatorSet.setStartDelay(delayJS.asNumber().toLong());
|
||||||
|
}
|
||||||
|
JSValue fillModeJSVal = value.asObject().getProperty("fillMode");
|
||||||
|
final int fillMode = fillModeJSVal.asNumber().toInt();
|
||||||
|
|
||||||
|
animatorSet.addListener(new AnimatorListenerAdapter() {
|
||||||
|
private HashMap<String, Float> originVals = new HashMap<>();
|
||||||
|
private String[] keys = {
|
||||||
|
"translationX",
|
||||||
|
"translationY",
|
||||||
|
"scaleX",
|
||||||
|
"scaleY",
|
||||||
|
"rotation",
|
||||||
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAnimationStart(Animator animation) {
|
||||||
|
super.onAnimationStart(animation);
|
||||||
|
for (String key : keys) {
|
||||||
|
originVals.put(key, getAnimatedValue(key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAnimationEnd(Animator animation) {
|
||||||
|
super.onAnimationEnd(animation);
|
||||||
|
if ((fillMode & 1) != 1) {
|
||||||
|
for (String key : keys) {
|
||||||
|
setAnimatedValue(key, originVals.get(key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
return animatorSet;
|
return animatorSet;
|
||||||
} else if (value.isObject()) {
|
} else if (value.isObject()) {
|
||||||
JSArray changeables = value.asObject().getProperty("changeables").asArray();
|
JSArray changeables = value.asObject().getProperty("changeables").asArray();
|
||||||
@ -674,9 +712,9 @@ public abstract class ViewNode<T extends View> extends DoricContextHolder {
|
|||||||
JSValue repeatCount = value.asObject().getProperty("repeatCount");
|
JSValue repeatCount = value.asObject().getProperty("repeatCount");
|
||||||
|
|
||||||
JSValue repeatMode = value.asObject().getProperty("repeatMode");
|
JSValue repeatMode = value.asObject().getProperty("repeatMode");
|
||||||
|
JSValue fillMode = value.asObject().getProperty("fillMode");
|
||||||
for (int j = 0; j < changeables.size(); j++) {
|
for (int j = 0; j < changeables.size(); j++) {
|
||||||
ObjectAnimator animator = parseChangeable(changeables.get(j).asObject());
|
ObjectAnimator animator = parseChangeable(changeables.get(j).asObject(), fillMode);
|
||||||
if (repeatCount.isNumber()) {
|
if (repeatCount.isNumber()) {
|
||||||
animator.setRepeatCount(repeatCount.asNumber().toInt());
|
animator.setRepeatCount(repeatCount.asNumber().toInt());
|
||||||
}
|
}
|
||||||
@ -698,12 +736,87 @@ public abstract class ViewNode<T extends View> extends DoricContextHolder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ObjectAnimator parseChangeable(JSObject jsObject) {
|
private ObjectAnimator parseChangeable(JSObject jsObject, JSValue fillMode) {
|
||||||
String key = jsObject.getProperty("key").asString().value();
|
String key = jsObject.getProperty("key").asString().value();
|
||||||
return ObjectAnimator.ofFloat(this,
|
float startVal = jsObject.getProperty("fromValue").asNumber().toFloat();
|
||||||
|
float endVal = jsObject.getProperty("toValue").asNumber().toFloat();
|
||||||
|
ObjectAnimator animator = ObjectAnimator.ofFloat(this,
|
||||||
key,
|
key,
|
||||||
jsObject.getProperty("fromValue").asNumber().toFloat(),
|
startVal,
|
||||||
jsObject.getProperty("toValue").asNumber().toFloat()
|
endVal
|
||||||
);
|
);
|
||||||
|
setFillMode(animator, key, startVal, endVal, fillMode);
|
||||||
|
return animator;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setFillMode(ObjectAnimator animator,
|
||||||
|
final String key,
|
||||||
|
float startVal,
|
||||||
|
float endVal,
|
||||||
|
JSValue jsValue) {
|
||||||
|
int fillMode = 0;
|
||||||
|
if (jsValue.isNumber()) {
|
||||||
|
fillMode = jsValue.asNumber().toInt();
|
||||||
|
}
|
||||||
|
if ((fillMode & 2) == 2) {
|
||||||
|
setAnimatedValue(key, startVal);
|
||||||
|
}
|
||||||
|
final int finalFillMode = fillMode;
|
||||||
|
animator.addListener(new AnimatorListenerAdapter() {
|
||||||
|
private float originVal;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAnimationStart(Animator animation) {
|
||||||
|
super.onAnimationStart(animation);
|
||||||
|
originVal = getAnimatedValue(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAnimationEnd(Animator animation) {
|
||||||
|
super.onAnimationEnd(animation);
|
||||||
|
if ((finalFillMode & 1) != 1) {
|
||||||
|
setAnimatedValue(key, originVal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setAnimatedValue(String key, float value) {
|
||||||
|
switch (key) {
|
||||||
|
case "translationX":
|
||||||
|
setTranslationX(value);
|
||||||
|
break;
|
||||||
|
case "translationY":
|
||||||
|
setTranslationY(value);
|
||||||
|
break;
|
||||||
|
case "scaleX":
|
||||||
|
setScaleX(value);
|
||||||
|
break;
|
||||||
|
case "scaleY":
|
||||||
|
setScaleY(value);
|
||||||
|
break;
|
||||||
|
case "rotation":
|
||||||
|
setRotation(value);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private float getAnimatedValue(String key) {
|
||||||
|
switch (key) {
|
||||||
|
case "translationX":
|
||||||
|
return getTranslationX();
|
||||||
|
case "translationY":
|
||||||
|
return getTranslationY();
|
||||||
|
case "scaleX":
|
||||||
|
return getScaleX();
|
||||||
|
case "scaleY":
|
||||||
|
return getScaleY();
|
||||||
|
case "rotation":
|
||||||
|
return getRotation();
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -170,8 +170,7 @@ class AnimatorDemo extends Panel {
|
|||||||
thisLabel('animationSet').apply({
|
thisLabel('animationSet').apply({
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
const animationSet = new AnimationSet
|
const animationSet = new AnimationSet
|
||||||
animationSet.fillMode = FillMode.Forward
|
//animationSet.fillMode = FillMode.Removed
|
||||||
animationSet.delay = 2000
|
|
||||||
const translate = new TranslationAnimation
|
const translate = new TranslationAnimation
|
||||||
translate.fromTranslationX = 100
|
translate.fromTranslationX = 100
|
||||||
translate.toTranslationX = 200
|
translate.toTranslationX = 200
|
||||||
@ -179,6 +178,7 @@ class AnimatorDemo extends Panel {
|
|||||||
translate.toTranslationY = 200
|
translate.toTranslationY = 200
|
||||||
translate.duration = 2000
|
translate.duration = 2000
|
||||||
translate.delay = 1000
|
translate.delay = 1000
|
||||||
|
translate.fillMode = FillMode.Forward
|
||||||
const scale = new ScaleAnimation
|
const scale = new ScaleAnimation
|
||||||
scale.fromScaleX = 1
|
scale.fromScaleX = 1
|
||||||
scale.toScaleX = 5
|
scale.toScaleX = 5
|
||||||
@ -186,10 +186,12 @@ class AnimatorDemo extends Panel {
|
|||||||
scale.toScaleY = 5
|
scale.toScaleY = 5
|
||||||
//scale.delay = 1000
|
//scale.delay = 1000
|
||||||
scale.duration = 2000
|
scale.duration = 2000
|
||||||
|
scale.fillMode = FillMode.Backward
|
||||||
const rotation = new RotationAnimation
|
const rotation = new RotationAnimation
|
||||||
rotation.fromRotation = 0
|
rotation.fromRotation = 0
|
||||||
rotation.toRotation = 6.2
|
rotation.toRotation = 6.3
|
||||||
rotation.duration = 3000
|
rotation.duration = 2000
|
||||||
|
rotation.fillMode = FillMode.Removed
|
||||||
animationSet.addAnimation(translate)
|
animationSet.addAnimation(translate)
|
||||||
animationSet.addAnimation(scale)
|
animationSet.addAnimation(scale)
|
||||||
animationSet.addAnimation(rotation)
|
animationSet.addAnimation(rotation)
|
||||||
|
@ -340,7 +340,9 @@ - (CFTimeInterval)computeDurationOfAnimations:(NSArray<CAAnimation *> *)animatio
|
|||||||
[animations forEach:^(CAAnimation *obj) {
|
[animations forEach:^(CAAnimation *obj) {
|
||||||
interval = MAX(interval, obj.beginTime + obj.duration * (1 + obj.repeatCount));
|
interval = MAX(interval, obj.beginTime + obj.duration * (1 + obj.repeatCount));
|
||||||
}];
|
}];
|
||||||
return interval;
|
/// Here add 0.00001 to force animationGroup's last child animation affects fill mode.
|
||||||
|
/// Otherwise the child's fill mode will be overwritten by parent.
|
||||||
|
return interval + 0.00001;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (CAAnimation *)parseAnimation:(id)params {
|
- (CAAnimation *)parseAnimation:(id)params {
|
||||||
|
@ -45,15 +45,15 @@ export enum FillMode {
|
|||||||
/**
|
/**
|
||||||
* The receiver remains visible in its final state when the animation is completed.
|
* The receiver remains visible in its final state when the animation is completed.
|
||||||
*/
|
*/
|
||||||
Forward = 1,
|
Forward = 0x1,
|
||||||
/**
|
/**
|
||||||
* The receiver clamps values before zero to zero when the animation is completed.
|
* The receiver clamps values before zero to zero when the animation is completed.
|
||||||
*/
|
*/
|
||||||
Backward = 2,
|
Backward = 0x2,
|
||||||
/**
|
/**
|
||||||
* The receiver clamps values at both ends of the object’s time space
|
* The receiver clamps values at both ends of the object’s time space
|
||||||
*/
|
*/
|
||||||
Both = 3,
|
Both = 0x3,
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class Animation implements IAnimation {
|
abstract class Animation implements IAnimation {
|
||||||
|
Reference in New Issue
Block a user