unoplatform / uno

Build Mobile, Desktop and WebAssembly apps with C# and XAML. Today. Open source and professionally supported.
https://platform.uno
Apache License 2.0
8.77k stars 706 forks source link

[iOS, Android][CheckBox] Inconsistent transition animation. #3532

Open MaximeDion-Work opened 4 years ago

MaximeDion-Work commented 4 years ago

Current behavior

iOS: Animation starts at the right position, but then glitch to the lower right. image

Android: When clicking while the animation is already playing will reset the animation, but on circle expands from the top left. image

Expected behavior

When clicking a Checkbox animation should always be a circle expanding from the center.

How to reproduce it (as minimally and precisely as possible)

Relevant code: CheckBox.xaml (see VisualTransition on PressRingTransform)

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                    xmlns:xamarin="http://nventive.com/xamarin"
                    xmlns:ios="http://uno.ui/ios"
                    xmlns:android="http://uno.ui/android"
                    xmlns:wasm="http://uno.ui/wasm"
                    mc:Ignorable="xamarin ios android wasm">

    <GridLength x:Key="CheckAreaLength">40</GridLength>
    <x:Double x:Key="FocusAreaSize">40</x:Double>
    <x:Double x:Key="CheckAreaSize">18</x:Double>
    <CornerRadius x:Key="CheckAreaCornerRadius">4</CornerRadius>

    <Style x:Key="MaterialCheckBoxStyle"
           TargetType="CheckBox">

        <Setter Property="Background"
                Value="{ThemeResource SelectControlToggleOffButtonColor}" />
        <Setter Property="BorderBrush"
                Value="{ThemeResource SelectControlStrokeColor}" />
        <Setter Property="BorderThickness"
                Value="2" />
        <Setter Property="Padding"
                Value="8,0,0,0" />
        <Setter Property="HorizontalAlignment"
                Value="Left" />
        <Setter Property="VerticalAlignment"
                Value="Stretch" />
        <Setter Property="HorizontalContentAlignment"
                Value="Left" />
        <Setter Property="VerticalContentAlignment"
                Value="Center" />
        <Setter Property="MinWidth"
                Value="0" />
        <Setter Property="MinHeight"
                Value="{StaticResource CheckAreaSize}" />
        <Setter Property="UseSystemFocusVisuals"
                Value="False" />

        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="CheckBox">
                    <Grid x:Name="Root"
                          Background="Transparent">
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="CombinedStates">

                                <VisualState x:Name="UncheckedNormal" />
                                <VisualState x:Name="UncheckedPointerOver" />
                                <VisualState x:Name="UncheckedPressed" />

                                <VisualState x:Name="UncheckedDisabled">
                                    <VisualState.Setters>
                                        <Setter Target="BackgroundBorder.Opacity"
                                                Value="0.5" />
                                        <Setter Target="ContentPresenter.Opacity"
                                                Value="0.5" />
                                    </VisualState.Setters>
                                </VisualState>

                                <VisualState x:Name="CheckedNormal">
                                    <VisualState.Setters>
                                        <Setter Target="BackgroundBorder.Background"
                                                Value="{ThemeResource SelectControlBackgroundColor}" />
                                        <Setter Target="BackgroundBorder.BorderThickness"
                                                Value="0" />
                                        <Setter Target="CheckGlyph.Opacity"
                                                Value="1" />
                                    </VisualState.Setters>
                                </VisualState>

                                <VisualState x:Name="CheckedPointerOver">
                                    <VisualState.Setters>
                                        <Setter Target="BackgroundBorder.Background"
                                                Value="{ThemeResource SelectControlBackgroundColor}" />
                                        <Setter Target="BackgroundBorder.BorderThickness"
                                                Value="0" />
                                        <Setter Target="CheckGlyph.Opacity"
                                                Value="1" />
                                    </VisualState.Setters>
                                </VisualState>

                                <VisualState x:Name="CheckedPressed">
                                    <VisualState.Setters>
                                        <Setter Target="BackgroundBorder.Background"
                                                Value="{ThemeResource SelectControlBackgroundColor}" />
                                        <Setter Target="BackgroundBorder.BorderThickness"
                                                Value="0" />
                                        <Setter Target="CheckGlyph.Opacity"
                                                Value="1" />
                                    </VisualState.Setters>
                                </VisualState>

                                <VisualState x:Name="CheckedDisabled">
                                    <VisualState.Setters>
                                        <Setter Target="BackgroundBorder.Opacity"
                                                Value="0.5" />
                                        <Setter Target="ContentPresenter.Opacity"
                                                Value="0.5" />
                                        <Setter Target="BackgroundBorder.Background"
                                                Value="{ThemeResource SelectControlBackgroundColor}" />
                                        <Setter Target="BackgroundBorder.BorderThickness"
                                                Value="0" />
                                        <Setter Target="CheckGlyph.Opacity"
                                                Value="1" />
                                    </VisualState.Setters>
                                </VisualState>

                                <VisualState x:Name="IndeterminateNormal">
                                    <VisualState.Setters>
                                        <Setter Target="BackgroundBorder.Background"
                                                Value="{ThemeResource SelectControlBackgroundColor}" />
                                        <Setter Target="BackgroundBorder.BorderThickness"
                                                Value="0" />
                                        <Setter Target="HyphenGlyph.Opacity"
                                                Value="1" />
                                    </VisualState.Setters>
                                </VisualState>

                                <VisualState x:Name="IndeterminatePointerOver">
                                    <VisualState.Setters>
                                        <Setter Target="BackgroundBorder.Background"
                                                Value="{ThemeResource SelectControlBackgroundColor}" />
                                        <Setter Target="BackgroundBorder.BorderThickness"
                                                Value="0" />
                                        <Setter Target="HyphenGlyph.Opacity"
                                                Value="1" />
                                    </VisualState.Setters>
                                </VisualState>

                                <VisualState x:Name="IndeterminatePressed">
                                    <VisualState.Setters>
                                        <Setter Target="BackgroundBorder.Background"
                                                Value="{ThemeResource SelectControlBackgroundColor}" />
                                        <Setter Target="BackgroundBorder.BorderThickness"
                                                Value="0" />
                                        <Setter Target="HyphenGlyph.Opacity"
                                                Value="1" />
                                    </VisualState.Setters>
                                </VisualState>

                                <VisualState x:Name="IndeterminateDisabled">
                                    <VisualState.Setters>
                                        <Setter Target="BackgroundBorder.Opacity"
                                                Value="0.5" />
                                        <Setter Target="ContentPresenter.Opacity"
                                                Value="0.5" />
                                        <Setter Target="BackgroundBorder.Background"
                                                Value="{ThemeResource SelectControlBackgroundColor}" />
                                        <Setter Target="BackgroundBorder.BorderThickness"
                                                Value="0" />
                                        <Setter Target="HyphenGlyph.Opacity"
                                                Value="1" />
                                    </VisualState.Setters>
                                </VisualState>

                                <VisualStateGroup.Transitions>
                                    <VisualTransition From="UncheckedNormal"
                                                      To="UncheckedPressed">
                                        <Storyboard>
                                            <DoubleAnimation Storyboard.TargetName="PressRingTransform"
                                                             Storyboard.TargetProperty="ScaleX"
                                                             Duration="0:0:0.4"
                                                             EasingFunction="{StaticResource Material_EaseInOutFunction}"
                                                             From="0"
                                                             To="1" />

                                            <DoubleAnimation Storyboard.TargetName="PressRingTransform"
                                                             Storyboard.TargetProperty="ScaleY"
                                                             Duration="0:0:0.4"
                                                             EasingFunction="{StaticResource Material_EaseInOutFunction}"
                                                             From="0"
                                                             To="1" />

                                            <android:DoubleAnimation Storyboard.TargetName="PressRing"
                                                                     Storyboard.TargetProperty="Opacity"
                                                                     Duration="0:0:0.5"
                                                                     EasingFunction="{StaticResource Material_EaseInOutFunction}"
                                                                     From="1"
                                                                     To="0" />

                                            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Opacity)"
                                                                           Storyboard.TargetName="PressRing">
                                                <EasingDoubleKeyFrame KeyTime="0"
                                                                      Value="0.5" />
                                                <EasingDoubleKeyFrame KeyTime="0:0:0.2"
                                                                      Value="0.5" />
                                                <EasingDoubleKeyFrame KeyTime="0:0:0.4"
                                                                      Value="0" />
                                            </DoubleAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </VisualTransition>

                                    <VisualTransition From="UncheckedPointerOver"
                                                      To="UncheckedPressed">
                                        <Storyboard>
                                            <DoubleAnimation Storyboard.TargetName="PressRingTransform"
                                                             Storyboard.TargetProperty="ScaleX"
                                                             Duration="0:0:0.4"
                                                             EasingFunction="{StaticResource Material_EaseInOutFunction}"
                                                             From="0"
                                                             To="1" />

                                            <DoubleAnimation Storyboard.TargetName="PressRingTransform"
                                                             Storyboard.TargetProperty="ScaleY"
                                                             Duration="0:0:0.4"
                                                             EasingFunction="{StaticResource Material_EaseInOutFunction}"
                                                             From="0"
                                                             To="1" />

                                            <android:DoubleAnimation Storyboard.TargetName="PressRing"
                                                                     Storyboard.TargetProperty="Opacity"
                                                                     Duration="0:0:0.5"
                                                                     EasingFunction="{StaticResource Material_EaseInOutFunction}"
                                                                     From="1"
                                                                     To="0" />

                                            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Opacity)"
                                                                           Storyboard.TargetName="PressRing">
                                                <EasingDoubleKeyFrame KeyTime="0"
                                                                      Value="0.5" />
                                                <EasingDoubleKeyFrame KeyTime="0:0:0.2"
                                                                      Value="0.5" />
                                                <EasingDoubleKeyFrame KeyTime="0:0:0.4"
                                                                      Value="0" />
                                            </DoubleAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </VisualTransition>

                                    <VisualTransition From="CheckedNormal"
                                                      To="CheckedPressed">
                                        <Storyboard>
                                            <DoubleAnimation Storyboard.TargetName="PressRingTransform"
                                                             Storyboard.TargetProperty="ScaleX"
                                                             Duration="0:0:0.4"
                                                             EasingFunction="{StaticResource Material_EaseInOutFunction}"
                                                             From="0"
                                                             To="1" />

                                            <DoubleAnimation Storyboard.TargetName="PressRingTransform"
                                                             Storyboard.TargetProperty="ScaleY"
                                                             Duration="0:0:0.4"
                                                             EasingFunction="{StaticResource Material_EaseInOutFunction}"
                                                             From="0"
                                                             To="1" />

                                            <android:DoubleAnimation Storyboard.TargetName="PressRing"
                                                                     Storyboard.TargetProperty="Opacity"
                                                                     Duration="0:0:0.5"
                                                                     EasingFunction="{StaticResource Material_EaseInOutFunction}"
                                                                     From="1"
                                                                     To="0" />

                                            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Opacity)"
                                                                           Storyboard.TargetName="PressRing">
                                                <EasingDoubleKeyFrame KeyTime="0"
                                                                      Value="0.5" />
                                                <EasingDoubleKeyFrame KeyTime="0:0:0.2"
                                                                      Value="0.5" />
                                                <EasingDoubleKeyFrame KeyTime="0:0:0.4"
                                                                      Value="0" />
                                            </DoubleAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </VisualTransition>

                                    <VisualTransition From="CheckedPointerOver"
                                                      To="CheckedPressed">
                                        <Storyboard>
                                            <DoubleAnimation Storyboard.TargetName="PressRingTransform"
                                                             Storyboard.TargetProperty="ScaleX"
                                                             Duration="0:0:0.4"
                                                             EasingFunction="{StaticResource Material_EaseInOutFunction}"
                                                             From="0"
                                                             To="1" />

                                            <DoubleAnimation Storyboard.TargetName="PressRingTransform"
                                                             Storyboard.TargetProperty="ScaleY"
                                                             Duration="0:0:0.4"
                                                             EasingFunction="{StaticResource Material_EaseInOutFunction}"
                                                             From="0"
                                                             To="1" />

                                            <android:DoubleAnimation Storyboard.TargetName="PressRing"
                                                                     Storyboard.TargetProperty="Opacity"
                                                                     Duration="0:0:0.5"
                                                                     EasingFunction="{StaticResource Material_EaseInOutFunction}"
                                                                     From="1"
                                                                     To="0" />

                                            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Opacity)"
                                                                           Storyboard.TargetName="PressRing">
                                                <EasingDoubleKeyFrame KeyTime="0"
                                                                      Value="0.5" />
                                                <EasingDoubleKeyFrame KeyTime="0:0:0.2"
                                                                      Value="0.5" />
                                                <EasingDoubleKeyFrame KeyTime="0:0:0.4"
                                                                      Value="0" />
                                            </DoubleAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </VisualTransition>

                                    <VisualTransition From="IndeterminateNormal"
                                                      To="IndeterminatePressed">

                                        <Storyboard>
                                            <DoubleAnimation Storyboard.TargetName="PressRingTransform"
                                                             Storyboard.TargetProperty="ScaleX"
                                                             Duration="0:0:0.4"
                                                             EasingFunction="{StaticResource Material_EaseInOutFunction}"
                                                             From="0"
                                                             To="1" />

                                            <DoubleAnimation Storyboard.TargetName="PressRingTransform"
                                                             Storyboard.TargetProperty="ScaleY"
                                                             Duration="0:0:0.4"
                                                             EasingFunction="{StaticResource Material_EaseInOutFunction}"
                                                             From="0"
                                                             To="1" />

                                            <android:DoubleAnimation Storyboard.TargetName="PressRing"
                                                                     Storyboard.TargetProperty="Opacity"
                                                                     Duration="0:0:0.5"
                                                                     EasingFunction="{StaticResource Material_EaseInOutFunction}"
                                                                     From="1"
                                                                     To="0" />

                                            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Opacity)"
                                                                           Storyboard.TargetName="PressRing">
                                                <EasingDoubleKeyFrame KeyTime="0"
                                                                      Value="0.5" />
                                                <EasingDoubleKeyFrame KeyTime="0:0:0.2"
                                                                      Value="0.5" />
                                                <EasingDoubleKeyFrame KeyTime="0:0:0.4"
                                                                      Value="0" />
                                            </DoubleAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </VisualTransition>

                                    <VisualTransition From="IndeterminatePointerOver"
                                                      To="IndeterminatePressed">

                                        <Storyboard>
                                            <DoubleAnimation Storyboard.TargetName="PressRingTransform"
                                                             Storyboard.TargetProperty="ScaleX"
                                                             Duration="0:0:0.4"
                                                             EasingFunction="{StaticResource Material_EaseInOutFunction}"
                                                             From="0"
                                                             To="1" />

                                            <DoubleAnimation Storyboard.TargetName="PressRingTransform"
                                                             Storyboard.TargetProperty="ScaleY"
                                                             Duration="0:0:0.4"
                                                             EasingFunction="{StaticResource Material_EaseInOutFunction}"
                                                             From="0"
                                                             To="1" />

                                            <android:DoubleAnimation Storyboard.TargetName="PressRing"
                                                                     Storyboard.TargetProperty="Opacity"
                                                                     Duration="0:0:0.5"
                                                                     EasingFunction="{StaticResource Material_EaseInOutFunction}"
                                                                     From="1"
                                                                     To="0" />

                                            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Opacity)"
                                                                           Storyboard.TargetName="PressRing">
                                                <EasingDoubleKeyFrame KeyTime="0"
                                                                      Value="0.5" />
                                                <EasingDoubleKeyFrame KeyTime="0:0:0.2"
                                                                      Value="0.5" />
                                                <EasingDoubleKeyFrame KeyTime="0:0:0.4"
                                                                      Value="0" />
                                            </DoubleAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </VisualTransition>
                                </VisualStateGroup.Transitions>
                            </VisualStateGroup>

                            <VisualStateGroup x:Name="FocusStates">
                                <VisualState x:Name="Focused">
                                    <VisualState.Setters>
                                        <Setter Target="FocusRing.Opacity"
                                                Value="1" />
                                    </VisualState.Setters>
                                </VisualState>

                                <VisualState x:Name="PointerFocused">
                                    <VisualState.Setters>
                                        <Setter Target="FocusRing.Opacity"
                                                Value="1" />
                                    </VisualState.Setters>
                                </VisualState>

                                <VisualState x:Name="Unfocused" />
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>

                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="{StaticResource CheckAreaLength}" />
                            <ColumnDefinition Width="*" />
                        </Grid.ColumnDefinitions>

                        <Ellipse x:Name="FocusRing"
                                 HorizontalAlignment="Center"
                                 VerticalAlignment="Center"
                                 Stretch="Uniform"
                                 Width="{StaticResource FocusAreaSize}"
                                 Height="{StaticResource FocusAreaSize}"
                                 Fill="{ThemeResource SelectControlToggleHoverButtonColor}"
                                 IsHitTestVisible="False"
                                 StrokeThickness="0"
                                 Opacity="0" />

                        <Ellipse x:Name="PressRing"
                                 HorizontalAlignment="Center"
                                 VerticalAlignment="Center"
                                 Stretch="Uniform"
                                 Width="{StaticResource FocusAreaSize}"
                                 Height="{StaticResource FocusAreaSize}"
                                 Fill="{StaticResource MaterialOnSurfaceDisabledBrush}"
                                 IsHitTestVisible="False"
                                 Opacity="0">
                            <Ellipse.RenderTransform>
                                <CompositeTransform x:Name="PressRingTransform"
                                                    ScaleX="0"
                                                    ScaleY="0"
                                                    CenterX="20"
                                                    CenterY="20" />
                            </Ellipse.RenderTransform>
                        </Ellipse>

                        <Grid Height="{StaticResource CheckAreaSize}"
                              Width="{StaticResource CheckAreaSize}">
                            <Grid x:Name="BackgroundBorder"
                                  Background="{TemplateBinding Background}"
                                  BorderBrush="{TemplateBinding BorderBrush}"
                                  BorderThickness="{TemplateBinding BorderThickness}"
                                  CornerRadius="2" />

                            <Path x:Name="HyphenGlyph"
                                  Data="M0,0L32,0 32,5.3 0,5.3z"
                                  Fill="{ThemeResource SelectControlIndicatorColor}"
                                  VerticalAlignment="Center"
                                  HorizontalAlignment="Center"
                                  Stretch="Uniform"
                                  Width="12"
                                  Height="4"
                                  Opacity="0"
                                  AutomationProperties.AccessibilityView="Raw"
                                  xamarin:Margin="0,2,0,0" />

                            <Path x:Name="CheckGlyph"
                                  Data="M28.718018,0L32,3.2819897 10.666016,24.616999 0,13.951997 3.2810059,10.670007 10.666016,18.055033z"
                                  Fill="{ThemeResource SelectControlIndicatorColor}"
                                  VerticalAlignment="Center"
                                  HorizontalAlignment="Center"
                                  Stretch="Uniform"
                                  Width="12"
                                  Height="12"
                                  Opacity="0"
                                  AutomationProperties.AccessibilityView="Raw"
                                  xamarin:Margin="0,2,0,0" />
                        </Grid>

                        <ContentPresenter x:Name="ContentPresenter"
                                          ContentTemplate="{TemplateBinding ContentTemplate}"
                                          ContentTransitions="{TemplateBinding ContentTransitions}"
                                          Content="{TemplateBinding Content}"
                                          Margin="{TemplateBinding Padding}"
                                          HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                          VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                          Grid.Column="1"
                                          AutomationProperties.AccessibilityView="Raw"
                                          TextWrapping="Wrap" />
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

p

Environment

Nuget Package: Uno.UI

Package Version(s): 3.0.0 dev 692 Affected platform(s):

Visual Studio:

Relevant plugins:

Anything else we need to know?

dr1rrb commented 4 years ago

This is a known issue:

  1. When animating a Transform, you can animate only one property at a time (i.e. CompositeTransform.TranslateX or CompositeTransform.TranslateY),

https://github.com/unoplatform/uno/blob/master/doc/articles/features/working-with-animations.md

Here you are trying to animate ScaleX and SacleY at the same time.