0.前言
现在已经可以写自己的插件啦!想想就好激动。
App Inventor有个很严重的缺点,那就是不支持动画。
这是个很严重的大问题,我们可以考虑通过插件解决。
1.开发
1.1预备知识
大家必须要先学好Android,不然接下来可没得玩。
在Android下,有一个View.animate()的动画实现方式,超简洁
比如我让textView在2000ms内旋转720°
textView.animate().rotation(720).setDuration(2000).start();
接下来我们将封装成一个类AnimationUtil来执行动画。
1.2创建java文件
这次的代码可能有点长,不过全是封装,看一眼就好。
老规矩,我的包是cn.roger.animation,那么我就在\components\src\cn\roger\animation
下创建我的AnimationUtil.java文件
package cn.roger.animation;
import com.google.appinventor.components.annotations.*;
import com.google.appinventor.components.common.ComponentCategory;
import com.google.appinventor.components.runtime.*;
import com.google.appinventor.components.runtime.util.*;
import com.google.appinventor.components.runtime.errors.YailRuntimeError;
import android.view.ViewPropertyAnimator;
@DesignerComponent(version = AnimationUtil.VERSION,
description = "by Roger Young",
category = ComponentCategory.EXTENSION,
nonVisible = true,
iconName = "images/extension.png")
@SimpleObject(external = true)
public class AnimationUtil extends AndroidNonvisibleComponent {
public static final int VERSION = 1;
private static final String LOG_TAG = "AnimationUtil";
public AnimationUtil(ComponentContainer container) {
super(container.$form());
}
@SimpleFunction(description = "start")
public void start(Object vpa) {
((ViewPropertyAnimator)vpa).start();
}
@SimpleFunction(description = "getAnimator")
public Object getAnimator(AndroidViewComponent avc) {
return avc.getView().animate();
}
@SimpleFunction(description = "scaleX")
public Object scaleX(Object vpa,float f) {
return ((ViewPropertyAnimator)vpa).scaleX(f);
}
@SimpleFunction(description = "scaleY")
public Object scaleY(Object vpa,float f) {
return ((ViewPropertyAnimator)vpa).scaleY(f);
}
@SimpleFunction(description = "scaleXBy")
public Object scaleXBy(Object vpa,float f) {
return ((ViewPropertyAnimator)vpa).scaleXBy(f);
}
@SimpleFunction(description = "scaleYBy")
public Object scaleYBy(Object vpa,float f) {
return ((ViewPropertyAnimator)vpa).scaleYBy(f);
}
@SimpleFunction(description = "alpha")
public Object alpha(Object vpa,float f) {
return ((ViewPropertyAnimator)vpa).alpha(f);
}
@SimpleFunction(description = "alphaBy")
public Object alphaBy(Object vpa,float f) {
return ((ViewPropertyAnimator)vpa).alphaBy(f);
}
@SimpleFunction(description = "translationX")
public Object translationX(Object vpa,float f) {
return ((ViewPropertyAnimator)vpa).translationX(f);
}
@SimpleFunction(description = "translationY")
public Object translationY(Object vpa,float f) {
return ((ViewPropertyAnimator)vpa).translationY(f);
}
@SimpleFunction(description = "translationZ")
public Object translationZ(Object vpa,float f) {
return ((ViewPropertyAnimator)vpa).translationZ(f);
}
@SimpleFunction(description = "translationXBy")
public Object translationXBy(Object vpa,float f) {
return ((ViewPropertyAnimator)vpa).translationXBy(f);
}
@SimpleFunction(description = "translationYBy")
public Object translationYBy(Object vpa,float f) {
return ((ViewPropertyAnimator)vpa).translationYBy(f);
}
@SimpleFunction(description = "translationZBy")
public Object translationZBy(Object vpa,float f) {
return ((ViewPropertyAnimator)vpa).translationZBy(f);
}
@SimpleFunction(description = "setDuration")
public Object setDuration(Object vpa,long l) {
return ((ViewPropertyAnimator)vpa).setDuration(l);
}
@SimpleFunction(description = "setStartDelay")
public Object setStartDelay(Object vpa,long l) {
return ((ViewPropertyAnimator)vpa).setStartDelay(l);
}
@SimpleFunction(description = "cancel")
public void cancel(Object vpa) {
((ViewPropertyAnimator)vpa).cancel();
}
@SimpleFunction(description = "rotation")
public Object rotation(Object vpa,float f) {
return ((ViewPropertyAnimator)vpa).rotation(f);
}
@SimpleFunction(description = "rotationX")
public Object rotationX(Object vpa,float f) {
return ((ViewPropertyAnimator)vpa).rotationX(f);
}
@SimpleFunction(description = "rotationY")
public Object rotationY(Object vpa,float f) {
return ((ViewPropertyAnimator)vpa).rotationY(f);
}
@SimpleFunction(description = "rotationBy")
public Object rotationBy(Object vpa,float f) {
return ((ViewPropertyAnimator)vpa).rotationBy(f);
}
@SimpleFunction(description = "rotationXBy")
public Object rotationXBy(Object vpa,float f) {
return ((ViewPropertyAnimator)vpa).rotationXBy(f);
}
@SimpleFunction(description = "rotationYBy")
public Object rotationYBy(Object vpa,float f) {
return ((ViewPropertyAnimator)vpa).rotationYBy(f);
}
@SimpleFunction(description = "withLayer")
public Object withLayer(Object vpa) {
return ((ViewPropertyAnimator)vpa).withLayer();
}
@SimpleFunction(description = "x")
public Object x(Object vpa,float f) {
return ((ViewPropertyAnimator)vpa).x(f);
}
@SimpleFunction(description = "y")
public Object y(Object vpa,float f) {
return ((ViewPropertyAnimator)vpa).y(f);
}
@SimpleFunction(description = "z")
public Object z(Object vpa,float f) {
return ((ViewPropertyAnimator)vpa).z(f);
}
@SimpleFunction(description = "xBy")
public Object xBy(Object vpa,float f) {
return ((ViewPropertyAnimator)vpa).xBy(f);
}
@SimpleFunction(description = "yBy")
public Object yBy(Object vpa,float f) {
return ((ViewPropertyAnimator)vpa).yBy(f);
}
@SimpleFunction(description = "zBy")
public Object zBy(Object vpa,float f) {
return ((ViewPropertyAnimator)vpa).zBy(f);
}
}
1.3源码讲解
getAnimator()
返回动画类ViewPropertyAnimator
start()
执行,cancel()
取消
剩下的方法就都是封装而已
但这里有个坑,细心的朋友可能发现了,我的返回值的类型都是Object
,不是ViewPropertyAnimator
。到时候用的是后还得强制类型转换,很烦。
如果你不转的话,会挂,报错
[javac] java.lang.RuntimeException: Cannot convert Java type 'android.view.ViewPropertyAnimator' to Yail type
Yail type是何方神圣我也不太清楚,顺着报错来到了\components\src\com\google\appinventor\components\scripts\ComponentProcessor.java
的1500行左右,发现了以下代码
protected final String javaTypeToYailType(String type) {
// boolean -> boolean
if (type.equals("boolean")) {
return type;
}
// String -> text
if (type.equals("java.lang.String")) {
return "text";
}
// {float, double, int, short, long, byte} -> number
if (type.equals("float") || type.equals("double") || type.equals("int") ||
type.equals("short") || type.equals("long") || type.equals("byte")) {
return "number";
}
// YailList -> list
if (type.equals("com.google.appinventor.components.runtime.util.YailList")) {
return "list";
}
// List<?> -> list
if (type.startsWith("java.util.List")) {
return "list";
}
// Calendar -> InstantInTime
if (type.equals("java.util.Calendar")) {
return "InstantInTime";
}
if (type.equals("java.lang.Object")) {
return "any";
}
if (type.equals("com.google.appinventor.components.runtime.Component")) {
return "component";
}
// Check if it's a component.
if (componentTypes.contains(type)) {
return "component";
}
throw new RuntimeException("Cannot convert Java type '" + type +
"' to Yail type");
}
这个似乎只支持Object,于是把全部的都改成Object,再添一个强制类型转换,问题解决。
说好的any呢???
2.测试
编译导入拖入,我们先不表,来看这蛋疼的动画设置方式
还是上次的temp测试,刚才的插件都没撤掉
然后编译,运行,记得输入数字!!!不然又崩了,这就是懒的结果。。。
上成果
当你第二次点击的时候它不会动,这是因为用的是不加By的函数。加by的意思是从原先开始。
如果你不加by,那么他会从0~720,第二次是720~720,当然不会动啦
如果你加by,会从0~720,720~1440,一直增加下去。
就这样,第一个有实用功能的插件完成啦
如果大家喜欢,我不需要物质上的鼓励,在评论区里留个谢谢也行啊。毕竟我还是个高二生,需要大家的鼓励