Refactor CountBadge

Add IAnimationAwareControl Support
This commit is contained in:
chinboy
2025-02-11 19:40:18 +08:00
parent caafcbc8cb
commit f76a982bd5
2 changed files with 116 additions and 37 deletions
+47 -2
View File
@@ -1,7 +1,9 @@
using AtomUI.Data;
using AtomUI.Theme;
using AtomUI.Theme.Data;
using AtomUI.Theme.Palette;
using AtomUI.Theme.Styling;
using AtomUI.Theme.Utils;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Primitives;
@@ -16,7 +18,9 @@ public enum CountBadgeSize
Small
}
public class CountBadge : Control
public class CountBadge : Control,
IControlSharedTokenResourcesHost,
IAnimationAwareControl
{
#region 公共属性定义
@@ -47,6 +51,12 @@ public class CountBadge : Control
public static readonly StyledProperty<bool> BadgeIsVisibleProperty =
AvaloniaProperty.Register<CountBadge, bool>(nameof(BadgeIsVisible), true);
public static readonly StyledProperty<bool> IsMotionEnabledProperty
= AvaloniaProperty.Register<CountBadge, bool>(nameof(IsMotionEnabled), true);
public static readonly StyledProperty<bool> IsWaveAnimationEnabledProperty
= AvaloniaProperty.Register<CountBadge, bool>(nameof(IsWaveAnimationEnabled), true);
public string? BadgeColor
{
get => GetValue(BadgeColorProperty);
@@ -96,6 +106,18 @@ public class CountBadge : Control
set => SetValue(BadgeIsVisibleProperty, value);
}
public bool IsMotionEnabled
{
get => GetValue(IsMotionEnabledProperty);
set => SetValue(IsMotionEnabledProperty, value);
}
public bool IsWaveAnimationEnabled
{
get => GetValue(IsWaveAnimationEnabledProperty);
set => SetValue(IsWaveAnimationEnabledProperty, value);
}
#endregion
#region 内部属性定义
@@ -109,6 +131,10 @@ public class CountBadge : Control
get => GetValue(MotionDurationProperty);
set => SetValue(MotionDurationProperty, value);
}
Control IControlSharedTokenResourcesHost.HostControl => this;
string IControlSharedTokenResourcesHost.TokenId => BadgeToken.ID;
Control IAnimationAwareControl.PropertyBindTarget => this;
#endregion
@@ -124,6 +150,12 @@ public class CountBadge : Control
SizeProperty);
AffectsRender<CountBadge>(BadgeColorProperty, OffsetProperty);
}
public CountBadge()
{
this.RegisterResources();
this.BindAnimationProperties(IsMotionEnabledProperty, IsWaveAnimationEnabledProperty);
}
public sealed override void ApplyTemplate()
{
@@ -172,6 +204,10 @@ public class CountBadge : Control
}
else
{
if (DecoratedTarget is null)
{
IsVisible = true;
}
badgeAdorner.ApplyToTarget(null, this);
}
}
@@ -184,6 +220,13 @@ public class CountBadge : Control
return;
}
_badgeAdorner.DetachFromTarget(_adornerLayer, enableMotion);
if (!enableMotion)
{
if (DecoratedTarget is null)
{
IsVisible = false;
}
}
}
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
@@ -209,6 +252,8 @@ public class CountBadge : Control
BindUtils.RelayBind(this, SizeProperty, _badgeAdorner, CountBadgeAdorner.SizeProperty);
BindUtils.RelayBind(this, OverflowCountProperty, _badgeAdorner, CountBadgeAdorner.OverflowCountProperty);
BindUtils.RelayBind(this, CountProperty, _badgeAdorner, CountBadgeAdorner.CountProperty);
BindUtils.RelayBind(this, IsMotionEnabledProperty, _badgeAdorner, CountBadgeAdorner.IsMotionEnabledProperty);
BindUtils.RelayBind(this, IsWaveAnimationEnabledProperty, _badgeAdorner, CountBadgeAdorner.IsWaveAnimationEnabledProperty);
}
TokenResourceBinder.CreateTokenBinding(this, MotionDurationProperty, SharedTokenKey.MotionDurationSlow);
@@ -245,7 +290,7 @@ public class CountBadge : Control
}
else
{
HideAdorner(true);
HideAdorner(IsMotionEnabled);
}
}
+69 -35
View File
@@ -5,6 +5,7 @@ using AtomUI.Theme.Styling;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Primitives;
using Avalonia.LogicalTree;
using Avalonia.Media;
namespace AtomUI.Controls;
@@ -27,18 +28,6 @@ internal class CountBadgeAdorner : TemplatedControl
public static readonly StyledProperty<CountBadgeSize> SizeProperty =
AvaloniaProperty.Register<CountBadgeAdorner, CountBadgeSize>(
nameof(Size));
internal static readonly StyledProperty<int> CountProperty =
AvaloniaProperty.Register<CountBadgeAdorner, int>(
nameof(Count));
internal static readonly StyledProperty<IBrush?> BadgeShadowColorProperty =
AvaloniaProperty.Register<CountBadgeAdorner, IBrush?>(
nameof(BadgeShadowColor));
internal static readonly StyledProperty<double> BadgeShadowSizeProperty =
AvaloniaProperty.Register<CountBadgeAdorner, double>(
nameof(BadgeShadowSize));
public IBrush? BadgeColor
{
@@ -70,18 +59,6 @@ internal class CountBadgeAdorner : TemplatedControl
set => SetValue(CountProperty, value);
}
public IBrush? BadgeShadowColor
{
get => GetValue(BadgeShadowColorProperty);
set => SetValue(BadgeShadowColorProperty, value);
}
public double BadgeShadowSize
{
get => GetValue(BadgeShadowSizeProperty);
set => SetValue(BadgeShadowSizeProperty, value);
}
#endregion
#region 内部属性定义
@@ -110,6 +87,24 @@ internal class CountBadgeAdorner : TemplatedControl
o => o.MotionDuration,
(o, v) => o.MotionDuration = v);
internal static readonly StyledProperty<int> CountProperty =
AvaloniaProperty.Register<CountBadgeAdorner, int>(
nameof(Count));
internal static readonly StyledProperty<IBrush?> BadgeShadowColorProperty =
AvaloniaProperty.Register<CountBadgeAdorner, IBrush?>(
nameof(BadgeShadowColor));
internal static readonly StyledProperty<double> BadgeShadowSizeProperty =
AvaloniaProperty.Register<CountBadgeAdorner, double>(
nameof(BadgeShadowSize));
internal static readonly StyledProperty<bool> IsMotionEnabledProperty
= AvaloniaProperty.Register<CountBadgeAdorner, bool>(nameof(IsMotionEnabled), true);
internal static readonly StyledProperty<bool> IsWaveAnimationEnabledProperty
= AvaloniaProperty.Register<CountBadgeAdorner, bool>(nameof(IsWaveAnimationEnabled), true);
private bool _isAdornerMode;
internal bool IsAdornerMode
@@ -119,25 +114,49 @@ internal class CountBadgeAdorner : TemplatedControl
}
private BoxShadows _boxShadow;
public BoxShadows BoxShadow
internal BoxShadows BoxShadow
{
get => _boxShadow;
set => SetAndRaise(BoxShadowProperty, ref _boxShadow, value);
}
private string? _countText;
public string? CountText
internal string? CountText
{
get => _countText;
set => SetAndRaise(CountTextProperty, ref _countText, value);
}
private TimeSpan _motionDuration;
public TimeSpan MotionDuration
internal TimeSpan MotionDuration
{
get => _motionDuration;
set => SetAndRaise(MotionDurationProperty, ref _motionDuration, value);
}
internal IBrush? BadgeShadowColor
{
get => GetValue(BadgeShadowColorProperty);
set => SetValue(BadgeShadowColorProperty, value);
}
internal double BadgeShadowSize
{
get => GetValue(BadgeShadowSizeProperty);
set => SetValue(BadgeShadowSizeProperty, value);
}
internal bool IsMotionEnabled
{
get => GetValue(IsMotionEnabledProperty);
set => SetValue(IsMotionEnabledProperty, value);
}
internal bool IsWaveAnimationEnabled
{
get => GetValue(IsWaveAnimationEnabledProperty);
set => SetValue(IsWaveAnimationEnabledProperty, value);
}
#endregion
@@ -157,16 +176,21 @@ internal class CountBadgeAdorner : TemplatedControl
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{
base.OnApplyTemplate(e);
TokenResourceBinder.CreateTokenBinding(this, BadgeShadowSizeProperty, BadgeTokenKey.BadgeShadowSize);
TokenResourceBinder.CreateTokenBinding(this, BadgeShadowColorProperty, BadgeTokenKey.BadgeShadowColor);
TokenResourceBinder.CreateTokenBinding(this, MotionDurationProperty, SharedTokenKey.MotionDurationMid);
TokenResourceBinder.CreateTokenBinding(this, BadgeColorProperty, BadgeTokenKey.BadgeColor);
_indicatorMotionActor = e.NameScope.Get<MotionActorControl>(CountBadgeAdornerTheme.IndicatorMotionActorPart);
if (_needInitialHide)
{
_indicatorMotionActor.IsVisible = false;
_needInitialHide = false;
}
}
protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e)
{
base.OnAttachedToLogicalTree(e);
TokenResourceBinder.CreateTokenBinding(this, BadgeShadowSizeProperty, BadgeTokenKey.BadgeShadowSize);
TokenResourceBinder.CreateTokenBinding(this, BadgeShadowColorProperty, BadgeTokenKey.BadgeShadowColor);
TokenResourceBinder.CreateTokenBinding(this, MotionDurationProperty, SharedTokenKey.MotionDurationMid);
TokenResourceBinder.CreateTokenBinding(this, BadgeColorProperty, BadgeTokenKey.BadgeColor);
BuildBoxShadow();
BuildCountText();
}
@@ -267,10 +291,20 @@ internal class CountBadgeAdorner : TemplatedControl
adornerLayer.Children.Add(this);
}
_motionCancellationTokenSource?.Cancel();
_motionCancellationTokenSource = new CancellationTokenSource();
ApplyShowMotion();
if (IsMotionEnabled)
{
_motionCancellationTokenSource?.Cancel();
_motionCancellationTokenSource = new CancellationTokenSource();
ApplyShowMotion();
}
else
{
if (_indicatorMotionActor is not null)
{
_indicatorMotionActor.IsVisible = true;
}
}
}
internal void DetachFromTarget(AdornerLayer? adornerLayer, bool enableMotion = true)