Skip to content

[Feature] AnimatedCornerRadius #240

@AbdAlghaniAlbiek

Description

@AbdAlghaniAlbiek

Describe the problem this feature would solve

I have made a TemplatedControl that have 4 new properties (TopLeftCorner, TopRightCorner, BottomLeftCorner, BottomRightCorner) and each of them control in the radius of corner that associated with.
And the purpose of doing this that in WPF there type of animation called: "ThicknessAnimation" and this animation provide me the ability to animate the properties that are from thickness class like: (margin, padding, borderThickness ...) and because this animation isn't available in UWP the solutions simply was making a dependency property for each paramerter of the thickness and animate them all such as: (make four properties for the Margin => LeftMargin, TopMargin, RightMargin, BelowMawrgin, and animate all of them or some of them depending on your needs in one storyboard) and in my sample here I made animation for the corners of border

The generic xaml for this TemplatedControl :

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:CalculatorControlSample"
    xmlns:local2="using:CalculatorControlSample.Temp">

    <Style TargetType="local2:AnimatedCornerRadius">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="local2:AnimatedCornerRadius">
                    <Grid>
                        <Border
                        Width="{TemplateBinding Width}"
                        Height="{TemplateBinding Height}"
                        Opacity="{TemplateBinding Opacity}"
                        Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}"
                        CornerRadius="{TemplateBinding CornerRadius}"
                        HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
                        VerticalAlignment="{TemplateBinding VerticalAlignment}"/>

                        <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                          VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                          Margin="{TemplateBinding Padding}"
                                          Content="{TemplateBinding Content}"/>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

And .cs file

public sealed class AnimatedCornerRadius : Control
 {
        public AnimatedCornerRadius()
        {
            this.DefaultStyleKey = typeof(AnimatedCornerRadius);
        }

        public object Content
        {
            get { return (object)GetValue(ContentProperty); }
            set { SetValue(ContentProperty, value); }
        }
        public static readonly DependencyProperty ContentProperty =
            DependencyProperty.Register(nameof(Content), typeof(object),typeof(AnimatedCornerRadius), new PropertyMetadata(null));

        public int TopLeftCorner
        {
            get { return (int)GetValue(TopLeftCornerProperty); }
            set { SetValue(TopLeftCornerProperty, value); }
        }
        public static readonly DependencyProperty TopLeftCornerProperty =
            DependencyProperty.Register(nameof(TopLeftCorner), typeof(int), typeof(AnimatedCornerRadius),
                new PropertyMetadata(0, (s, e) =>
                {
                    ((AnimatedCornerRadius)s).CornerRadius = new CornerRadius(
                        double.Parse(e.NewValue.ToString()),
                        ((AnimatedCornerRadius)s).CornerRadius.TopRight,
                        ((AnimatedCornerRadius)s).CornerRadius.BottomRight,
                        ((AnimatedCornerRadius)s).CornerRadius.BottomLeft);
                }));

        public int TopRightCorner
        {
            get { return (int)GetValue(TopRightCornerProperty); }
            set { SetValue(TopRightCornerProperty, value); }
        }
        public static readonly DependencyProperty TopRightCornerProperty =
            DependencyProperty.Register(nameof(TopRightCorner), typeof(int), typeof(AnimatedCornerRadius),
                new PropertyMetadata(0, (s, e) =>
                {
                    ((AnimatedCornerRadius)s).CornerRadius = new CornerRadius(
                        ((AnimatedCornerRadius)s).CornerRadius.TopLeft,
                        double.Parse(e.NewValue.ToString()),
                        ((AnimatedCornerRadius)s).CornerRadius.BottomRight,
                        ((AnimatedCornerRadius)s).CornerRadius.BottomLeft);
                }));

        public int BottomRightCorner
        {
            get { return (int)GetValue(BottomRightCornerProperty); }
            set { SetValue(BottomRightCornerProperty, value); }
        }
        public static readonly DependencyProperty BottomRightCornerProperty =
            DependencyProperty.Register(nameof(BottomRightCorner), typeof(int), typeof(AnimatedCornerRadius),
                new PropertyMetadata(0, (s, e) =>
                {
                    ((AnimatedCornerRadius)s).CornerRadius = new CornerRadius(
                        ((AnimatedCornerRadius)s).CornerRadius.TopLeft,
                        ((AnimatedCornerRadius)s).CornerRadius.TopRight,
                        double.Parse(e.NewValue.ToString()),
                        ((AnimatedCornerRadius)s).CornerRadius.BottomLeft);
                }));

        public int BottomLeftCorner
        {
            get { return (int)GetValue(BottomLeftCornerProperty); }
            set { SetValue(BottomLeftCornerProperty, value); }
        }
        public static readonly DependencyProperty BottomLeftCornerProperty =
            DependencyProperty.Register(nameof(BottomLeftCorner), typeof(int), typeof(AnimatedCornerRadius),
                new PropertyMetadata(0, (s, e) =>
                {
                    ((AnimatedCornerRadius)s).CornerRadius = new CornerRadius(
                        ((AnimatedCornerRadius)s).CornerRadius.TopLeft,
                        ((AnimatedCornerRadius)s).CornerRadius.TopRight,
                        ((AnimatedCornerRadius)s).CornerRadius.BottomRight,
                        double.Parse(e.NewValue.ToString()));
                }));
    }

and I define this control in MainPage and put the storyboard inside the same control and I made this storyboard ""Begin"" in code behind:

<controls:AnimatedCornerRadius

            x:Name="animatedBorder"
            Width="300"
            Height="300"
            Background="White"
            BorderBrush="Red"
            BorderThickness="8"
            CornerRadius="0"
            Tapped="animatedBorder_Tapped">
            <controls:AnimatedCornerRadius.Resources>
                <Storyboard x:Key="animatingCorners" AutoReverse="True">
                    <DoubleAnimation
                        EnableDependentAnimation="True"
                        Storyboard.TargetName="animatedBorder"
                        Storyboard.TargetProperty="TopLeftCorner"
                        From="0"
                        To="60"
                        Duration="0:0:1" />
                    <DoubleAnimation
                        EnableDependentAnimation="True"
                        Storyboard.TargetName="animatedBorder"
                        Storyboard.TargetProperty="TopRightCorner"
                        From="0"
                        To="60"
                        Duration="0:0:1" />
                    <DoubleAnimation
                        EnableDependentAnimation="True"
                        Storyboard.TargetName="animatedBorder"
                        Storyboard.TargetProperty="BottomRightCorner"
                        From="0"
                        To="60"
                        Duration="0:0:1" />
                    <DoubleAnimation
                        EnableDependentAnimation="True"
                        Storyboard.TargetName="animatedBorder"
                        Storyboard.TargetProperty="BottomLeftCorner"
                        From="0"
                        To="60"
                        Duration="0:0:1" />
                </Storyboard>
            </controls:AnimatedCornerRadius.Resources>
        </controls:AnimatedCornerRadius>

But then I think to make this properties as Attached properties to be possible to any one to implement it directly in any dependency object but then I figured out that It is impossible to animate attached properties, so I need your help to choice what is the better choice to deal with (making entirely new control to animate the corners OR there is some way else in behaviors and AnimationBuilder that can do it ????)

NOTE:
As you see, you can use these properties (TopLeftCorner, TopRightCorner, BottomRightCorner, BottomLeftCorner) as attached properties and adding it to VisualExtensions class too

Describe the solution

Making Animating CornerRadius possible using custom control

Describe alternatives you've considered

It's a good idea to add this type of animation (CornerRadiusAnimation or ThicknessAnimation) to AnimationBuilder if this possibole

Additional context & Screenshots

recordedVideo2021-12-07-232948.mp4

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions