0
votes

I created a, somewhat, reusable Opacity animation in code that exposes two dependency properties so the animation can be run without having to define animations for all the elements.

If anyone is wondering then yes, I also created these animations in UWP XAML with the help of behaviors but I am getting the same results. The problem is while in XAML I can't actually see the end result of Opacity values of the element but with code-behind I can insert breakpoints and see the values.

The class that I am using is:

public static class VisibilityAnimationHelper
    {
        private static Storyboard visibleSB = null;
        private static Storyboard collapseSB = null;
        private static DoubleAnimation collapsedAnim = null;
        private static DoubleAnimation visibleAnim = null;

        public static readonly DependencyProperty AnimationProperty = DependencyProperty.RegisterAttached("AnimationProperty", typeof(Visibility), typeof(VisibilityAnimationHelper), new PropertyMetadata(Visibility.Visible, AnimationChangedCallback));

        public static readonly DependencyProperty ParentProperty = DependencyProperty.RegisterAttached("Parent", typeof(FrameworkElement), typeof(VisibilityAnimationHelper), null);

        private static void AnimationChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (!(d is UIElement element)) return;


            collapsedAnim = new DoubleAnimation()
            {
                To = 0.01,
                FillBehavior = FillBehavior.Stop
            };
            collapsedAnim.Completed += delegate
            {
                element.Visibility = Visibility.Collapsed;
            };

            visibleAnim = new DoubleAnimation()
            {
                To = 1.01,
                FillBehavior = FillBehavior.Stop
            };
            visibleAnim.Completed += delegate
            {

            };

            visibleSB = new Storyboard()
            {
                AutoReverse = false,
                Duration = new Duration(TimeSpan.FromSeconds(0.2))
            };
            Storyboard.SetTarget(visibleAnim, element);
            Storyboard.SetTargetProperty(visibleAnim, "Opacity");
            collapseSB = new Storyboard()
            {
                AutoReverse = false,
                Duration = new Duration(TimeSpan.FromSeconds(0.2))
            };
            Storyboard.SetTarget(collapsedAnim, element);
            Storyboard.SetTargetProperty(collapsedAnim, "Opacity");

            if ((Visibility)e.NewValue == Visibility.Collapsed)
            {
                if (!collapseSB.Children.Contains(collapsedAnim))
                    collapseSB.Children.Add(collapsedAnim);
                collapseSB.Begin();
            }
            else
            {
                element.Visibility = Visibility.Visible;
                if (!visibleSB.Children.Contains(visibleAnim))
                    visibleSB.Children.Add(visibleAnim);
                visibleSB.Begin();
            }

        }

        public static void SetParent(DependencyObject element, FrameworkElement value)
        {
            element.SetValue(ParentProperty, value);
        }

        public static FrameworkElement GetParent(DependencyObject element)
        {
            return (FrameworkElement)element.GetValue(ParentProperty);
        }

        public static void SetAnimationProperty(DependencyObject element, Visibility value)
        {
            element.SetValue(AnimationProperty, value);
        }

        public static Visibility GetAnimationProperty(DependencyObject element)
        {
            return (Visibility)element.GetValue(AnimationProperty);
        }
    }

You can use this class to test how it's working. For me the end result looks like below:

Problem If you look at the above picture, in the first row, right most item is showing 2 hearts with opacity set to 1 (as a normal thing), middle item shows one heart as normal and other one a little fainted. The fainted one has just been animated, once hiden and then shown again. If I keep animating the hearts they keep fading away bit by bit.

I also inserted two breakpoints when the animations completed and the result of the opacity is wrong. I am not sure why the animation is not setting proper values. It can be a bug within the SDK maybe.

collapsed-animation-ended visible-animation-ended

In the above 2 pics you can see the end result of the Opacity of the element. When the collapsed animation completes the Opacity gets set to around 0.8 (when it should be 0) and then after the visible animation completes then the opacity is around 0.84 (when it should be 1). In the UI it animates correctly but the actual opacity of the eement gets se wrongly somehow.

Maybe I am running the animations wrongly? Please provide some suggestions here. Thanks

1

1 Answers

0
votes

Changing the Storyboards and Animations to following seems to be helping with setting the correct vaues.

collapsedAnim = new DoubleAnimation()
{
    To = 0,
    AutoReverse = false,
    Duration = new Duration(TimeSpan.FromSeconds(0.2))
};
visibleAnim = new DoubleAnimation()
{
    To = 1,
    AutoReverse = false,
    Duration = new Duration(TimeSpan.FromSeconds(0.2))
};
visibleSB = new Storyboard();
collapseSB = new Storyboard();