Skip to content

Commit

Permalink
Merge pull request #6082 from wieslawsoltes/feature/SetterAnimatorAtt…
Browse files Browse the repository at this point in the history
…achedPropertyHack

Allow setting custom Animator in property to Setter (attached property alternative)
  • Loading branch information
jmacato committed Jun 17, 2021
2 parents 7c37a18 + ab28847 commit 742538d
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 1 deletion.
3 changes: 3 additions & 0 deletions samples/RenderDemo/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@
<TabItem Header="Transitions">
<pages:TransitionsPage/>
</TabItem>
<TabItem Header="Custom Animator">
<pages:CustomAnimatorPage/>
</TabItem>
<TabItem Header="Clipping">
<pages:ClippingPage/>
</TabItem>
Expand Down
25 changes: 25 additions & 0 deletions samples/RenderDemo/Pages/CustomAnimatorPage.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<UserControl
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:pages="clr-namespace:RenderDemo.Pages"
x:Class="RenderDemo.Pages.CustomAnimatorPage"
MaxWidth="600">
<Grid>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock.Styles>
<Style Selector="TextBlock">
<Style.Animations>
<Animation Duration="0:0:1" IterationCount="Infinite">
<KeyFrame Cue="0%">
<Setter Property="Text" Value="" Animation.Animator="{x:Type pages:CustomStringAnimator}"/>
</KeyFrame>
<KeyFrame Cue="100%">
<Setter Property="Text" Value="0123456789" Animation.Animator="{x:Type pages:CustomStringAnimator}"/>
</KeyFrame>
</Animation>
</Style.Animations>
</Style>
</TextBlock.Styles>
</TextBlock>
</Grid>
</UserControl>
27 changes: 27 additions & 0 deletions samples/RenderDemo/Pages/CustomAnimatorPage.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using System.Reactive.Linq;
using Avalonia;
using Avalonia.Animation;
using Avalonia.Controls;
using Avalonia.Controls.Shapes;
using Avalonia.Data;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
using Avalonia.Media;
using RenderDemo.ViewModels;

namespace RenderDemo.Pages
{
public class CustomAnimatorPage : UserControl
{
public CustomAnimatorPage()
{
InitializeComponent();
}

private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
}
}
16 changes: 16 additions & 0 deletions samples/RenderDemo/Pages/CustomStringAnimator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using Avalonia.Animation.Animators;

namespace RenderDemo.Pages
{
public class CustomStringAnimator : Animator<string>
{
public override string Interpolate(double progress, string oldValue, string newValue)
{
if (newValue.Length == 0) return "";
var step = 1.0 / newValue.Length;
var length = (int)(progress / step);
var result = newValue.Substring(0, length + 1);
return result;
}
}
}
29 changes: 28 additions & 1 deletion src/Avalonia.Animation/Animation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,33 @@ public string RepeatCount
[Content]
public KeyFrames Children { get; } = new KeyFrames();

// Store values for the Animator attached properties for IAnimationSetter objects.
private static readonly Dictionary<IAnimationSetter, Type> s_animators = new Dictionary<IAnimationSetter, Type>();

/// <summary>
/// Gets the value of the Animator attached property for a setter.
/// </summary>
/// <param name="setter">The animation setter.</param>
/// <returns>The property animator type.</returns>
public static Type GetAnimator(IAnimationSetter setter)
{
if (s_animators.TryGetValue(setter, out var type))
{
return type;
}
return null;
}

/// <summary>
/// Sets the value of the Animator attached property for a setter.
/// </summary>
/// <param name="setter">The animation setter.</param>
/// <param name="value">The property animator value.</param>
public static void SetAnimator(IAnimationSetter setter, Type value)
{
s_animators[setter] = value;
}

private readonly static List<(Func<AvaloniaProperty, bool> Condition, Type Animator)> Animators = new List<(Func<AvaloniaProperty, bool>, Type)>
{
( prop => typeof(bool).IsAssignableFrom(prop.PropertyType), typeof(BoolAnimator) ),
Expand Down Expand Up @@ -248,7 +275,7 @@ private static Type GetAnimatorType(AvaloniaProperty property)
{
foreach (var setter in keyframe.Setters)
{
var handler = GetAnimatorType(setter.Property);
var handler = Animation.GetAnimator(setter) ?? GetAnimatorType(setter.Property);

if (handler == null)
{
Expand Down

0 comments on commit 742538d

Please sign in to comment.