feat:Add several predefined SizeAnimations.

This commit is contained in:
望尘空忧
2025-08-18 23:11:02 +08:00
parent 2345c8a9de
commit c631c9a871
6 changed files with 201 additions and 67 deletions

View File

@@ -41,9 +41,7 @@
ItemsSource="{Binding MenuItems}" ItemsSource="{Binding MenuItems}"
SelectedItem="{Binding SelectedMenuItem}" SelectedItem="{Binding SelectedMenuItem}"
SubMenuBinding="{Binding Children}" SubMenuBinding="{Binding Children}"
u:SizeAnimationHelper.TriggerAvaloniaProperty="{x:Static u:NavMenu.IsHorizontalCollapsedProperty}" Classes="enable_animation">
u:SizeAnimationHelper.CreateAnimation="{x:Static views:NavMenuDemo.NavMenuAnimation}"
u:SizeAnimationHelper.EnableWHAnimation="True">
<u:NavMenu.Styles> <u:NavMenu.Styles>
<Style x:DataType="vm:MenuItem" Selector="u|NavMenuItem"> <Style x:DataType="vm:MenuItem" Selector="u|NavMenuItem">
<Setter Property="IsSeparator" Value="{Binding IsSeparator}" /> <Setter Property="IsSeparator" Value="{Binding IsSeparator}" />

View File

@@ -17,38 +17,4 @@ public partial class NavMenuDemo : UserControl
{ {
InitializeComponent(); InitializeComponent();
} }
public static SizeAnimationHelperAnimationGeneratorDelegate NavMenuAnimation { get; } =
(_, oldDesiredSize, newDesiredSize) =>
{
if (oldDesiredSize.Width > newDesiredSize.Width)
newDesiredSize = newDesiredSize.WithWidth(newDesiredSize.Width + 20);
return new Animation
{
Duration = TimeSpan.FromMilliseconds(300),
Easing = new CubicEaseInOut(),
FillMode = FillMode.None,
Children =
{
new KeyFrame
{
Cue = new Cue(0.0),
Setters =
{
new Setter(WidthProperty, oldDesiredSize.Width),
new Setter(HeightProperty, oldDesiredSize.Height)
}
},
new KeyFrame
{
Cue = new Cue(1.0),
Setters =
{
new Setter(WidthProperty, newDesiredSize.Width),
new Setter(HeightProperty, newDesiredSize.Height)
}
}
}
};
};
} }

View File

@@ -44,6 +44,15 @@
<Setter Property="Width" Value="{Binding $self.CollapseWidth}" /> <Setter Property="Width" Value="{Binding $self.CollapseWidth}" />
<Setter Property="Grid.IsSharedSizeScope" Value="False" /> <Setter Property="Grid.IsSharedSizeScope" Value="False" />
</Style> </Style>
<Style Selector="^.enable_animation">
<Setter Property="u:SizeAnimationHelper.TriggerAvaloniaProperty"
Value="{x:Static u:NavMenu.IsHorizontalCollapsedProperty}">
</Setter>
<Setter Property="u:SizeAnimationHelper.CreateAnimation"
Value="{DynamicResource NavMenuWidthAnimationGenerator}">
</Setter>
<Setter Property="u:SizeAnimationHelper.EnableWHAnimation" Value="True"></Setter>
</Style>
</ControlTheme> </ControlTheme>
<ControlTemplate x:Key="DefaultNavMenuItemTemplate" TargetType="u:NavMenuItem"> <ControlTemplate x:Key="DefaultNavMenuItemTemplate" TargetType="u:NavMenuItem">
@@ -134,13 +143,15 @@
<Transitions> <Transitions>
<DoubleTransition Easing="QuadraticEaseIn" Property="Height" Duration="0.25" /> <DoubleTransition Easing="QuadraticEaseIn" Property="Height" Duration="0.25" />
<DoubleTransition Easing="QuadraticEaseOut" Property="Opacity" Duration="0.25" /> <DoubleTransition Easing="QuadraticEaseOut" Property="Opacity" Duration="0.25" />
<TransformOperationsTransition Easing="QuadraticEaseInOut" Property="RenderTransform" Duration="0.25" /> <TransformOperationsTransition Easing="QuadraticEaseInOut" Property="RenderTransform"
Duration="0.25" />
</Transitions> </Transitions>
</ItemsPresenter.Transitions> </ItemsPresenter.Transitions>
</ItemsPresenter> </ItemsPresenter>
<LayoutTransformControl.Transitions> <LayoutTransformControl.Transitions>
<Transitions> <Transitions>
<TransformOperationsTransition Easing="QuadraticEaseInOut" Property="LayoutTransform" Duration="0.15" Delay="0.1" /> <TransformOperationsTransition Easing="QuadraticEaseInOut" Property="LayoutTransform"
Duration="0.15" Delay="0.1" />
</Transitions> </Transitions>
</LayoutTransformControl.Transitions> </LayoutTransformControl.Transitions>
</LayoutTransformControl> </LayoutTransformControl>

View File

@@ -26,6 +26,8 @@ public class SemiTheme : Styles
public SemiTheme(IServiceProvider? provider = null) public SemiTheme(IServiceProvider? provider = null)
{ {
AvaloniaXamlLoader.Load(provider, this); AvaloniaXamlLoader.Load(provider, this);
Resources.MergedDictionaries.Add(new SizeAnimations.DefaultSizeAnimations());
Resources.MergedDictionaries.Add(new SizeAnimations.NavMenuSizeAnimations());
} }
public static ThemeVariant Aquatic => new(nameof(Aquatic), ThemeVariant.Dark); public static ThemeVariant Aquatic => new(nameof(Aquatic), ThemeVariant.Dark);

View File

@@ -0,0 +1,105 @@
using Avalonia.Animation;
using Avalonia.Animation.Easings;
using Avalonia.Controls;
using Avalonia.Layout;
using Avalonia.Styling;
using Ursa.Helpers;
namespace Ursa.Themes.Semi.SizeAnimations;
public partial class DefaultSizeAnimations : ResourceDictionary
{
public const string WidthAnimationGeneratorKey = "WidthAnimationGenerator";
public const string HeightAnimationGeneratorKey = "HeightAnimationGenerator";
public const string WidthHeightAnimationGeneratorKey = "WidthHeightAnimationGenerator";
public DefaultSizeAnimations()
{
Add(WidthAnimationGeneratorKey, WidthAnimationGenerator);
Add(HeightAnimationGeneratorKey, HeightAnimationGenerator);
Add(WidthHeightAnimationGeneratorKey, WidthHeightAnimationGenerator);
}
private readonly SizeAnimationHelperAnimationGeneratorDelegate WidthAnimationGenerator =
(_, oldDesiredSize, newDesiredSize) => new Animation
{
Duration = TimeSpan.FromMilliseconds(300),
Easing = new CubicEaseInOut(),
FillMode = FillMode.None,
Children =
{
new KeyFrame
{
Cue = new Cue(0.0),
Setters =
{
new Setter(Layoutable.WidthProperty, oldDesiredSize.Width)
}
},
new KeyFrame
{
Cue = new Cue(1.0),
Setters =
{
new Setter(Layoutable.WidthProperty, newDesiredSize.Width)
}
}
}
};
private readonly SizeAnimationHelperAnimationGeneratorDelegate HeightAnimationGenerator =
(_, oldDesiredSize, newDesiredSize) => new Animation
{
Duration = TimeSpan.FromMilliseconds(300),
Easing = new CubicEaseInOut(),
FillMode = FillMode.None,
Children =
{
new KeyFrame
{
Cue = new Cue(0.0),
Setters =
{
new Setter(Layoutable.HeightProperty, oldDesiredSize.Height)
}
},
new KeyFrame
{
Cue = new Cue(1.0),
Setters =
{
new Setter(Layoutable.HeightProperty, newDesiredSize.Height)
}
}
}
};
private readonly SizeAnimationHelperAnimationGeneratorDelegate WidthHeightAnimationGenerator =
(_, oldDesiredSize, newDesiredSize) => new Animation
{
Duration = TimeSpan.FromMilliseconds(300),
Easing = new CubicEaseInOut(),
FillMode = FillMode.None,
Children =
{
new KeyFrame
{
Cue = new Cue(0.0),
Setters =
{
new Setter(Layoutable.WidthProperty, oldDesiredSize.Width),
new Setter(Layoutable.HeightProperty, oldDesiredSize.Height)
}
},
new KeyFrame
{
Cue = new Cue(1.0),
Setters =
{
new Setter(Layoutable.WidthProperty, newDesiredSize.Width),
new Setter(Layoutable.HeightProperty, newDesiredSize.Height)
}
}
}
};
}

View File

@@ -0,0 +1,52 @@
using Avalonia.Animation;
using Avalonia.Animation.Easings;
using Avalonia.Controls;
using Avalonia.Layout;
using Avalonia.Styling;
using Ursa.Helpers;
namespace Ursa.Themes.Semi.SizeAnimations;
public class NavMenuSizeAnimations : ResourceDictionary
{
public const string NavMenuWidthAnimationGeneratorKey = "NavMenuWidthAnimationGenerator";
public NavMenuSizeAnimations()
{
Add(NavMenuWidthAnimationGeneratorKey, NavMenuWidthAnimationGenerator);
}
private readonly SizeAnimationHelperAnimationGeneratorDelegate NavMenuWidthAnimationGenerator =
(_, oldDesiredSize, newDesiredSize) =>
{
if (oldDesiredSize.Width > newDesiredSize.Width)
newDesiredSize = newDesiredSize.WithWidth(newDesiredSize.Width + 20);
return new Animation
{
Duration = TimeSpan.FromMilliseconds(300),
Easing = new CubicEaseInOut(),
FillMode = FillMode.None,
Children =
{
new KeyFrame
{
Cue = new Cue(0.0),
Setters =
{
new Setter(Layoutable.WidthProperty, oldDesiredSize.Width),
new Setter(Layoutable.HeightProperty, oldDesiredSize.Height)
}
},
new KeyFrame
{
Cue = new Cue(1.0),
Setters =
{
new Setter(Layoutable.WidthProperty, newDesiredSize.Width),
new Setter(Layoutable.HeightProperty, newDesiredSize.Height)
}
}
}
};
};
}