From a1359bb2ac107be111990c359ad51e5a8968bc07 Mon Sep 17 00:00:00 2001 From: Michael Gangolf Date: Fri, 12 Nov 2021 16:31:17 +0100 Subject: [PATCH] feat(android): update library (#56) * lottie update * README * update library --- README.md | 16 +- android/build.gradle | 2 +- android/manifest | 2 +- android/src/ti/animation/AnimationView.java | 738 +++++++++--------- .../src/ti/animation/AnimationViewProxy.java | 404 +++++----- .../src/ti/animation/TiAnimationModule.java | 3 +- 6 files changed, 560 insertions(+), 605 deletions(-) diff --git a/README.md b/README.md index f25d31c..4432196 100644 --- a/README.md +++ b/README.md @@ -8,17 +8,9 @@ Appcelerator Titanium Android module to support smooth and scalable animations using [Airbnb Lottie](https://airbnb.design/lottie/). - -> ⚠️ The versions iOS 2.0.0 and Android 3.0.0 contain a breaking change that removed the Facebook Keyframes library. We decided to go with a Lottie only library for the future, since it made the race for the best animation library. Also, the deprecated method `addViewToLayer` is now removed. Please continue to use `addViewToKeypathLayer`. - -## Migrate from iOS < 2.0.0 and Android < 3.0.0 - -Instead of using `createLottieView`, simply use `createAnimationView` now. That's it! - ## Requirements -- Axway Titanium SDK 7.0.0+ -- Axway Titanium SDK 9.0.0+ for Ti.Animation 4.0.0+ +- Axway Titanium SDK 9.0.0+ ## Library versions: @@ -26,7 +18,7 @@ The Titanium modules use external libraries |Library|Platform|Version|Build Date| |---|---|---|---| -| [Airbnb Lottie](https://github.com/airbnb/lottie-android) | Android | 3.7.1 | 2021/07/08 | +| [Airbnb Lottie](https://github.com/airbnb/lottie-android) | Android | 4.2.1 | 2021/11/12 | | [Airbnb Lottie](https://github.com/airbnb/lottie-ios) | iOS | 2.5.2 | 2018/12/10 | @@ -140,6 +132,4 @@ If you scale your view bigger and you have some jagged lines you need to add `di ## Authors - Hans Knöchel ([@hansemannnn](https://twitter.com/hansemannnn) / [Web](http://hans-knoechel.de)) -- Michael Gangolf ([@MichaelGangolf](https://twitter.com/MichaelGangolf) / [Web](http://migaweb.de)) - -Patreon donate button +- Michael Gangolf ([@MichaelGangolf](https://twitter.com/MichaelGangolf) / [Web](http://migaweb.de)) Buy Me A Coke donate button diff --git a/android/build.gradle b/android/build.gradle index 5fdd8ae..95d435e 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -4,5 +4,5 @@ repositories { } dependencies { - implementation 'com.airbnb.android:lottie:3.7.1' + implementation 'com.airbnb.android:lottie:4.2.1' } diff --git a/android/manifest b/android/manifest index dc094ec..434feb9 100644 --- a/android/manifest +++ b/android/manifest @@ -2,7 +2,7 @@ # this is your module manifest and used by Titanium # during compilation, packaging, distribution, etc. # -version: 4.1.0 +version: 4.2.0 apiversion: 4 architectures: arm64-v8a armeabi-v7a x86 x86_64 description: ti.animation diff --git a/android/src/ti/animation/AnimationView.java b/android/src/ti/animation/AnimationView.java index ed68002..368da2c 100644 --- a/android/src/ti/animation/AnimationView.java +++ b/android/src/ti/animation/AnimationView.java @@ -7,394 +7,372 @@ */ package ti.animation; -import org.appcelerator.kroll.KrollDict; -import org.appcelerator.kroll.KrollProxy; -import org.appcelerator.kroll.common.Log; -import org.appcelerator.titanium.util.TiConvert; -import org.appcelerator.titanium.proxy.TiViewProxy; -import org.appcelerator.titanium.view.TiUIView; -import android.widget.ImageView.ScaleType; +import android.animation.Animator; +import android.animation.ValueAnimator; +import android.content.res.Resources; import android.view.LayoutInflater; import android.view.View; -import android.content.res.Resources; +import android.widget.ImageView.ScaleType; + import com.airbnb.lottie.LottieAnimationView; +import com.airbnb.lottie.LottieComposition; +import com.airbnb.lottie.LottieCompositionFactory; +import com.airbnb.lottie.LottieDrawable; +import com.airbnb.lottie.LottieOnCompositionLoadedListener; import com.airbnb.lottie.TextDelegate; -import com.airbnb.lottie.*; -import android.animation.Animator; -import android.animation.ValueAnimator; + +import org.appcelerator.kroll.KrollDict; +import org.appcelerator.kroll.KrollFunction; +import org.appcelerator.kroll.KrollProxy; +import org.appcelerator.kroll.common.Log; +import org.appcelerator.kroll.common.TiMessenger; import org.appcelerator.titanium.TiApplication; import org.appcelerator.titanium.io.TiBaseFile; import org.appcelerator.titanium.io.TiFileFactory; -import java.io.InputStream; -import java.lang.Exception; +import org.appcelerator.titanium.proxy.TiViewProxy; +import org.appcelerator.titanium.util.TiConvert; +import org.appcelerator.titanium.view.TiUIView; import org.json.JSONObject; -import org.appcelerator.kroll.common.TiMessenger; -import org.appcelerator.kroll.KrollFunction; -import java.lang.Float; + +import java.io.InputStream; import java.nio.charset.StandardCharsets; -public class AnimationView extends TiUIView implements LottieOnCompositionLoadedListener -{ - - private static final String LCAT = "AnimationViewProxy"; - - private LottieAnimationView lottieView; - private TiViewProxy proxy; - private KrollFunction callbackReady = null; - private float initialDuration = 0; - private ValueAnimator va = null; - private TextDelegate delegate; - - AnimationView(TiViewProxy proxy) - { - super(proxy); - - this.proxy = proxy; - String packageName = proxy.getActivity().getPackageName(); - Resources resources = proxy.getActivity().getResources(); - View viewWrapper; - - int resId_viewHolder; - int resId_lottie; - - resId_viewHolder = resources.getIdentifier("layout_lottie", "layout", packageName); - resId_lottie = resources.getIdentifier("animation_view", "id", packageName); - - LayoutInflater inflater = LayoutInflater.from(proxy.getActivity()); - viewWrapper = inflater.inflate(resId_viewHolder, null); - - lottieView = viewWrapper.findViewById(resId_lottie); - delegate = new TextDelegate(lottieView); - setNativeView(viewWrapper); - - setScaleMode(TiConvert.toString(proxy.getProperty("scaleMode"))); - lottieView.addAnimatorUpdateListener(new AnimatorUpdateListener()); - lottieView.addAnimatorListener(new AnimatorListener()); - lottieView.addLottieOnCompositionLoadedListener(this); - - if (TiConvert.toBoolean(proxy.getProperty("disableHardwareAcceleration"))) { - lottieView.setLayerType(View.LAYER_TYPE_SOFTWARE, null); - } else { - lottieView.setLayerType(View.LAYER_TYPE_HARDWARE, null); - } - lottieView.enableMergePathsForKitKatAndAbove(TiConvert.toBoolean(proxy.getProperty("mergePath"))); - } - - @Override - public void processProperties(KrollDict d) - { - super.processProperties(d); - - if (d.containsKey("scaleMode")) { - setScaleMode(d.getString("scaleMode")); - } - if (d.containsKey("disableHardwareAcceleration")) { - if (d.getBoolean("disableHardwareAcceleration")) { - lottieView.setLayerType(View.LAYER_TYPE_SOFTWARE, null); - } else { - lottieView.setLayerType(View.LAYER_TYPE_HARDWARE, null); - } - } - if (d.containsKey("loop")) { - lottieView.setRepeatCount(d.getBoolean("loop") ? LottieDrawable.INFINITE : 0); - } - if (d.containsKey("ready")) { - callbackReady = (KrollFunction) d.get("ready"); - } - if (d.containsKey("mergePath")) { - lottieView.enableMergePathsForKitKatAndAbove(d.getBoolean("mergePath")); - } - if (d.containsKey("progress")) { - setProgress(Float.parseFloat(d.getString("progress"))); - } - if (d.containsKey("speed")) { - Object speed = d.get("speed"); - if (speed != null) { - proxy.setProperty("duration", (initialDuration / TiConvert.toFloat(speed))); - } - } - if (d.containsKey("autoStart")) { - proxy.setProperty("autoStart", d.getBoolean("autoStart")); - } - if (d.containsKey("start")) { - if (d.getBoolean("start")) { - startAnimation(TiConvert.toInt(proxy.getProperty("startFrame")), - TiConvert.toInt(proxy.getProperty("endFrame"))); - } - } - - if (d.containsKey("file") && !d.getString("file").equals("")) { - if (TiApplication.isUIThread()) { - loadFile(d.getString("file")); - } else { - TiMessenger.sendBlockingMainMessage( - proxy.getMainHandler().obtainMessage(AnimationViewProxy.MSG_LOAD_FILE, d.getString("file"))); - } - } else if (d.containsKey("json")) { - loadJson(d.getString("json")); - } - } - - @Override - public void propertyChanged(String key, Object oldValue, Object newValue, KrollProxy proxy) - { - KrollDict d = new KrollDict(); - d.put(key, newValue); - processProperties(d); - } - - private void setScaleMode(String smode) - { - // Set scale mode on view - // - switch (smode) { - case "center": - lottieView.setScaleType(ScaleType.CENTER); - break; - case "centerCrop": - lottieView.setScaleType(ScaleType.CENTER_CROP); - break; - case "centerInside": - default: - lottieView.setScaleType(ScaleType.CENTER_INSIDE); - break; - } - } - - private void parseJson(String json) - { - try { - JSONObject jsonObject = new JSONObject(json); - proxy.setProperty("width", jsonObject.optInt("w", 0)); - proxy.setProperty("height", jsonObject.optInt("h", 0)); - } catch (Exception e) { - Log.e(LCAT, "Couldn't read width/height"); - } - } - - private void loadJson(String jsonString) - { - try { - parseJson(jsonString); - LottieCompositionFactory.fromJsonStringSync(jsonString, null); - } catch (Exception e) { - Log.e(LCAT, "Could not parse JSON string"); - } - } - - @Override - public void onCompositionLoaded(LottieComposition composition) - { - lottieView.setComposition(composition); - lottieView.setImageAssetsFolder("Resources/" + TiConvert.toString(proxy.getProperty("assetFolder"))); - lottieView.setTextDelegate(delegate); - - initialDuration = lottieView.getDuration(); - if (TiConvert.toFloat(proxy.getProperty("speed")) == 1.0f) { - proxy.setProperty("duration", initialDuration); - } else { - proxy.setProperty("duration", (initialDuration / TiConvert.toFloat(proxy.getProperty("speed")))); - } - if (TiConvert.toBoolean(proxy.getProperty("loop"))) { - lottieView.setRepeatCount(LottieDrawable.INFINITE); - } - if (TiConvert.toBoolean(proxy.getProperty("autoStart"))) { - startAnimation(TiConvert.toInt(proxy.getProperty("startFrame")), - TiConvert.toInt(proxy.getProperty("endFrame"))); - } - if (callbackReady != null) { - callbackReady.call(proxy.getKrollObject(), new KrollDict()); - } - ((AnimationViewProxy) proxy).readyEvent(new KrollDict()); - } - - void loadFile(String f) - { - String url = proxy.resolveUrl(null, f); - TiBaseFile file = TiFileFactory.createTitaniumFile(new String[] { url }, false); - - if (file.exists()) { - try { - InputStream stream = file.getInputStream(); - int size = stream.available(); - byte[] buffer = new byte[size]; - stream.read(buffer); - String json = new String(buffer, StandardCharsets.UTF_8); - parseJson(json); - lottieView.setAnimation(url.replaceAll("file:///android_asset/", "")); - } catch (Exception e) { - Log.e(LCAT, "Error opening file " + file.name()); - } - } else { - Log.e(LCAT, "File " + file.name() + " not found!"); - } - } - - protected class AnimatorUpdateListener implements ValueAnimator.AnimatorUpdateListener - { - public void onAnimationUpdate(ValueAnimator animation) - { - KrollDict event = new KrollDict(); - event.put("frame", lottieView.getFrame()); - event.put("status", AnimationViewProxy.ANIMATION_RUNNING); - ((AnimationViewProxy) proxy).updateEvent(event); - } - } - - protected class AnimatorListener implements Animator.AnimatorListener - { - public void onAnimationStart(Animator animation) - { - KrollDict event = new KrollDict(); - event.put("status", AnimationViewProxy.ANIMATION_START); - ((AnimationViewProxy) proxy).updateEvent(event); - } - - public void onAnimationEnd(Animator animation) - { - KrollDict event = new KrollDict(); - event.put("status", AnimationViewProxy.ANIMATION_END); - event.put("loop", TiConvert.toBoolean(proxy.getProperty("loop"))); - ((AnimationViewProxy) proxy).completeEvent(event); - } - - public void onAnimationCancel(Animator animation) - { - KrollDict event = new KrollDict(); - event.put("status", AnimationViewProxy.ANIMATION_CANCEL); - ((AnimationViewProxy) proxy).updateEvent(event); - } - - public void onAnimationRepeat(Animator animation) - { - KrollDict event = new KrollDict(); - event.put("status", AnimationViewProxy.ANIMATION_END); - event.put("loop", TiConvert.toBoolean(proxy.getProperty("loop"))); - ((AnimationViewProxy) proxy).completeEvent(event); - } - } - - void startAnimation(int startFrame, int endFrame) - { - lottieView.cancelAnimation(); - lottieView.setProgress(0f); - proxy.setProperty("paused", false); - - if (startFrame == -1 && TiConvert.toInt(proxy.getProperty("startFrame"),-1) != -1){ - startFrame = TiConvert.toInt(proxy.getProperty("startFrame"),-1); - } - - if (endFrame == -1 && TiConvert.toInt(proxy.getProperty("endFrame"),-1) != -1){ - endFrame = TiConvert.toInt(proxy.getProperty("endFrame"),-1); - } - - if (TiConvert.toFloat(proxy.getProperty("speed")) == 1.0f) { - if (startFrame != -1) { - lottieView.setMinFrame(startFrame); - } - if (endFrame != -1) { - lottieView.setMaxFrame(endFrame); - } - lottieView.playAnimation(); - va = null; - } else { - va = ValueAnimator.ofFloat(0f, 1f); - va.setDuration((long) TiConvert.toFloat(proxy.getProperty("duration"))); - - if (TiConvert.toBoolean(proxy.getProperty("loop"))) { - va.setRepeatCount(-1); - } - va.addUpdateListener(animation -> { - lottieView.setProgress((Float) animation.getAnimatedValue()); - KrollDict event = new KrollDict(); - event.put("frame", lottieView.getFrame()); - event.put("status", AnimationViewProxy.ANIMATION_RUNNING); - ((AnimationViewProxy) proxy).updateEvent(event); - }); - - va.addListener(new Animator.AnimatorListener() { - @Override - public void onAnimationStart(Animator animation) - { - } - @Override - public void onAnimationCancel(Animator animation) - { - } - @Override - public void onAnimationRepeat(Animator animation) - { - KrollDict event = new KrollDict(); - event.put("status", AnimationViewProxy.ANIMATION_END); - event.put("loop", TiConvert.toBoolean(proxy.getProperty("loop"))); - ((AnimationViewProxy) proxy).completeEvent(event); - } - @Override - public void onAnimationEnd(Animator animation) - { - KrollDict event = new KrollDict(); - event.put("status", AnimationViewProxy.ANIMATION_END); - event.put("loop", TiConvert.toBoolean(proxy.getProperty("loop"))); - ((AnimationViewProxy) proxy).completeEvent(event); - } - }); - va.start(); - } - } - - void pauseAnimation() - { - proxy.setProperty("paused", true); - - if (va != null) { - va.pause(); - } else { - lottieView.pauseAnimation(); - } - } - - void resumeAnimation() - { - proxy.setProperty("paused", false); - if (va != null) { - va.resume(); - } else { - lottieView.resumeAnimation(); - } - } - - void stopAnimation() - { - proxy.setProperty("paused", false); - if (va != null) { - va.cancel(); - } else { - lottieView.cancelAnimation(); - } - } - - void setProgress(float val) - { - lottieView.setProgress(val); - } - - void setFrame(int val) - { - lottieView.setFrame(val); - } - - void setText(String layer, String text) - { - delegate.setText(layer, text); - } - - float getProgress() - { - return lottieView.getProgress(); - } - - int getFrame() - { - return lottieView.getFrame(); - } +public class AnimationView extends TiUIView implements LottieOnCompositionLoadedListener { + + private static final String LCAT = "AnimationViewProxy"; + + private final LottieAnimationView lottieView; + private final TiViewProxy proxy; + private KrollFunction callbackReady = null; + private float initialDuration = 0; + private ValueAnimator va = null; + private final TextDelegate delegate; + + AnimationView(TiViewProxy proxy) { + super(proxy); + + this.proxy = proxy; + String packageName = proxy.getActivity().getPackageName(); + Resources resources = proxy.getActivity().getResources(); + View viewWrapper; + + int resId_viewHolder; + int resId_lottie; + + resId_viewHolder = resources.getIdentifier("layout_lottie", "layout", packageName); + resId_lottie = resources.getIdentifier("animation_view", "id", packageName); + + LayoutInflater inflater = LayoutInflater.from(proxy.getActivity()); + viewWrapper = inflater.inflate(resId_viewHolder, null); + + lottieView = viewWrapper.findViewById(resId_lottie); + delegate = new TextDelegate(lottieView); + setNativeView(viewWrapper); + + setScaleMode(TiConvert.toString(proxy.getProperty("scaleMode"))); + lottieView.addAnimatorUpdateListener(new AnimatorUpdateListener()); + lottieView.addAnimatorListener(new AnimatorListener()); + lottieView.addLottieOnCompositionLoadedListener(this); + + if (TiConvert.toBoolean(proxy.getProperty("disableHardwareAcceleration"))) { + lottieView.setLayerType(View.LAYER_TYPE_SOFTWARE, null); + } else { + lottieView.setLayerType(View.LAYER_TYPE_HARDWARE, null); + } + lottieView.enableMergePathsForKitKatAndAbove(TiConvert.toBoolean(proxy.getProperty("mergePath"))); + } + + @Override + public void processProperties(KrollDict d) { + super.processProperties(d); + + if (d.containsKey("scaleMode")) { + setScaleMode(d.getString("scaleMode")); + } + if (d.containsKey("disableHardwareAcceleration")) { + if (d.getBoolean("disableHardwareAcceleration")) { + lottieView.setLayerType(View.LAYER_TYPE_SOFTWARE, null); + } else { + lottieView.setLayerType(View.LAYER_TYPE_HARDWARE, null); + } + } + if (d.containsKey("loop")) { + lottieView.setRepeatCount(d.getBoolean("loop") ? LottieDrawable.INFINITE : 0); + } + if (d.containsKey("ready")) { + callbackReady = (KrollFunction) d.get("ready"); + } + if (d.containsKey("mergePath")) { + lottieView.enableMergePathsForKitKatAndAbove(d.getBoolean("mergePath")); + } + if (d.containsKey("progress")) { + setProgress(Float.parseFloat(d.getString("progress"))); + } + if (d.containsKey("speed")) { + Object speed = d.get("speed"); + if (speed != null) { + proxy.setProperty("duration", (initialDuration / TiConvert.toFloat(speed))); + } + } + if (d.containsKey("autoStart")) { + proxy.setProperty("autoStart", d.getBoolean("autoStart")); + } + if (d.containsKey("start")) { + if (d.getBoolean("start")) { + startAnimation(TiConvert.toInt(proxy.getProperty("startFrame")), + TiConvert.toInt(proxy.getProperty("endFrame"))); + } + } + + if (d.containsKey("file") && !d.getString("file").equals("")) { + if (TiApplication.isUIThread()) { + loadFile(d.getString("file")); + } else { + TiMessenger.sendBlockingMainMessage( + proxy.getMainHandler().obtainMessage(AnimationViewProxy.MSG_LOAD_FILE, d.getString("file"))); + } + } else if (d.containsKey("json")) { + loadJson(d.getString("json")); + } + } + + @Override + public void propertyChanged(String key, Object oldValue, Object newValue, KrollProxy proxy) { + KrollDict d = new KrollDict(); + d.put(key, newValue); + processProperties(d); + } + + private void setScaleMode(String smode) { + // Set scale mode on view + // + switch (smode) { + case "center": + lottieView.setScaleType(ScaleType.CENTER); + break; + case "centerCrop": + lottieView.setScaleType(ScaleType.CENTER_CROP); + break; + case "centerInside": + default: + lottieView.setScaleType(ScaleType.CENTER_INSIDE); + break; + } + } + + private void parseJson(String json) { + try { + JSONObject jsonObject = new JSONObject(json); + proxy.setProperty("width", jsonObject.optInt("w", 0)); + proxy.setProperty("height", jsonObject.optInt("h", 0)); + } catch (Exception e) { + Log.e(LCAT, "Couldn't read width/height"); + } + } + + private void loadJson(String jsonString) { + try { + parseJson(jsonString); + LottieCompositionFactory.fromJsonStringSync(jsonString, null); + } catch (Exception e) { + Log.e(LCAT, "Could not parse JSON string"); + } + } + + @Override + public void onCompositionLoaded(LottieComposition composition) { + lottieView.setComposition(composition); + lottieView.setImageAssetsFolder("Resources/" + TiConvert.toString(proxy.getProperty("assetFolder"))); + lottieView.setTextDelegate(delegate); + + initialDuration = lottieView.getDuration(); + if (TiConvert.toFloat(proxy.getProperty("speed")) == 1.0f) { + proxy.setProperty("duration", initialDuration); + } else { + proxy.setProperty("duration", (initialDuration / TiConvert.toFloat(proxy.getProperty("speed")))); + } + if (TiConvert.toBoolean(proxy.getProperty("loop"))) { + lottieView.setRepeatCount(LottieDrawable.INFINITE); + } + if (TiConvert.toBoolean(proxy.getProperty("autoStart"))) { + startAnimation(TiConvert.toInt(proxy.getProperty("startFrame")), + TiConvert.toInt(proxy.getProperty("endFrame"))); + } + if (callbackReady != null) { + callbackReady.call(proxy.getKrollObject(), new KrollDict()); + } + ((AnimationViewProxy) proxy).readyEvent(new KrollDict()); + } + + void loadFile(String f) { + String url = proxy.resolveUrl(null, f); + TiBaseFile file = TiFileFactory.createTitaniumFile(new String[]{url}, false); + + if (file.exists()) { + try { + InputStream stream = file.getInputStream(); + int size = stream.available(); + byte[] buffer = new byte[size]; + stream.read(buffer); + String json = new String(buffer, StandardCharsets.UTF_8); + parseJson(json); + lottieView.setAnimation(url.replaceAll("file:///android_asset/", "")); + } catch (Exception e) { + Log.e(LCAT, "Error opening file " + file.name()); + } + } else { + Log.e(LCAT, "File " + file.name() + " not found!"); + } + } + + void startAnimation(int startFrame, int endFrame) { + lottieView.cancelAnimation(); + lottieView.setProgress(0f); + proxy.setProperty("paused", false); + + if (startFrame == -1 && TiConvert.toInt(proxy.getProperty("startFrame"), -1) != -1) { + startFrame = TiConvert.toInt(proxy.getProperty("startFrame"), -1); + } + + if (endFrame == -1 && TiConvert.toInt(proxy.getProperty("endFrame"), -1) != -1) { + endFrame = TiConvert.toInt(proxy.getProperty("endFrame"), -1); + } + + if (TiConvert.toFloat(proxy.getProperty("speed")) == 1.0f) { + if (startFrame != -1) { + lottieView.setMinFrame(startFrame); + } + if (endFrame != -1) { + lottieView.setMaxFrame(endFrame); + } + lottieView.playAnimation(); + va = null; + } else { + va = ValueAnimator.ofFloat(0f, 1f); + va.setDuration((long) TiConvert.toFloat(proxy.getProperty("duration"))); + + if (TiConvert.toBoolean(proxy.getProperty("loop"))) { + va.setRepeatCount(-1); + } + va.addUpdateListener(animation -> { + lottieView.setProgress((Float) animation.getAnimatedValue()); + KrollDict event = new KrollDict(); + event.put("frame", lottieView.getFrame()); + event.put("status", AnimationViewProxy.ANIMATION_RUNNING); + ((AnimationViewProxy) proxy).updateEvent(event); + }); + + va.addListener(new Animator.AnimatorListener() { + @Override + public void onAnimationStart(Animator animation) { + } + + @Override + public void onAnimationCancel(Animator animation) { + } + + @Override + public void onAnimationRepeat(Animator animation) { + KrollDict event = new KrollDict(); + event.put("status", AnimationViewProxy.ANIMATION_END); + event.put("loop", TiConvert.toBoolean(proxy.getProperty("loop"))); + ((AnimationViewProxy) proxy).completeEvent(event); + } + + @Override + public void onAnimationEnd(Animator animation) { + KrollDict event = new KrollDict(); + event.put("status", AnimationViewProxy.ANIMATION_END); + event.put("loop", TiConvert.toBoolean(proxy.getProperty("loop"))); + ((AnimationViewProxy) proxy).completeEvent(event); + } + }); + va.start(); + } + } + + void pauseAnimation() { + proxy.setProperty("paused", true); + + if (va != null) { + va.pause(); + } else { + lottieView.pauseAnimation(); + } + } + + void resumeAnimation() { + proxy.setProperty("paused", false); + if (va != null) { + va.resume(); + } else { + lottieView.resumeAnimation(); + } + } + + void stopAnimation() { + proxy.setProperty("paused", false); + if (va != null) { + va.cancel(); + } else { + lottieView.cancelAnimation(); + } + } + + void setText(String layer, String text) { + delegate.setText(layer, text); + } + + float getProgress() { + return lottieView.getProgress(); + } + + void setProgress(float val) { + lottieView.setProgress(val); + } + + int getFrame() { + return lottieView.getFrame(); + } + + void setFrame(int val) { + lottieView.setFrame(val); + } + + protected class AnimatorUpdateListener implements ValueAnimator.AnimatorUpdateListener { + public void onAnimationUpdate(ValueAnimator animation) { + KrollDict event = new KrollDict(); + event.put("frame", lottieView.getFrame()); + event.put("status", AnimationViewProxy.ANIMATION_RUNNING); + ((AnimationViewProxy) proxy).updateEvent(event); + } + } + + protected class AnimatorListener implements Animator.AnimatorListener { + public void onAnimationStart(Animator animation) { + KrollDict event = new KrollDict(); + event.put("status", AnimationViewProxy.ANIMATION_START); + ((AnimationViewProxy) proxy).updateEvent(event); + } + + public void onAnimationEnd(Animator animation) { + KrollDict event = new KrollDict(); + event.put("status", AnimationViewProxy.ANIMATION_END); + event.put("loop", TiConvert.toBoolean(proxy.getProperty("loop"))); + ((AnimationViewProxy) proxy).completeEvent(event); + } + + public void onAnimationCancel(Animator animation) { + KrollDict event = new KrollDict(); + event.put("status", AnimationViewProxy.ANIMATION_CANCEL); + ((AnimationViewProxy) proxy).updateEvent(event); + } + + public void onAnimationRepeat(Animator animation) { + KrollDict event = new KrollDict(); + event.put("status", AnimationViewProxy.ANIMATION_END); + event.put("loop", TiConvert.toBoolean(proxy.getProperty("loop"))); + ((AnimationViewProxy) proxy).completeEvent(event); + } + } } diff --git a/android/src/ti/animation/AnimationViewProxy.java b/android/src/ti/animation/AnimationViewProxy.java index 3b73dd9..b01bd8c 100644 --- a/android/src/ti/animation/AnimationViewProxy.java +++ b/android/src/ti/animation/AnimationViewProxy.java @@ -7,219 +7,207 @@ */ package ti.animation; +import android.app.Activity; +import android.os.Message; + +import org.appcelerator.kroll.KrollDict; import org.appcelerator.kroll.KrollProxy; import org.appcelerator.kroll.annotations.Kroll; +import org.appcelerator.kroll.common.AsyncResult; import org.appcelerator.kroll.common.TiConfig; +import org.appcelerator.kroll.common.TiMessenger; +import org.appcelerator.titanium.TiApplication; import org.appcelerator.titanium.proxy.TiViewProxy; import org.appcelerator.titanium.view.TiUIView; -import android.app.Activity; -import org.appcelerator.titanium.TiApplication; -import android.os.Message; -import org.appcelerator.kroll.common.TiMessenger; -import org.appcelerator.kroll.common.AsyncResult; -import org.appcelerator.kroll.KrollDict; @Kroll.proxy(creatableInModule = TiAnimationModule.class, - propertyAccessors = { "file", "scaleMode", "disableHardwareAcceleration", "mergePath", "update", - "autoStart", "loop", "assetFolder", "width", "height", "duration", "paused", "speed", - "startFrame", "endFrame", "json" }) - -public class AnimationViewProxy extends TiViewProxy -{ - // Standard Debugging variables - private static final String LCAT = "AnimationViewProxy"; - private static final boolean DBG = TiConfig.LOGD; - - static final int MSG_START_ANIMATION = KrollProxy.MSG_LAST_ID + 101; - static final int MSG_LOAD_FILE = KrollProxy.MSG_LAST_ID + 102; - static final int MSG_PAUSE_ANIMATION = KrollProxy.MSG_LAST_ID + 103; - static final int MSG_RESUME_ANIMATION = KrollProxy.MSG_LAST_ID + 104; - static final int MSG_STOP_ANIMATION = KrollProxy.MSG_LAST_ID + 105; - - @Kroll.constant - static final int ANIMATION_START = 1; - @Kroll.constant - static final int ANIMATION_END = 2; - @Kroll.constant - static final int ANIMATION_CANCEL = 3; - @Kroll.constant - static final int ANIMATION_REPEAT = 4; - @Kroll.constant - static final int ANIMATION_RUNNING = 5; - - // Constructor - public AnimationViewProxy() - { - super(); - defaultValues.put("scaleMode", "center_inside"); - defaultValues.put("disableHardwareAcceleration", false); - defaultValues.put("mergePath", false); - defaultValues.put("autoStart", false); - defaultValues.put("loop", false); - defaultValues.put("assetFolder", ""); - defaultValues.put("speed", 1); - defaultValues.put("startFrame", -1); - defaultValues.put("endFrame", -1); - defaultValues.put("duration", 0); - defaultValues.put("file", ""); - defaultValues.put("json", ""); - defaultValues.put("paused", false); - } - - @Override - public TiUIView createView(Activity activity) - { - TiUIView view = new AnimationView(this); - view.getLayoutParams().autoFillsHeight = true; - view.getLayoutParams().autoFillsWidth = true; - return view; - } - protected AnimationView getView() - { - return (AnimationView) getOrCreateView(); - } - - public boolean handleMessage(Message message) - { - AsyncResult result = null; - switch (message.what) { - case MSG_LOAD_FILE: { - result = (AsyncResult) message.obj; - getView().loadFile((String) result.getArg()); - result.setResult(null); - return true; - } - case MSG_START_ANIMATION: { - result = (AsyncResult) message.obj; - int[] frames = (int[]) result.getArg(); - getView().startAnimation(frames[0], frames[1]); - result.setResult(null); - return true; - } - case MSG_PAUSE_ANIMATION: { - getView().pauseAnimation(); - result.setResult(null); - return true; - } - case MSG_RESUME_ANIMATION: { - getView().resumeAnimation(); - result.setResult(null); - return true; - } - case MSG_STOP_ANIMATION: { - getView().stopAnimation(); - result.setResult(null); - return true; - } - } - - return super.handleMessage(message); - } - - @Kroll.method - public void start(@Kroll.argument(optional = true) int fromFrame, @Kroll.argument(optional = true) int endFrame) - { - if (TiApplication.isUIThread()) { - getView().startAnimation(fromFrame, endFrame); - } else { - TiMessenger.sendBlockingMainMessage(getMainHandler().obtainMessage(MSG_START_ANIMATION), - new int[] { fromFrame, endFrame }); - } - } - - @Kroll.method - public void resume() - { - if (TiApplication.isUIThread()) { - getView().resumeAnimation(); - } else { - TiMessenger.sendBlockingMainMessage(getMainHandler().obtainMessage(MSG_RESUME_ANIMATION)); - } - } - - @Kroll.method - public void stop() - { - if (TiApplication.isUIThread()) { - getView().stopAnimation(); - } else { - TiMessenger.sendBlockingMainMessage(getMainHandler().obtainMessage(MSG_STOP_ANIMATION)); - } - } - - @Kroll.method - public void pause() - { - if (TiApplication.isUIThread()) { - getView().pauseAnimation(); - } else { - TiMessenger.sendBlockingMainMessage(getMainHandler().obtainMessage(MSG_PAUSE_ANIMATION)); - } - } - - // clang-format off - @Kroll.setProperty - @Kroll.method - public void setText(String layer, String text) - // clang-format on - { - getView().setText(layer, text); - } - - // clang-format off - @Kroll.setProperty - @Kroll.method - public void setProgress(float val) - // clang-format on - { - getView().setProgress(val); - } - - // clang-format off - @Kroll.getProperty - @Kroll.method - public float getProgress() - // clang-format on - { - return getView().getProgress(); - } - - // clang-format off - @Kroll.setProperty - @Kroll.method - public void setFrame(int val) - // clang-format on - { - getView().setFrame(val); - } - - // clang-format off - @Kroll.getProperty - @Kroll.method - public int getFrame() - // clang-format on - { - return getView().getFrame(); - } - - void updateEvent(KrollDict event) - { - if (hasListeners("update")) { - fireEvent("update", event); - } - } - - void completeEvent(KrollDict event) - { - if (hasListeners("complete")) { - fireEvent("complete", event); - } - } - - void readyEvent(KrollDict event) - { - if (hasListeners("ready")) { - fireEvent("ready", event); - } - } + propertyAccessors = {"file", "scaleMode", "disableHardwareAcceleration", "mergePath", "update", + "autoStart", "loop", "assetFolder", "width", "height", "duration", "paused", "speed", + "startFrame", "endFrame", "json"}) + +public class AnimationViewProxy extends TiViewProxy { + static final int MSG_START_ANIMATION = KrollProxy.MSG_LAST_ID + 101; + static final int MSG_LOAD_FILE = KrollProxy.MSG_LAST_ID + 102; + static final int MSG_PAUSE_ANIMATION = KrollProxy.MSG_LAST_ID + 103; + static final int MSG_RESUME_ANIMATION = KrollProxy.MSG_LAST_ID + 104; + static final int MSG_STOP_ANIMATION = KrollProxy.MSG_LAST_ID + 105; + @Kroll.constant + static final int ANIMATION_START = 1; + @Kroll.constant + static final int ANIMATION_END = 2; + @Kroll.constant + static final int ANIMATION_CANCEL = 3; + @Kroll.constant + static final int ANIMATION_REPEAT = 4; + @Kroll.constant + static final int ANIMATION_RUNNING = 5; + // Standard Debugging variables + private static final String LCAT = "AnimationViewProxy"; + private static final boolean DBG = TiConfig.LOGD; + + // Constructor + public AnimationViewProxy() { + super(); + defaultValues.put("scaleMode", "center_inside"); + defaultValues.put("disableHardwareAcceleration", false); + defaultValues.put("mergePath", false); + defaultValues.put("autoStart", false); + defaultValues.put("loop", false); + defaultValues.put("assetFolder", ""); + defaultValues.put("speed", 1); + defaultValues.put("startFrame", -1); + defaultValues.put("endFrame", -1); + defaultValues.put("duration", 0); + defaultValues.put("file", ""); + defaultValues.put("json", ""); + defaultValues.put("paused", false); + } + + @Override + public TiUIView createView(Activity activity) { + TiUIView view = new AnimationView(this); + view.getLayoutParams().autoFillsHeight = true; + view.getLayoutParams().autoFillsWidth = true; + return view; + } + + protected AnimationView getView() { + return (AnimationView) getOrCreateView(); + } + + public boolean handleMessage(Message message) { + AsyncResult result = null; + switch (message.what) { + case MSG_LOAD_FILE: { + result = (AsyncResult) message.obj; + getView().loadFile((String) result.getArg()); + result.setResult(null); + return true; + } + case MSG_START_ANIMATION: { + result = (AsyncResult) message.obj; + int[] frames = (int[]) result.getArg(); + getView().startAnimation(frames[0], frames[1]); + result.setResult(null); + return true; + } + case MSG_PAUSE_ANIMATION: { + getView().pauseAnimation(); + result.setResult(null); + return true; + } + case MSG_RESUME_ANIMATION: { + getView().resumeAnimation(); + result.setResult(null); + return true; + } + case MSG_STOP_ANIMATION: { + getView().stopAnimation(); + result.setResult(null); + return true; + } + } + + return super.handleMessage(message); + } + + @Kroll.method + public void start(@Kroll.argument(optional = true) int fromFrame, @Kroll.argument(optional = true) int endFrame) { + if (TiApplication.isUIThread()) { + getView().startAnimation(fromFrame, endFrame); + } else { + TiMessenger.sendBlockingMainMessage(getMainHandler().obtainMessage(MSG_START_ANIMATION), + new int[]{fromFrame, endFrame}); + } + } + + @Kroll.method + public void resume() { + if (TiApplication.isUIThread()) { + getView().resumeAnimation(); + } else { + TiMessenger.sendBlockingMainMessage(getMainHandler().obtainMessage(MSG_RESUME_ANIMATION)); + } + } + + @Kroll.method + public void stop() { + if (TiApplication.isUIThread()) { + getView().stopAnimation(); + } else { + TiMessenger.sendBlockingMainMessage(getMainHandler().obtainMessage(MSG_STOP_ANIMATION)); + } + } + + @Kroll.method + public void pause() { + if (TiApplication.isUIThread()) { + getView().pauseAnimation(); + } else { + TiMessenger.sendBlockingMainMessage(getMainHandler().obtainMessage(MSG_PAUSE_ANIMATION)); + } + } + + // clang-format off + @Kroll.setProperty + @Kroll.method + public void setText(String layer, String text) + // clang-format on + { + getView().setText(layer, text); + } + + // clang-format off + @Kroll.getProperty + @Kroll.method + public float getProgress() + // clang-format on + { + return getView().getProgress(); + } + + // clang-format off + @Kroll.setProperty + @Kroll.method + public void setProgress(float val) + // clang-format on + { + getView().setProgress(val); + } + + // clang-format off + @Kroll.getProperty + @Kroll.method + public int getFrame() + // clang-format on + { + return getView().getFrame(); + } + + // clang-format off + @Kroll.setProperty + @Kroll.method + public void setFrame(int val) + // clang-format on + { + getView().setFrame(val); + } + + void updateEvent(KrollDict event) { + if (hasListeners("update")) { + fireEvent("update", event); + } + } + + void completeEvent(KrollDict event) { + if (hasListeners("complete")) { + fireEvent("complete", event); + } + } + + void readyEvent(KrollDict event) { + if (hasListeners("ready")) { + fireEvent("ready", event); + } + } } diff --git a/android/src/ti/animation/TiAnimationModule.java b/android/src/ti/animation/TiAnimationModule.java index ef23581..6c1187b 100644 --- a/android/src/ti/animation/TiAnimationModule.java +++ b/android/src/ti/animation/TiAnimationModule.java @@ -11,7 +11,6 @@ import org.appcelerator.kroll.annotations.Kroll.module; @module(name = "TiAnimation", id = "ti.animation") -public class TiAnimationModule extends KrollModule -{ +public class TiAnimationModule extends KrollModule { }