adonis-ui icon indicating copy to clipboard operation
adonis-ui copied to clipboard

Configurable Animation Duration

Open alexhelms opened this issue 4 years ago • 3 comments

Is your feature request related to a problem? Please describe. I would like to increase the animation duration for expanders and other controls but because the duration is hardcoded in the control template I would have to reimplement the template in order to change it.

Describe the solution you'd like Similar to how radius and border thickness has a configurable variables, and additional one for animation duration seems that it would be a decent fit.

Describe alternatives you've considered Reimplementing control templates which is cumbersome and would require maintenance as this library is improved over time.

alexhelms avatar May 08 '20 01:05 alexhelms

You're right, that's something I considered would be nice to have as well. I already tried to make animations configurable in the past but unfortunately WPF is kind of limited here.

The problem is that animations do not support the use of Binding and DynamicResource for their properties. As far as I understood, the reason for this is that animations are freezable. This means that once an animation starts its properties get frozen (read-only) by WPF so that for example the duration cannot be changed while the animation is running. This gives WPF the ability to run animations in a parallel thread as well.

Bindings on the other hand have the purpose of updating their target when the source changes. So in Adonis UI I would like to do something like:

<DoubleAnimation Storyboard.TargetName="Container"
                 Storyboard.TargetProperty="(FrameworkElement.RenderTransform).(ScaleTransform.ScaleY)"
                 To="1"
                 Duration="{Binding CustomDuration}"/>

... but it throws an exception because in theory you could change the value of CustomDuration while the animation is running and the binding would try to update the value.

On a personal note, I don't really understand why there is no solution to this. In my limited mind I imagine the binding could update the value only until the animation starts and afterwards updates are rejected until the animation restarts. But I don't know the underlying architecture and cannot evaluate how hard it would be to implement this in WPF. And maybe I even misunderstood something here myself.

The only way I see to get this done would be to create the animations in code-behind. This is also how it is done for the ripple animation which is already configurable. Using C# code I could retrieve some configured duration value, create an animation programmatically and assign the value to its duration property without using bindings and dynamic resources. But this is not really straightforward either because styles normally don't have code-behind (the ripple animation is done by a custom control which is different from a default style). Maybe one could create something like a reusable animation dependency object for this, I don't know. I might check out other UI libraries and see whether they were able to solve this and how.

But until now, I have no idea how to realize this in a clean way.

benruehl avatar May 08 '20 15:05 benruehl

That is an excellent point and that seems like a strange limitation of WPF.

If the goal is to set animation duration only at compile time I may have a working solution. Please check out this commit on my fork (https://github.com/alexhelms/adonis-ui/commit/fb0e88b38c2b6359cadf2b7658500a061f645dcb). The animation duration can be overridden in App's Startup event which happens before resources are loaded.

I think compile-time configuration is a reasonable limitation. I don't see many people wanting to change animation times for core UI elements at runtime.

alexhelms avatar May 08 '20 16:05 alexhelms

Making it static is an option as well, good call. Disadvantages with this approach that come to my mind are the following:

  1. It steps a bit out of line because every other configuration can be done via xaml resources and properties
  2. It can only be configured globally and not individually per control

But hey, better than not configurable at all I guess :)

benruehl avatar May 08 '20 18:05 benruehl