Files
WCS/Plugins/Wcs/Plugin.Cowain.Wcs/Controls/GridColumnAnimationBehavior.cs
2026-03-02 09:13:29 +08:00

111 lines
3.4 KiB
C#

using Avalonia.Animation.Easings;
using Avalonia.Animation;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Xaml.Interactivity;
using Irihi.Avalonia.Shared.Helpers;
using Avalonia.Controls.Presenters;
using Avalonia.Data;
using Avalonia.Media;
using Avalonia.Styling;
namespace Plugin.Cowain.Wcs.Controls;
public class GridColumnAnimationBehavior : Behavior<Grid>
{
private IDisposable? _columnSubscription;
public static readonly StyledProperty<int> GridColumnProperty =
AvaloniaProperty.Register<GridColumnAnimationBehavior, int>(
nameof(GridColumn),
defaultBindingMode: BindingMode.TwoWay);
public int GridColumn
{
get => GetValue(GridColumnProperty);
set => SetValue(GridColumnProperty, value);
}
protected override void OnAttached()
{
base.OnAttached();
if (AssociatedObject is not null)
{
// 开始监听布局更新或直接触发初始动画
AssociatedObject.AttachedToVisualTree += HandleAttached;
}
}
protected override void OnDetaching()
{
if (AssociatedObject is not null)
{
AssociatedObject.AttachedToVisualTree -= HandleAttached;
}
_columnSubscription?.Dispose();
base.OnDetaching();
}
private void HandleAttached(object? sender, VisualTreeAttachmentEventArgs e)
{
if (AssociatedObject is Grid grid && grid.Parent is ContentPresenter contentPresenter)
{
// 使用绑定监听Grid.Column变化
_columnSubscription = contentPresenter.GetObservable(Grid.ColumnProperty)
.Subscribe(column =>
{
if (column != GridColumn)
{
AnimateColumnChange(grid, column, GridColumn);
}
});
}
}
private void AnimateColumnChange(Grid grid, int fromColumn, int toColumn)
{
var contentPresenter = grid.Parent as ContentPresenter;
if (contentPresenter == null) return;
// 创建水平移动动画
var transform = new TranslateTransform();
contentPresenter.RenderTransform = transform;
var _animation = new Animation
{
Duration = TimeSpan.FromSeconds(0.3),
Easing = new CubicEaseInOut(),
Children =
{
new KeyFrame
{
Cue = new Cue(0d),
Setters =
{
new Setter
{
Property = TranslateTransform.XProperty,
Value = fromColumn * -grid.ColumnDefinitions[fromColumn].ActualWidth
}
}
},
new KeyFrame
{
Cue = new Cue(1d),
Setters =
{
new Setter
{
Property = TranslateTransform.XProperty,
Value = toColumn * -grid.ColumnDefinitions[toColumn].ActualWidth
}
}
}
}
};
_animation.RunAsync(contentPresenter);
}
}