Refactor Collapse Animation

This commit is contained in:
polarboy 2024-09-29 17:47:54 +08:00
parent 4a98f6d5be
commit b6fcc74be3
2 changed files with 34 additions and 47 deletions

View File

@ -1,16 +1,16 @@
using AtomUI.Controls.MotionScene; using AtomUI.Controls.Primitives;
using AtomUI.Controls.Utils; using AtomUI.Controls.Utils;
using AtomUI.MotionScene;
using AtomUI.Theme.Styling; using AtomUI.Theme.Styling;
using AtomUI.Utils; using AtomUI.Utils;
using Avalonia; using Avalonia;
using Avalonia.Animation;
using Avalonia.Animation.Easings;
using Avalonia.Automation.Peers; using Avalonia.Automation.Peers;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Controls.Metadata; using Avalonia.Controls.Metadata;
using Avalonia.Controls.Mixins; using Avalonia.Controls.Mixins;
using Avalonia.Controls.Primitives; using Avalonia.Controls.Primitives;
using Avalonia.Controls.Templates; using Avalonia.Controls.Templates;
using Avalonia.Layout;
namespace AtomUI.Controls; namespace AtomUI.Controls;
@ -183,7 +183,7 @@ public class CollapseItem : HeaderedContentControl, ISelectable
} }
private bool _enableAnimation = true; private bool _enableAnimation = true;
private AnimationTargetPanel? _animationTarget; private MotionActorControl? _motionActor;
private Border? _headerDecorator; private Border? _headerDecorator;
private IconButton? _expandButton; private IconButton? _expandButton;
@ -225,7 +225,7 @@ public class CollapseItem : HeaderedContentControl, ISelectable
protected override void OnApplyTemplate(TemplateAppliedEventArgs e) protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{ {
base.OnApplyTemplate(e); base.OnApplyTemplate(e);
_animationTarget = e.NameScope.Find<AnimationTargetPanel>(CollapseItemTheme.ContentAnimationTargetPart); _motionActor = e.NameScope.Find<MotionActorControl>(CollapseItemTheme.ContentMotionActorPart);
_headerDecorator = e.NameScope.Find<Border>(CollapseItemTheme.HeaderDecoratorPart); _headerDecorator = e.NameScope.Find<Border>(CollapseItemTheme.HeaderDecoratorPart);
_expandButton = e.NameScope.Find<IconButton>(CollapseItemTheme.ExpandButtonPart); _expandButton = e.NameScope.Find<IconButton>(CollapseItemTheme.ExpandButtonPart);
TokenResourceBinder.CreateTokenBinding(this, MotionDurationProperty, GlobalTokenResourceKey.MotionDurationSlow); TokenResourceBinder.CreateTokenBinding(this, MotionDurationProperty, GlobalTokenResourceKey.MotionDurationSlow);
@ -296,65 +296,51 @@ public class CollapseItem : HeaderedContentControl, ISelectable
private void ExpandItemContent() private void ExpandItemContent()
{ {
if (_animationTarget is null || InAnimating) if (_motionActor is null || InAnimating)
{ {
return; return;
} }
if (!_enableAnimation) if (!_enableAnimation)
{ {
_animationTarget.IsVisible = true; _motionActor.IsVisible = true;
return; return;
} }
_animationTarget.IsVisible = true;
LayoutHelper.MeasureChild(_animationTarget, new Size(Bounds.Width, double.PositiveInfinity), new Thickness());
InAnimating = true; InAnimating = true;
var director = Director.Instance; var slideDownInMotionConfig = MotionFactory.BuildSlideUpInMotion(MotionDuration, new CubicEaseOut(),
var motion = new ExpandMotion(); FillMode.Forward);
motion.ConfigureOpacity(MotionDuration); _motionActor.RenderTransformOrigin = slideDownInMotionConfig.RenderTransformOrigin;
motion.ConfigureHeight(MotionDuration); MotionInvoker.Invoke(_motionActor, slideDownInMotionConfig, () =>
var motionActor = new MotionActor(_animationTarget, motion);
motionActor.DispatchInSceneLayer = false;
_animationTarget.InAnimation = true;
motionActor.Completed += (sender, args) =>
{ {
_animationTarget.InAnimation = false; _motionActor.SetCurrentValue(IsVisibleProperty, true);
InAnimating = false; }, () =>
}; {
director?.Schedule(motionActor); InAnimating = false;
});
} }
private void CollapseItemContent() private void CollapseItemContent()
{ {
if (_animationTarget is null || InAnimating) if (_motionActor is null || InAnimating)
{ {
return; return;
} }
if (!_enableAnimation) if (!_enableAnimation)
{ {
_animationTarget.IsVisible = false; _motionActor.IsVisible = false;
return; return;
} }
InAnimating = true; InAnimating = true;
var slideDownOutMotionConfig = MotionFactory.BuildSlideUpOutMotion(MotionDuration, new CubicEaseIn(),
LayoutHelper.MeasureChild(_animationTarget, new Size(Bounds.Width, double.PositiveInfinity), new Thickness()); FillMode.Forward);
var director = Director.Instance; MotionInvoker.Invoke(_motionActor, slideDownOutMotionConfig, null, () =>
var motion = new CollapseMotion();
motion.ConfigureOpacity(MotionDuration);
motion.ConfigureHeight(MotionDuration);
var motionActor = new MotionActor(_animationTarget!, motion);
motionActor.DispatchInSceneLayer = false;
_animationTarget.InAnimation = true;
motionActor.Completed += (sender, args) =>
{ {
InAnimating = false; _motionActor.SetCurrentValue(IsVisibleProperty, false);
_animationTarget.InAnimation = false; InAnimating = false;
_animationTarget.IsVisible = false; });
};
director?.Schedule(motionActor);
} }
private void SetupIconButton() private void SetupIconButton()

View File

@ -1,4 +1,5 @@
using AtomUI.MotionScene; using AtomUI.Controls.Primitives;
using AtomUI.MotionScene;
using AtomUI.Theme; using AtomUI.Theme;
using AtomUI.Theme.Styling; using AtomUI.Theme.Styling;
using AtomUI.Theme.Utils; using AtomUI.Theme.Utils;
@ -26,7 +27,7 @@ internal class CollapseItemTheme : BaseControlTheme
public const string HeaderDecoratorPart = "PART_HeaderDecorator"; public const string HeaderDecoratorPart = "PART_HeaderDecorator";
public const string ContentPresenterPart = "PART_ContentPresenter"; public const string ContentPresenterPart = "PART_ContentPresenter";
public const string AddOnContentPresenterPart = "PART_AddOnContentPresenter"; public const string AddOnContentPresenterPart = "PART_AddOnContentPresenter";
public const string ContentAnimationTargetPart = "PART_ContentAnimationTarget"; public const string ContentMotionActorPart = "PART_ContentMotionActor";
public CollapseItemTheme() : base(typeof(CollapseItem)) public CollapseItemTheme() : base(typeof(CollapseItem))
{ {
@ -43,16 +44,16 @@ internal class CollapseItemTheme : BaseControlTheme
}; };
BuildHeader(mainLayout, scope); BuildHeader(mainLayout, scope);
var animationPanel = new AnimationTargetPanel var motionActor = new MotionActorControl()
{ {
Name = ContentAnimationTargetPart Name = ContentMotionActorPart
}; };
animationPanel.SetCurrentValue(Visual.IsVisibleProperty, false); motionActor.SetCurrentValue(Visual.IsVisibleProperty, false);
var contentPresenter = new ContentPresenter var contentPresenter = new ContentPresenter
{ {
Name = ContentPresenterPart Name = ContentPresenterPart
}; };
animationPanel.Children.Add(contentPresenter); motionActor.Child = contentPresenter;
TokenResourceBinder.CreateGlobalTokenBinding(contentPresenter, ContentPresenter.BorderBrushProperty, TokenResourceBinder.CreateGlobalTokenBinding(contentPresenter, ContentPresenter.BorderBrushProperty,
GlobalTokenResourceKey.ColorBorder); GlobalTokenResourceKey.ColorBorder);
CreateTemplateParentBinding(contentPresenter, ContentPresenter.ContentProperty, CreateTemplateParentBinding(contentPresenter, ContentPresenter.ContentProperty,
@ -61,8 +62,8 @@ internal class CollapseItemTheme : BaseControlTheme
ContentControl.ContentTemplateProperty); ContentControl.ContentTemplateProperty);
CreateTemplateParentBinding(contentPresenter, ContentPresenter.BorderThicknessProperty, CreateTemplateParentBinding(contentPresenter, ContentPresenter.BorderThicknessProperty,
CollapseItem.ContentBorderThicknessProperty); CollapseItem.ContentBorderThicknessProperty);
mainLayout.Children.Add(animationPanel); mainLayout.Children.Add(motionActor);
animationPanel.RegisterInNameScope(scope); motionActor.RegisterInNameScope(scope);
contentPresenter.RegisterInNameScope(scope); contentPresenter.RegisterInNameScope(scope);
return mainLayout; return mainLayout;
}); });