From 7c8d00fbe7aa666a8c8bc48a8722fbb5dc42d975 Mon Sep 17 00:00:00 2001 From: Andrei Misiukevich Date: Mon, 9 Nov 2020 18:01:29 +0300 Subject: [PATCH] Fixed iOS crash, added new props --- README.md | 2 + TouchEffect.iOS/PlatformTouchEff.cs | 2 +- TouchEffect/TouchEff.cs | 86 +++++++++++++++++++---------- TouchEffect/TouchImage.cs | 2 +- TouchEffect/TouchVisualManager.cs | 60 ++++++++------------ 5 files changed, 82 insertions(+), 70 deletions(-) diff --git a/README.md b/README.md index 06d67a5..ebb8e05 100644 --- a/README.md +++ b/README.md @@ -155,6 +155,8 @@ HoveredRotationX | `double` | 0.0 | RotationX of hovered state RegularRotationY | `double` | 0.0 | RotationY of regular state PressedRotationY | `double` | 0.0 | RotationY of pressed state HoveredRotationY | `double` | 0.0 | RotationY of hovered state +AnimationDuration | `int` | 0 | The common duration of animation +AnimationEasing | `Easing` | null | The common easing of animation PressedAnimationDuration | `int` | 0 | The duration of animation by applying PressedOpacity and/or PressedBackgroundColor and/or PressedScale PressedAnimationEasing | `Easing` | null | The easing of animation by applying PressedOpacity and/or PressedBackgroundColor and/or PressedScale HoveredAnimationDuration | `int` | 0 | The duration of animation by applying HoveredOpacity and/or HoveredBackgroundColor and/or HoveredScale diff --git a/TouchEffect.iOS/PlatformTouchEff.cs b/TouchEffect.iOS/PlatformTouchEff.cs index 58ca755..161b955 100644 --- a/TouchEffect.iOS/PlatformTouchEff.cs +++ b/TouchEffect.iOS/PlatformTouchEff.cs @@ -152,7 +152,7 @@ public void HandleTouch(TouchStatus status, UserInteractionState? userInteractio _effect.HandleTouch(status); if (userInteractionState.HasValue) { - _effect.HandleUserInteraction(userInteractionState.Value); + _effect?.HandleUserInteraction(userInteractionState.Value); } if (_effect == null || !_effect.NativeAnimation || !_effect.CanExecute) diff --git a/TouchEffect/TouchEff.cs b/TouchEffect/TouchEff.cs index fbd9ee9..745b0c0 100644 --- a/TouchEffect/TouchEff.cs +++ b/TouchEffect/TouchEff.cs @@ -20,7 +20,7 @@ public class TouchEff : RoutingEffect public TouchEff() : base($"{nameof(TouchEffect)}.{nameof(TouchEff)}") => _visualManager = new TouchVisualManager(); - internal TouchEff(Func animationTaskGetter) : this() + internal TouchEff(Func animationTaskGetter) : this() => _visualManager.SetCustomAnimationTask(animationTaskGetter); public event TEffectStatusChangedHandler StatusChanged; @@ -38,7 +38,7 @@ internal TouchEff(Func - /// Android only - /// public static readonly BindableProperty DisallowTouchThresholdProperty = BindableProperty.CreateAttached( nameof(DisallowTouchThreshold), typeof(int), @@ -713,42 +723,54 @@ public static double GetPressedRotationY(BindableObject bindable) public static void SetPressedRotationY(BindableObject bindable, double value) => bindable.SetValue(PressedRotationYProperty, value); - public static int GetRegularAnimationDuration(BindableObject bindable) - => (int)bindable.GetValue(RegularAnimationDurationProperty); + public static int GetAnimationDuration(BindableObject bindable) + => (int)bindable.GetValue(AnimationDurationProperty); - public static void SetRegularAnimationDuration(BindableObject bindable, int value) - => bindable.SetValue(RegularAnimationDurationProperty, value); + public static void SetAnimationDuration(BindableObject bindable, int value) + => bindable.SetValue(AnimationDurationProperty, value); - public static int GetHoveredAnimationDuration(BindableObject bindable) - => (int)bindable.GetValue(HoveredAnimationDurationProperty); + public static Easing GetAnimationEasing(BindableObject bindable) + => bindable.GetValue(AnimationEasingProperty) as Easing; - public static void SetHoveredAnimationDuration(BindableObject bindable, int value) - => bindable.SetValue(HoveredAnimationDurationProperty, value); + public static void SetAnimationEasing(BindableObject bindable, Easing value) + => bindable.SetValue(AnimationEasingProperty, value); public static int GetPressedAnimationDuration(BindableObject bindable) - => (int)bindable.GetValue(PressedAnimationDurationProperty); + => (int)bindable.GetValue(PressedAnimationDurationProperty); public static void SetPressedAnimationDuration(BindableObject bindable, int value) => bindable.SetValue(PressedAnimationDurationProperty, value); + public static Easing GetPressedAnimationEasing(BindableObject bindable) + => bindable.GetValue(PressedAnimationEasingProperty) as Easing; + + public static void SetPressedAnimationEasing(BindableObject bindable, Easing value) + => bindable.SetValue(PressedAnimationEasingProperty, value); + + public static int GetRegularAnimationDuration(BindableObject bindable) + => (int)bindable.GetValue(RegularAnimationDurationProperty); + + public static void SetRegularAnimationDuration(BindableObject bindable, int value) + => bindable.SetValue(RegularAnimationDurationProperty, value); + public static Easing GetRegularAnimationEasing(BindableObject bindable) => bindable.GetValue(RegularAnimationEasingProperty) as Easing; public static void SetRegularAnimationEasing(BindableObject bindable, Easing value) => bindable.SetValue(RegularAnimationEasingProperty, value); + public static int GetHoveredAnimationDuration(BindableObject bindable) + => (int)bindable.GetValue(HoveredAnimationDurationProperty); + + public static void SetHoveredAnimationDuration(BindableObject bindable, int value) + => bindable.SetValue(HoveredAnimationDurationProperty, value); + public static Easing GetHoveredAnimationEasing(BindableObject bindable) => bindable.GetValue(HoveredAnimationEasingProperty) as Easing; public static void SetHoveredAnimationEasing(BindableObject bindable, Easing value) => bindable.SetValue(HoveredAnimationEasingProperty, value); - public static Easing GetPressedAnimationEasing(BindableObject bindable) - => bindable.GetValue(PressedAnimationEasingProperty) as Easing; - - public static void SetPressedAnimationEasing(BindableObject bindable, Easing value) - => bindable.SetValue(PressedAnimationEasingProperty, value); - public static int GetRippleCount(BindableObject bindable) => (int)bindable.GetValue(RippleCountProperty); @@ -909,16 +931,20 @@ public HoverState HoverState public double PressedRotationY => GetPressedRotationY(Control); + public int AnimationDuration => GetAnimationDuration(Control); + + public Easing AnimationEasing => GetAnimationEasing(Control); + public int PressedAnimationDuration => GetPressedAnimationDuration(Control); public Easing PressedAnimationEasing => GetPressedAnimationEasing(Control); public int RegularAnimationDuration => GetRegularAnimationDuration(Control); - public int HoveredAnimationDuration => GetHoveredAnimationDuration(Control); - public Easing RegularAnimationEasing => GetRegularAnimationEasing(Control); + public int HoveredAnimationDuration => GetHoveredAnimationDuration(Control); + public Easing HoveredAnimationEasing => GetHoveredAnimationEasing(Control); public int RippleCount => GetRippleCount(Control); diff --git a/TouchEffect/TouchImage.cs b/TouchEffect/TouchImage.cs index cd0d402..0aa484a 100644 --- a/TouchEffect/TouchImage.cs +++ b/TouchEffect/TouchImage.cs @@ -121,7 +121,7 @@ public bool ShouldSetImageOnAnimationEnd set => SetValue(ShouldSetImageOnAnimationEndProperty, value); } - private async Task GetAnimationTask(TouchEff sender, TouchState touchState, HoverState hoverState, int duration, CancellationToken token) + private async Task GetAnimationTask(TouchEff sender, TouchState touchState, HoverState hoverState, int duration, Easing easing, CancellationToken token) { var regularBackgroundImageSource = RegularBackgroundImageSource; var pressedBackgroundImageSource = PressedBackgroundImageSource; diff --git a/TouchEffect/TouchVisualManager.cs b/TouchEffect/TouchVisualManager.cs index 6a38801..f81ccd7 100644 --- a/TouchEffect/TouchVisualManager.cs +++ b/TouchEffect/TouchVisualManager.cs @@ -20,7 +20,7 @@ internal sealed class TouchVisualManager private CancellationTokenSource _animationTokenSource; - private Func _customAnimationTaskGetter; + private Func _customAnimationTaskGetter; private double? _durationMultiplier; @@ -197,7 +197,7 @@ internal void HandleLongPress(TouchEff sender) }); } - internal void SetCustomAnimationTask(Func animationTaskGetter) + internal void SetCustomAnimationTask(Func animationTaskGetter) => _customAnimationTaskGetter = animationTaskGetter; internal void Reset() @@ -219,6 +219,8 @@ internal void OnTapped(TouchEff sender) internal void AbortAnimations(TouchEff sender) { _animationTokenSource?.Cancel(); + _animationTokenSource?.Dispose(); + _animationTokenSource = null; var control = sender.Control; if (control == null) { @@ -250,7 +252,7 @@ private void UpdateVisualState(VisualElement visualElement, TouchState touchStat VisualStateManager.GoToState(visualElement, state); } - private async Task SetBackgroundColorAsync(TouchEff sender, TouchState touchState, HoverState hoverState, int duration) + private async Task SetBackgroundColorAsync(TouchEff sender, TouchState touchState, HoverState hoverState, int duration, Easing easing) { var regularBackgroundColor = sender.RegularBackgroundColor; var pressedBackgroundColor = sender.PressedBackgroundColor; @@ -268,17 +270,14 @@ private async Task SetBackgroundColorAsync(TouchEff sender, TouchState touchStat _defaultBackgroundColor = control.BackgroundColor; var color = GetBackgroundColor(regularBackgroundColor); - var easing = sender.RegularAnimationEasing; if (touchState == TouchState.Pressed) { color = GetBackgroundColor(pressedBackgroundColor); - easing = sender.PressedAnimationEasing; } else if (hoverState == HoverState.Hovering) { color = GetBackgroundColor(hoveredBackgroundColor); - easing = sender.HoveredAnimationEasing; } if (duration <= 0) @@ -297,7 +296,7 @@ private async Task SetBackgroundColorAsync(TouchEff sender, TouchState touchStat await animationCompletionSource.Task; } - private async Task SetOpacityAsync(TouchEff sender, TouchState touchState, HoverState hoverState, int duration) + private async Task SetOpacityAsync(TouchEff sender, TouchState touchState, HoverState hoverState, int duration, Easing easing) { var regularOpacity = sender.RegularOpacity; var pressedOpacity = sender.PressedOpacity; @@ -311,23 +310,20 @@ private async Task SetOpacityAsync(TouchEff sender, TouchState touchState, Hover } var opacity = regularOpacity; - var easing = sender.RegularAnimationEasing; if (touchState == TouchState.Pressed) { opacity = pressedOpacity; - easing = sender.PressedAnimationEasing; } else if (hoverState == HoverState.Hovering) { opacity = hoveredOpacity; - easing = sender.HoveredAnimationEasing; } await sender.Control.FadeTo(opacity, (uint)Abs(duration), easing); } - private async Task SetScaleAsync(TouchEff sender, TouchState touchState, HoverState hoverState, int duration) + private async Task SetScaleAsync(TouchEff sender, TouchState touchState, HoverState hoverState, int duration, Easing easing) { var regularScale = sender.RegularScale; var pressedScale = sender.PressedScale; @@ -341,17 +337,14 @@ private async Task SetScaleAsync(TouchEff sender, TouchState touchState, HoverSt } var scale = regularScale; - var easing = sender.RegularAnimationEasing; if (touchState == TouchState.Pressed) { scale = pressedScale; - easing = sender.PressedAnimationEasing; } else if (hoverState == HoverState.Hovering) { scale = hoveredScale; - easing = sender.HoveredAnimationEasing; } var control = sender.Control; @@ -367,7 +360,7 @@ private async Task SetScaleAsync(TouchEff sender, TouchState touchState, HoverSt await tcs.Task; } - private async Task SetTranslationAsync(TouchEff sender, TouchState touchState, HoverState hoverState, int duration) + private async Task SetTranslationAsync(TouchEff sender, TouchState touchState, HoverState hoverState, int duration, Easing easing) { var regularTranslationX = sender.RegularTranslationX; var pressedTranslationX = sender.PressedTranslationX; @@ -389,25 +382,22 @@ private async Task SetTranslationAsync(TouchEff sender, TouchState touchState, H var translationX = regularTranslationX; var translationY = regularTranslationY; - var easing = sender.RegularAnimationEasing; if (touchState == TouchState.Pressed) { translationX = pressedTranslationX; translationY = pressedTranslationY; - easing = sender.PressedAnimationEasing; } else if (hoverState == HoverState.Hovering) { translationX = hoveredTranslationX; translationY = hoveredTranslationY; - easing = sender.HoveredAnimationEasing; } await sender.Control.TranslateTo(translationX, translationY, (uint)Abs(duration), easing); } - private async Task SetRotationAsync(TouchEff sender, TouchState touchState, HoverState hoverState, int duration) + private async Task SetRotationAsync(TouchEff sender, TouchState touchState, HoverState hoverState, int duration, Easing easing) { var regularRotation = sender.RegularRotation; var pressedRotation = sender.PressedRotation; @@ -421,23 +411,20 @@ private async Task SetRotationAsync(TouchEff sender, TouchState touchState, Hove } var rotation = regularRotation; - var easing = sender.RegularAnimationEasing; if (touchState == TouchState.Pressed) { rotation = pressedRotation; - easing = sender.PressedAnimationEasing; } else if (hoverState == HoverState.Hovering) { rotation = hoveredRotation; - easing = sender.HoveredAnimationEasing; } await sender.Control.RotateTo(rotation, (uint)Abs(duration), easing); } - private async Task SetRotationXAsync(TouchEff sender, TouchState touchState, HoverState hoverState, int duration) + private async Task SetRotationXAsync(TouchEff sender, TouchState touchState, HoverState hoverState, int duration, Easing easing) { var regularRotationX = sender.RegularRotationX; var pressedRotationX = sender.PressedRotationX; @@ -451,23 +438,20 @@ private async Task SetRotationXAsync(TouchEff sender, TouchState touchState, Hov } var rotationX = regularRotationX; - var easing = sender.RegularAnimationEasing; if (touchState == TouchState.Pressed) { rotationX = pressedRotationX; - easing = sender.PressedAnimationEasing; } else if (hoverState == HoverState.Hovering) { rotationX = hoveredRotationX; - easing = sender.HoveredAnimationEasing; } await sender.Control.RotateXTo(rotationX, (uint)Abs(duration), easing); } - private async Task SetRotationYAsync(TouchEff sender, TouchState touchState, HoverState hoverState, int duration) + private async Task SetRotationYAsync(TouchEff sender, TouchState touchState, HoverState hoverState, int duration, Easing easing) { var regularRotationY = sender.RegularRotationY; var pressedRotationY = sender.PressedRotationY; @@ -481,17 +465,14 @@ private async Task SetRotationYAsync(TouchEff sender, TouchState touchState, Hov } var rotationY = regularRotationY; - var easing = sender.RegularAnimationEasing; if (touchState == TouchState.Pressed) { rotationY = pressedRotationY; - easing = sender.PressedAnimationEasing; } else if (hoverState == HoverState.Hovering) { rotationY = hoveredRotationY; - easing = sender.HoveredAnimationEasing; } await sender.Control.RotateYTo(rotationY, (uint)Abs(duration), easing); @@ -510,14 +491,17 @@ private Task GetAnimationTask(TouchEff sender, TouchState touchState, HoverState } var token = _animationTokenSource.Token; var duration = sender.RegularAnimationDuration; + var easing = sender.RegularAnimationEasing; if (touchState == TouchState.Pressed) { duration = sender.RegularAnimationDuration; + easing = sender.PressedAnimationEasing; } else if (hoverState == HoverState.Hovering) { duration = sender.HoveredAnimationDuration; + easing = sender.HoveredAnimationEasing; } duration = duration.AdjustDurationMultiplier(durationMultiplier); @@ -530,14 +514,14 @@ private Task GetAnimationTask(TouchEff sender, TouchState touchState, HoverState sender.RaiseAnimationStarted(touchState, hoverState, duration); return Task.WhenAll( - _customAnimationTaskGetter?.Invoke(sender, touchState, hoverState, duration, token) ?? Task.FromResult(true), - SetBackgroundColorAsync(sender, touchState, hoverState, duration), - SetOpacityAsync(sender, touchState, hoverState, duration), - SetScaleAsync(sender, touchState, hoverState, duration), - SetTranslationAsync(sender, touchState, hoverState, duration), - SetRotationAsync(sender, touchState, hoverState, duration), - SetRotationXAsync(sender, touchState, hoverState, duration), - SetRotationYAsync(sender, touchState, hoverState, duration), + _customAnimationTaskGetter?.Invoke(sender, touchState, hoverState, duration, easing, token) ?? Task.FromResult(true), + SetBackgroundColorAsync(sender, touchState, hoverState, duration, easing), + SetOpacityAsync(sender, touchState, hoverState, duration, easing), + SetScaleAsync(sender, touchState, hoverState, duration, easing), + SetTranslationAsync(sender, touchState, hoverState, duration, easing), + SetRotationAsync(sender, touchState, hoverState, duration, easing), + SetRotationXAsync(sender, touchState, hoverState, duration, easing), + SetRotationYAsync(sender, touchState, hoverState, duration, easing), Task.Run(async () => { _animationProgress = 0;