i have set up an animationLayer as described in the docs. most things work fine, but there is one issue:
when waking the watch up (onExitSleep, by hand motion or button) the last frame of the animation is diplayed for a fraction, before the animation starts paying.
weirdly enoguh, this does not happen when swiping to the watch face (onShow) from another menu. then the animation starts correctly with the first frame.
as my animation is an appear-style animation that start with a black screen, it is a bit jarring to have "final" image shown first, then disappear again and appear again.
this does not happen in the device simulator (using settings > lowPowerMode), but on the actual watch, a venu 2 the wrong frame is there.
i already tried several approaches:
- changing order of function calls -> no effect at all
- hiding the animationLayer, then showing it later on -> very inconsistent
- clearing the animation layer dc -> not allowed
how can this be avoided / what could be an issue causing this?
for reference, this is the watch face:
https://apps.garmin.com/en-US/apps/4d2a8dec-609e-479d-990a-4ae6a563fee4
code:
//! Responds to animation events
class AnimationDelegate extends WatchUi.AnimationDelegate {
private var _view as PentagramView;
//! Constructor
//! @param view The watch face view
public function initialize(view as PentagramView) {
_view = view;
WatchUi.AnimationDelegate.initialize();
}
//! Handle an animation event
//! @param event The animation event
//! @param options A dictionary of animation options
public function onAnimationEvent(
event as AnimationEvent,
options as Dictionary
) as Void {
// call stop once the animation has played fully
if (event == WatchUi.ANIMATION_EVENT_COMPLETE
|| event == WatchUi.ANIMATION_EVENT_CANCELED) {
_view.stop(); //stop the watch face manually, but is this needed? it doesnt loop if we dont do it...
}
}
}
class PentagramView extends WatchUi.WatchFace {
private var _animationLayer as AnimationLayer;
private var _drawLayer as Layer;
private var _drawLayerArea as Array<Number>;
private var _width as Number;
private var _font as FontResource?;
private var _fontSml as FontResource?;
private var _isAwake as Boolean?;
private var _smallDisplay as Boolean?;
//called when the watch face intializes
function initialize() {
WatchFace.initialize();
var settings = System.getDeviceSettings();
_width = settings.screenWidth;
// draw layer will be full screen
_drawLayerArea = [
0,
0,
settings.screenWidth,
settings.screenHeight,
] as Array<Number>;
// create animation Layer
_animationLayer = new WatchUi.AnimationLayer(
$.Rez.Drawables.pentagramU,
null
);
// create draw layer
_drawLayer = new WatchUi.Layer({
:locX => _drawLayerArea[0],
:locY => _drawLayerArea[1],
:width => _drawLayerArea[2],
:height => _drawLayerArea[3],
});
_smallDisplay = _width < 360;
_isAwake = true;
}
// Load your resources here
function onLayout(dc as Dc) as Void {
setLayout(Rez.Layouts.WatchFace(dc));
_font = WatchUi.loadResource($.Rez.Fonts.id_font_bmpfontLrg) as FontResource;
_fontSml = WatchUi.loadResource($.Rez.Fonts.id_font_bmpfontSml) as FontResource;
// clear the whole screen with solid color
dc.setColor(Graphics.COLOR_BLACK, Graphics.COLOR_BLACK);
dc.clear();
// add the layers to the view
addLayer(_animationLayer);
addLayer(_drawLayer);
}
// Called when this View is brought to the foreground. Restore
// the state of this View and prepare it to be shown. This includes
// loading resources into memory.
function onShow() as Void {
play();
}
// Update the view
function onUpdate(dc as Dc) as Void {
if(!_isAwake){
// clear the whole screen with solid color
dc.setColor(Graphics.COLOR_BLACK, Graphics.COLOR_BLACK);
dc.clear();
}
// Update the entire draw layer
updateWatchOverlay(true);
}
// Called when this View is removed from the screen. Save the
// state of this View here. This includes freeing resources from
// memory.
function onHide() as Void {
// invoke default View.onHide() which will stop all animations
View.onHide();
}
// The user has just looked at their watch. Timers and animations may be started here.
function onExitSleep() as Void {
_isAwake = true;
//self.requestUpdate(); //this does not help.
_animationLayer.setVisible(true);
play();
}
// Terminate any active timers and prepare for slow updates.
function onEnterSleep() as Void {
// animation playback will be stopped by system after entering sleep mode
//also hide the animation layer
_isAwake = false;
stop(); //do we need to stop? does not seem to make a difference
_animationLayer.setVisible(false);
}
//start the animation
function play() {
_animationLayer.play({
:delegate => new AnimationDelegate(self)
});
}
//stop the animation
function stop() {
_animationLayer.stop();
}