internal void HandleTouch(TouchEff sender, TouchStatus status)
        {
            if (sender.IsDisabled)
            {
                return;
            }

            var canExecuteAction = sender.CanExecute;

            if (status != TouchStatus.Started || canExecuteAction)
            {
                if (!canExecuteAction)
                {
                    status = TouchStatus.Canceled;
                }

                var state = status == TouchStatus.Started
                  ? TouchState.Pressed
                  : TouchState.Regular;

                if (status == TouchStatus.Started)
                {
                    _animationProgress = 0;
                    _animationState    = state;
                }

                var isToggled = sender.IsToggled;
                if (isToggled.HasValue)
                {
                    if (status != TouchStatus.Started)
                    {
                        _durationMultiplier = (_animationState == TouchState.Pressed && !isToggled.Value) ||
                                              (_animationState == TouchState.Regular && isToggled.Value)
                            ? 1 - _animationProgress
                            : _animationProgress;

                        UpdateStatusAndState(sender, status, state);
                        if (status == TouchStatus.Canceled)
                        {
                            sender.ForceUpdateState(false);
                            return;
                        }
                        OnTapped(sender);
                        sender.IsToggled = !isToggled;
                        return;
                    }

                    state = isToggled.Value
                        ? TouchState.Regular
                        : TouchState.Pressed;
                }

                UpdateStatusAndState(sender, status, state);
            }

            if (status == TouchStatus.Completed)
            {
                OnTapped(sender);
            }
        }
        internal void HandleLongPress(TouchEff sender)
        {
            if (sender.State == TouchState.Regular)
            {
                _longPressTokenSource?.Cancel();
                _longPressTokenSource?.Dispose();
                _longPressTokenSource = null;
                return;
            }

            if (sender.LongPressCommand == null || sender.UserInteractionState == UserInteractionState.Idle)
            {
                return;
            }

            _longPressTokenSource = new CancellationTokenSource();
            Task.Delay(sender.LongPressDuration, _longPressTokenSource.Token).ContinueWith(t =>
            {
                if (t.IsCanceled)
                {
                    return;
                }

                sender.HandleUserInteraction(UserInteractionState.Idle);
                var involeLongPressCommand = new Action(() => sender.LongPressCommand?.Execute(sender.LongPressCommandParameter));
                if (Device.IsInvokeRequired)
                {
                    Device.BeginInvokeOnMainThread(involeLongPressCommand);
                    return;
                }
                involeLongPressCommand.Invoke();
            });
        }
        private async Task SetRotationYAsync(TouchEff sender, TouchState touchState, HoverState hoverState, int duration)
        {
            var regularRotationY = sender.RegularRotationY;
            var pressedRotationY = sender.PressedRotationY;
            var hoveredRotationY = sender.HoveredRotationY;

            if (Abs(regularRotationY) <= double.Epsilon &&
                Abs(pressedRotationY) <= double.Epsilon &&
                Abs(hoveredRotationY) <= double.Epsilon)
            {
                return;
            }

            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);
        }
Exemple #4
0
        private async Task SetRotationXAsync(TouchEff sender, TouchState touchState, HoverState hoverState, int duration, Easing easing)
        {
            var regularRotationX = sender.RegularRotationX;
            var pressedRotationX = sender.PressedRotationX;
            var hoveredRotationX = sender.HoveredRotationX;

            if (Abs(regularRotationX) <= double.Epsilon &&
                Abs(pressedRotationX) <= double.Epsilon &&
                Abs(hoveredRotationX) <= double.Epsilon)
            {
                return;
            }

            var rotationX = regularRotationX;

            if (touchState == TouchState.Pressed)
            {
                rotationX = pressedRotationX;
            }
            else if (hoverState == HoverState.Hovering)
            {
                rotationX = hoveredRotationX;
            }

            await sender.Control.RotateXTo(rotationX, (uint)Abs(duration), easing);
        }
Exemple #5
0
        private async Task SetTranslationAsync(TouchEff sender, TouchState state, int duration)
        {
            var regularTranslationX = sender.RegularTranslationX;
            var pressedTranslationX = sender.PressedTranslationX;

            var regularTranslationY = sender.RegularTranslationY;
            var pressedTranslationY = sender.PressedTranslationY;

            if (Abs(regularTranslationX) <= double.Epsilon &&
                Abs(pressedTranslationX) <= double.Epsilon &&
                Abs(regularTranslationY) <= double.Epsilon &&
                Abs(pressedTranslationY) <= double.Epsilon)
            {
                return;
            }

            var translationX = regularTranslationX;
            var translationY = regularTranslationY;
            var easing       = sender.RegularAnimationEasing;

            if (state == TouchState.Pressed)
            {
                translationX = pressedTranslationX;
                translationY = pressedTranslationY;
                easing       = sender.PressedAnimationEasing;
            }
            await sender.Control.TranslateTo(translationX, translationY, (uint)Abs(duration), easing);
        }
        private async Task SetOpacityAsync(TouchEff sender, TouchState touchState, HoverState hoverState, int duration)
        {
            var regularOpacity = sender.RegularOpacity;
            var pressedOpacity = sender.PressedOpacity;
            var hoveredOpacity = sender.HoveredOpacity;

            if (Abs(regularOpacity - 1) <= double.Epsilon &&
                Abs(pressedOpacity - 1) <= double.Epsilon &&
                Abs(hoveredOpacity - 1) <= double.Epsilon)
            {
                return;
            }

            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);
        }
Exemple #7
0
        internal async void ChangeStateAsync(TouchEff sender, bool animated)
        {
            var state = sender.State;

            AbortAnimations(sender);
            _animationTokenSource = new CancellationTokenSource();
            var token = _animationTokenSource.Token;

            var isToggled = sender.IsToggled;

            if (!animated)
            {
                if (isToggled.HasValue)
                {
                    state = isToggled.Value
                        ? TouchState.Pressed
                        : TouchState.Regular;
                }
                var durationMultiplier = _durationMultiplier;
                _durationMultiplier = null;
                await GetAnimationTask(sender, state, durationMultiplier.GetValueOrDefault());

                return;
            }

            var rippleCount = sender.RippleCount;

            if (rippleCount == 0 || (state == TouchState.Regular && !isToggled.HasValue))
            {
                await GetAnimationTask(sender, state);

                return;
            }
            do
            {
                var rippleState = isToggled.HasValue && isToggled.Value
                    ? TouchState.Regular
                    : TouchState.Pressed;

                await GetAnimationTask(sender, rippleState);

                if (token.IsCancellationRequested)
                {
                    return;
                }

                rippleState = isToggled.HasValue && isToggled.Value
                    ? TouchState.Pressed
                    : TouchState.Regular;

                await GetAnimationTask(sender, rippleState);

                if (token.IsCancellationRequested)
                {
                    return;
                }
            } while (--rippleCount != 0);
        }
 internal void OnTapped(TouchEff sender)
 {
     if (!sender.CanExecute || (sender.LongPressCommand != null && sender.UserInteractionState == UserInteractionState.Idle))
     {
         return;
     }
     sender.Command?.Execute(sender.CommandParameter);
     sender.RaiseCompleted();
 }
Exemple #9
0
 internal void OnTapped(TouchEff sender)
 {
     if (!sender.CanExecute)
     {
         return;
     }
     sender.Command?.Execute(sender.CommandParameter);
     sender.RaiseCompleted();
 }
Exemple #10
0
        private Task GetAnimationTask(TouchEff sender, TouchState touchState, HoverState hoverState, double?durationMultiplier = null)
        {
            if (sender.Control == null)
            {
                return(Task.CompletedTask);
            }
            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);

            if (duration <= 0 &&
                Device.RuntimePlatform != Device.iOS &&
                Device.RuntimePlatform != Device.macOS)
            {
                duration = 1;
            }

            sender.RaiseAnimationStarted(touchState, hoverState, duration);
            return(Task.WhenAll(
                       _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;
                _animationState = touchState;

                for (var progress = AnimationProgressDelay; progress < duration; progress += AnimationProgressDelay)
                {
                    await Task.Delay(AnimationProgressDelay).ConfigureAwait(false);
                    if (token.IsCancellationRequested)
                    {
                        return;
                    }
                    _animationProgress = (double)progress / duration;
                }
                _animationProgress = 1;
            })));
        }
 private void UpdateStatusAndState(TouchEff sender, TouchStatus status, TouchState state)
 {
     if (sender.State != state || status != TouchStatus.Canceled)
     {
         sender.State = state;
         sender.RaiseStateChanged();
     }
     sender.Status = status;
     sender.RaiseStatusChanged();
 }
 internal void AbortAnimations(TouchEff sender)
 {
     _animationTokenSource?.Cancel();
     var control = sender.Control;
     if (control == null)
     {
         return;
     }
     ViewExtensions.CancelAnimations(control);
     AnimationExtensions.AbortAnimation(control, ChangeBackgroundColorAnimationName);
 }
        private async Task SetBackgroundColorAsync(TouchEff sender, TouchState touchState, HoverState hoverState, int duration)
        {
            var regularBackgroundColor = sender.RegularBackgroundColor;
            var pressedBackgroundColor = sender.PressedBackgroundColor;
            var hoveredBackgroundColor = sender.HoveredBackgroundColor;

            if (regularBackgroundColor == Color.Default &&
                pressedBackgroundColor == Color.Default &&
                hoveredBackgroundColor == Color.Default)
            {
                return;
            }

            var control = sender.Control;

            if (_defaultBackgroundColor == default(Color))
            {
                _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)
            {
                control.BackgroundColor = color;
                return;
            }

            var animationCompletionSource = new TaskCompletionSource <bool>();

            new Animation {
                { 0, 1, new Animation(v => control.BackgroundColor = new Color(v, control.BackgroundColor.G, control.BackgroundColor.B, control.BackgroundColor.A), control.BackgroundColor.R, color.R) },
                { 0, 1, new Animation(v => control.BackgroundColor = new Color(control.BackgroundColor.R, v, control.BackgroundColor.B, control.BackgroundColor.A), control.BackgroundColor.G, color.G) },
                { 0, 1, new Animation(v => control.BackgroundColor = new Color(control.BackgroundColor.R, control.BackgroundColor.G, v, control.BackgroundColor.A), control.BackgroundColor.B, color.B) },
                { 0, 1, new Animation(v => control.BackgroundColor = new Color(control.BackgroundColor.R, control.BackgroundColor.G, control.BackgroundColor.B, v), control.BackgroundColor.A, color.A) },
            }.Commit(sender.Control, ChangeBackgroundColorAnimationName, 16, (uint)duration, easing, (d, b) => animationCompletionSource.SetResult(true));
            await animationCompletionSource.Task;
        }
        private Task GetAnimationTask(TouchEff sender, TouchState state, double? durationMultiplier = null)
        {
            if (sender.Control == null)
            {
                return Task.CompletedTask;
            }
            var token = _animationTokenSource.Token;
            var duration = (state == TouchState.Regular
                ? sender.RegularAnimationDuration
                : sender.PressedAnimationDuration).AdjustDurationMultiplier(durationMultiplier);

            if(duration <= 0 && Device.RuntimePlatform == Device.Android)
            {
                duration = 1;
            }

            sender.RaiseAnimationStarted(state, duration);
            return Task.WhenAll(
                _customAnimationTaskGetter?.Invoke(sender, state, duration, token) ?? Task.FromResult(true),
                SetBackgroundColorAsync(sender, state, duration),
                SetOpacityAsync(sender, state, duration),
                SetScaleAsync(sender, state, duration),
                SetTranslationAsync(sender, state, duration),
                SetRotationAsync(sender, state, duration),
                SetRotationXAsync(sender, state, duration),
                SetRotationYAsync(sender, state, duration),
                Task.Run(async () =>
                {
                    _animationProgress = 0;
                    _animationState = state;

                    for (var progress = AnimationProgressDelay; progress < duration; progress += AnimationProgressDelay)
                    {
                        await Task.Delay(AnimationProgressDelay).ConfigureAwait(false);
                        if (token.IsCancellationRequested)
                        {
                            return;
                        }
                        _animationProgress = (double)progress / duration;
                    }
                    _animationProgress = 1;
                }));
        }
        internal void HandleHover(TouchEff sender, HoverStatus status)
        {
            if (!sender.Control.IsEnabled) {
                return;
            }

            var hoverState = status == HoverStatus.Entered
                ? HoverState.Hovering
                : HoverState.Regular;

            if(sender.HoverState != hoverState)
            {
                sender.HoverState = hoverState;
                sender.RaiseHoverStateChanged();
            }

            sender.HoverStatus = status;
            sender.RaiseHoverStatusChanged();
        }
Exemple #16
0
        private async Task SetRotationXAsync(TouchEff sender, TouchState state, int duration)
        {
            var regularRotationX = sender.RegularRotationX;
            var pressedRotationX = sender.PressedRotationX;

            if (Abs(regularRotationX) <= double.Epsilon &&
                Abs(pressedRotationX) <= double.Epsilon)
            {
                return;
            }

            var rotationX = regularRotationX;
            var easing    = sender.RegularAnimationEasing;

            if (state == TouchState.Pressed)
            {
                rotationX = pressedRotationX;
                easing    = sender.PressedAnimationEasing;
            }
            await sender.Control.RotateXTo(rotationX, (uint)Abs(duration), easing);
        }
Exemple #17
0
        private async Task SetScaleAsync(TouchEff sender, TouchState state, int duration)
        {
            var regularScale = sender.RegularScale;
            var pressedScale = sender.PressedScale;

            if (Abs(regularScale - 1) <= double.Epsilon &&
                Abs(pressedScale - 1) <= double.Epsilon)
            {
                return;
            }

            var scale  = regularScale;
            var easing = sender.RegularAnimationEasing;

            if (state == TouchState.Pressed)
            {
                scale  = pressedScale;
                easing = sender.PressedAnimationEasing;
            }
            await sender.Control.ScaleTo(scale, (uint)Abs(duration), easing);
        }
        private async Task SetScaleAsync(TouchEff sender, TouchState touchState, HoverState hoverState, int duration)
        {
            var regularScale = sender.RegularScale;
            var pressedScale = sender.PressedScale;
            var hoveredScale = sender.HoveredScale;

            if (Abs(regularScale - 1) <= double.Epsilon &&
                Abs(pressedScale - 1) <= double.Epsilon &&
                Abs(hoveredScale - 1) <= double.Epsilon)
            {
                return;
            }

            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;
            var tcs     = new TaskCompletionSource <bool>();

            control.Animate($"{nameof(SetScaleAsync)}{control.Id}", v =>
            {
                if (double.IsNaN(v))
                {
                    return;
                }
                control.Scale = v;
            }, control.Scale, scale, 16, (uint)Abs(duration), easing, (v, b) => tcs.SetResult(b));
            await tcs.Task;
        }
Exemple #19
0
        private async Task SetTranslationAsync(TouchEff sender, TouchState touchState, HoverState hoverState, int duration, Easing easing)
        {
            var regularTranslationX = sender.RegularTranslationX;
            var pressedTranslationX = sender.PressedTranslationX;
            var hoveredTranslationX = sender.HoveredTranslationX;

            var regularTranslationY = sender.RegularTranslationY;
            var pressedTranslationY = sender.PressedTranslationY;
            var hoveredTranslationY = sender.HoveredTranslationY;

            if (Abs(regularTranslationX) <= double.Epsilon &&
                Abs(pressedTranslationX) <= double.Epsilon &&
                Abs(hoveredTranslationX) <= double.Epsilon &&
                Abs(regularTranslationY) <= double.Epsilon &&
                Abs(pressedTranslationY) <= double.Epsilon &&
                Abs(hoveredTranslationY) <= double.Epsilon)
            {
                return;
            }

            var translationX = regularTranslationX;
            var translationY = regularTranslationY;

            if (touchState == TouchState.Pressed)
            {
                translationX = pressedTranslationX;
                translationY = pressedTranslationY;
            }
            else if (hoverState == HoverState.Hovering)
            {
                translationX = hoveredTranslationX;
                translationY = hoveredTranslationY;
            }

            await sender.Control.TranslateTo(translationX, translationY, (uint)Abs(duration), easing);
        }
 private bool CanExecuteAction(TouchEff sender)
     => sender.Control.IsEnabled && ((sender.Command?.CanExecute(sender.CommandParameter) ?? false) || sender.IsCompletedSet);