public static bool AbortAnimation(this IAnimatable self, string handle) { var key = new AnimatableKey(self, handle); if (!s_animations.ContainsKey(key) && !s_kinetics.ContainsKey(key)) { return(false); } Action abort = () => { AbortAnimation(key); AbortKinetic(key); }; if (Device.IsInvokeRequired) { Device.BeginInvokeOnMainThread(abort); } else { abort(); } return(true); }
static void AnimateKineticInternal(IAnimatable self, string name, Func <double, double, bool> callback, double velocity, double drag, Action finished = null) { var key = new AnimatableKey(self, name); AbortKinetic(key); double sign = velocity / Math.Abs(velocity); velocity = Math.Abs(velocity); int tick = Ticker.Default.Insert(step => { long ms = step; velocity -= drag * ms; velocity = Math.Max(0, velocity); var result = false; if (velocity > 0) { result = callback(sign * velocity * ms, velocity); } if (!result) { finished?.Invoke(); s_kinetics.Remove(key); } return(result); }); s_kinetics[key] = tick; }
static void AbortKinetic(AnimatableKey key) { if (!s_kinetics.ContainsKey(key)) { return; } Ticker.Default.Remove(s_kinetics[key]); s_kinetics.Remove(key); }
static void AbortAnimation(AnimatableKey key) { if (!s_animations.ContainsKey(key)) { return; } Info info = s_animations[key]; info.Tweener.ValueUpdated -= HandleTweenerUpdated; info.Tweener.Finished -= HandleTweenerFinished; info.Tweener.Stop(); info.Finished?.Invoke(1.0f, true); s_animations.Remove(key); }
public static bool AbortAnimation(this IAnimatable self, string handle) { var key = new AnimatableKey(self, handle); if (!s_animations.ContainsKey(key) && !s_kinetics.ContainsKey(key)) { return(false); } Action abort = () => { AbortAnimation(key); AbortKinetic(key); }; DoAction(self, abort); return(true); }
protected bool Equals(AnimatableKey other) { if (!string.Equals(Handle, other.Handle)) { return false; } IAnimatable thisAnimatable; if (!Animatable.TryGetTarget(out thisAnimatable)) { return false; } IAnimatable thatAnimatable; if (!other.Animatable.TryGetTarget(out thatAnimatable)) { return false; } return Equals(thisAnimatable, thatAnimatable); }
protected bool Equals(AnimatableKey other) { if (!string.Equals(Handle, other.Handle)) { return(false); } IAnimatable thisAnimatable; if (!Animatable.TryGetTarget(out thisAnimatable)) { return(false); } IAnimatable thatAnimatable; if (!other.Animatable.TryGetTarget(out thatAnimatable)) { return(false); } return(Equals(thisAnimatable, thatAnimatable)); }
static void AnimateInternal <T>(IAnimatable self, string name, Func <double, T> transform, Action <T> callback, uint rate, uint length, Easing easing, Action <T, bool> finished, Func <bool> repeat) { var key = new AnimatableKey(self, name); AbortAnimation(key); Action <double> step = f => callback(transform(f)); Action <double, bool> final = null; if (finished != null) { final = (f, b) => finished(transform(f), b); } var info = new Info { Rate = rate, Length = length, Easing = easing ?? Easing.Linear }; var tweener = new Tweener(info.Length); tweener.Handle = key; tweener.ValueUpdated += HandleTweenerUpdated; tweener.Finished += HandleTweenerFinished; info.Tweener = tweener; info.Callback = step; info.Finished = final; info.Repeat = repeat; info.Owner = new WeakReference <IAnimatable>(self); s_animations[key] = info; info.Callback(0.0f); tweener.Start(); }
static void AbortAnimation(AnimatableKey key) { // If multiple animations on the same view with the same name (IOW, the same AnimatableKey) are invoked // asynchronously (e.g., from the `[Animate]To` methods in `ViewExtensions`), it's possible to get into // a situation where after invoking the `Finished` handler below `s_animations` will have a new `Info` // object in it with the same AnimatableKey. We need to continue cancelling animations until that is no // longer the case; thus, the `while` loop. // If we don't cancel all of the animations popping in with this key, `AnimateInternal` will overwrite one // of them with the new `Info` object, and the overwritten animation will never complete; any `await` for // it will never return. while (s_animations.ContainsKey(key)) { Info info = s_animations[key]; s_animations.Remove(key); info.Tweener.ValueUpdated -= HandleTweenerUpdated; info.Tweener.Finished -= HandleTweenerFinished; info.Tweener.Stop(); info.Finished?.Invoke(1.0f, true); } }
public static bool AnimationIsRunning(this IAnimatable self, string handle) { var key = new AnimatableKey(self, handle); return(s_animations.ContainsKey(key)); }