feat:Android use ObjectAnimator to implement animate plugin

This commit is contained in:
pengfei.zhou 2019-11-29 14:37:42 +08:00
parent dd69a3f150
commit 410ad72d71
5 changed files with 207 additions and 38 deletions

View File

@ -15,6 +15,8 @@
*/
package pub.doric;
import android.animation.Animator;
import android.animation.AnimatorSet;
import android.content.Context;
import com.github.pengfeizhou.jscore.JSDecoder;
@ -193,4 +195,15 @@ public class DoricContext {
public IDoricNavBar getDoricNavBar() {
return this.doricNavBar;
}
private AnimatorSet animatorSet;
public void setAnimatorSet(AnimatorSet animatorSet) {
this.animatorSet = animatorSet;
}
public AnimatorSet getAnimatorSet() {
return this.animatorSet;
}
}

View File

@ -20,6 +20,7 @@ import android.text.TextUtils;
import pub.doric.loader.DoricAssetJSLoader;
import pub.doric.loader.DoricHttpJSLoader;
import pub.doric.loader.IDoricJSLoader;
import pub.doric.plugin.AnimatePlugin;
import pub.doric.plugin.NavBarPlugin;
import pub.doric.plugin.NavigatorPlugin;
import pub.doric.plugin.NetworkPlugin;
@ -89,6 +90,7 @@ public class DoricRegistry {
this.registerNativePlugin(NavigatorPlugin.class);
this.registerNativePlugin(NavBarPlugin.class);
this.registerNativePlugin(PopoverPlugin.class);
this.registerNativePlugin(AnimatePlugin.class);
this.registerViewNode(RootNode.class);
this.registerViewNode(TextNode.class);

View File

@ -0,0 +1,86 @@
package pub.doric.plugin;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.text.TextUtils;
import com.github.pengfeizhou.jscore.JSObject;
import com.github.pengfeizhou.jscore.JavaValue;
import java.util.concurrent.Callable;
import pub.doric.DoricContext;
import pub.doric.async.AsyncResult;
import pub.doric.extension.bridge.DoricMethod;
import pub.doric.extension.bridge.DoricPlugin;
import pub.doric.extension.bridge.DoricPromise;
import pub.doric.shader.RootNode;
import pub.doric.shader.ViewNode;
import pub.doric.utils.DoricLog;
import pub.doric.utils.ThreadMode;
/**
* @Description: pub.doric.plugin
* @Author: pengfei.zhou
* @CreateDate: 2019-11-29
*/
@DoricPlugin(name = "animate")
public class AnimatePlugin extends DoricJavaPlugin {
public AnimatePlugin(DoricContext doricContext) {
super(doricContext);
}
@DoricMethod
public void submit(DoricPromise promise) {
promise.resolve();
}
@DoricMethod
public void animateRender(final JSObject jsObject, final DoricPromise promise) {
getDoricContext().getDriver().asyncCall(new Callable<Object>() {
@Override
public Object call() throws Exception {
final long duration = jsObject.getProperty("duration").asNumber().toLong();
AnimatorSet animatorSet = new AnimatorSet();
getDoricContext().setAnimatorSet(animatorSet);
String viewId = jsObject.getProperty("id").asString().value();
RootNode rootNode = getDoricContext().getRootNode();
if (TextUtils.isEmpty(rootNode.getId())) {
rootNode.setId(viewId);
rootNode.blend(jsObject.getProperty("props").asObject());
} else {
ViewNode viewNode = getDoricContext().targetViewNode(viewId);
if (viewNode != null) {
viewNode.blend(jsObject.getProperty("props").asObject());
}
}
getDoricContext().setAnimatorSet(null);
animatorSet.setDuration(duration);
animatorSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
promise.resolve();
}
});
animatorSet.start();
return null;
}
}, ThreadMode.UI).setCallback(new AsyncResult.Callback<Object>() {
@Override
public void onResult(Object result) {
}
@Override
public void onError(Throwable t) {
t.printStackTrace();
DoricLog.e("Shader.render:error%s", t.getLocalizedMessage());
promise.reject(new JavaValue(t.getLocalizedMessage()));
}
@Override
public void onFinish() {
}
});
}
}

View File

@ -15,6 +15,8 @@
*/
package pub.doric.shader;
import android.animation.Animator;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
@ -123,16 +125,48 @@ public abstract class ViewNode<T extends View> extends DoricContextHolder {
protected void blend(T view, String name, JSValue prop) {
switch (name) {
case "width":
if (isAnimating()) {
addAnimator(ObjectAnimator.ofFloat(
this,
name,
getWidth(),
prop.asNumber().toFloat()));
} else {
setWidth(prop.asNumber().toFloat());
}
break;
case "height":
if (isAnimating()) {
addAnimator(ObjectAnimator.ofFloat(
this,
name,
getHeight(),
prop.asNumber().toFloat()));
} else {
setHeight(prop.asNumber().toFloat());
}
break;
case "x":
if (isAnimating()) {
addAnimator(ObjectAnimator.ofFloat(
this,
name,
getX(),
prop.asNumber().toFloat()));
} else {
setX(prop.asNumber().toFloat());
}
break;
case "y":
if (isAnimating()) {
addAnimator(ObjectAnimator.ofFloat(
this,
name,
getY(),
prop.asNumber().toFloat()));
} else {
setY(prop.asNumber().toFloat());
}
break;
case "bgColor":
view.setBackgroundColor(prop.asNumber().toInt());
@ -244,30 +278,6 @@ public abstract class ViewNode<T extends View> extends DoricContextHolder {
return mId;
}
protected void setWidth(float width) {
if (mLayoutParams.width >= 0) {
mLayoutParams.width = DoricUtils.dp2px(width);
}
}
protected void setHeight(float height) {
if (mLayoutParams.height >= 0) {
mLayoutParams.height = DoricUtils.dp2px(height);
}
}
protected void setX(float x) {
if (mLayoutParams instanceof ViewGroup.MarginLayoutParams) {
((ViewGroup.MarginLayoutParams) mLayoutParams).leftMargin = DoricUtils.dp2px(x);
}
}
protected void setY(float y) {
if (mLayoutParams instanceof ViewGroup.MarginLayoutParams) {
((ViewGroup.MarginLayoutParams) mLayoutParams).topMargin = DoricUtils.dp2px(y);
}
}
protected void setLayoutConfig(JSObject layoutConfig) {
if (mSuperNode != null) {
mSuperNode.blendSubLayoutConfig(this, layoutConfig);
@ -329,14 +339,25 @@ public abstract class ViewNode<T extends View> extends DoricContextHolder {
}
}
@DoricMethod
public int getWidth() {
return getNodeView().getWidth();
protected boolean isAnimating() {
return getDoricContext().getAnimatorSet() != null;
}
protected void addAnimator(Animator animator) {
if (getDoricContext().getAnimatorSet() == null) {
return;
}
getDoricContext().getAnimatorSet().play(animator);
}
@DoricMethod
public int getHeight() {
return getNodeView().getHeight();
public float getWidth() {
return DoricUtils.px2dp(getNodeView().getWidth());
}
@DoricMethod
public float getHeight() {
return DoricUtils.px2dp(getNodeView().getHeight());
}
@DoricMethod
@ -355,4 +376,53 @@ public abstract class ViewNode<T extends View> extends DoricContextHolder {
public float getRotation() {
return getNodeView().getRotation() / 360;
}
@DoricMethod
protected void setWidth(float width) {
if (mLayoutParams.width >= 0) {
mLayoutParams.width = DoricUtils.dp2px(width);
mView.requestLayout();
}
}
@DoricMethod
protected void setHeight(float height) {
if (mLayoutParams.height >= 0) {
mLayoutParams.height = DoricUtils.dp2px(height);
mView.requestLayout();
}
}
@DoricMethod
protected void setX(float x) {
if (mLayoutParams instanceof ViewGroup.MarginLayoutParams) {
((ViewGroup.MarginLayoutParams) mLayoutParams).leftMargin = DoricUtils.dp2px(x);
mView.requestLayout();
}
}
@DoricMethod
protected void setY(float y) {
if (mLayoutParams instanceof ViewGroup.MarginLayoutParams) {
((ViewGroup.MarginLayoutParams) mLayoutParams).topMargin = DoricUtils.dp2px(y);
mView.requestLayout();
}
}
@DoricMethod
public float getX() {
if (mLayoutParams instanceof ViewGroup.MarginLayoutParams) {
return DoricUtils.px2dp(((ViewGroup.MarginLayoutParams) mLayoutParams).leftMargin);
}
return 0;
}
@DoricMethod
public float getY() {
if (mLayoutParams instanceof ViewGroup.MarginLayoutParams) {
return DoricUtils.px2dp(((ViewGroup.MarginLayoutParams) mLayoutParams).topMargin);
}
return 0;
}
}

View File

@ -5,7 +5,7 @@ import { title, label, colors, box } from "./utils";
class AnimatorDemo extends Panel {
build(rootView: Group): void {
const view = box(2)
scroller(vlayout([
vlayout([
title("Animator Demo"),
label('Reset').apply({
width: 100,
@ -79,11 +79,9 @@ class AnimatorDemo extends Panel {
bgColor: colors[1].alpha(0.3 * 255),
}),
]).apply({
layoutConfig: layoutConfig().atmost().h(LayoutSpec.WRAP_CONTENT),
layoutConfig: layoutConfig().atmost(),
gravity: gravity().center(),
space: 10,
} as IVLayout)).apply({
layoutConfig: layoutConfig().atmost(),
}).in(rootView)
} as IVLayout).in(rootView)
}
}