From 48953ea9211ffc132699ec0c61ba7710f147af61 Mon Sep 17 00:00:00 2001 From: qinware Date: Fri, 22 Aug 2025 18:37:33 +0800 Subject: [PATCH] Refactor SwitchKnob --- src/AtomUI.Controls/Switch/SwitchKnob.cs | 98 ++++++++++++------- .../Switch/Themes/SwitchKnobTheme.axaml | 10 -- .../Switch/Themes/ToggleSwitchThemes.axaml | 1 - 3 files changed, 62 insertions(+), 47 deletions(-) delete mode 100644 src/AtomUI.Controls/Switch/Themes/SwitchKnobTheme.axaml diff --git a/src/AtomUI.Controls/Switch/SwitchKnob.cs b/src/AtomUI.Controls/Switch/SwitchKnob.cs index 370955375..d9ae03ec2 100644 --- a/src/AtomUI.Controls/Switch/SwitchKnob.cs +++ b/src/AtomUI.Controls/Switch/SwitchKnob.cs @@ -1,19 +1,24 @@ +using System.Reactive.Disposables; +using AtomUI.Animations; using AtomUI.Controls.Utils; using AtomUI.Data; using AtomUI.Media; +using AtomUI.Theme; +using AtomUI.Theme.Data; +using AtomUI.Theme.Styling; using AtomUI.Utils; using Avalonia; using Avalonia.Animation; using Avalonia.Animation.Easings; using Avalonia.Controls; -using Avalonia.Controls.Primitives; +using Avalonia.LogicalTree; using Avalonia.Media; using Avalonia.Styling; using Avalonia.VisualTree; namespace AtomUI.Controls; -internal class SwitchKnob : TemplatedControl +internal class SwitchKnob : Control, IResourceBindingManager { #region 公共属性定义 @@ -23,8 +28,8 @@ internal class SwitchKnob : TemplatedControl public static readonly StyledProperty KnobBackgroundColorProperty = AvaloniaProperty.Register(nameof(KnobBackgroundColor)); - public static readonly StyledProperty KnobBoxShadowProperty = - AvaloniaProperty.Register(nameof(KnobBoxShadow)); + public static readonly StyledProperty KnobBoxShadowProperty = + AvaloniaProperty.Register(nameof(KnobBoxShadow)); public IBrush? KnobBackgroundColor { @@ -38,7 +43,7 @@ internal class SwitchKnob : TemplatedControl set => SetValue(IsCheckedStateProperty, value); } - public BoxShadow KnobBoxShadow + public BoxShadow? KnobBoxShadow { get => GetValue(KnobBoxShadowProperty); set => SetValue(KnobBoxShadowProperty, value); @@ -65,9 +70,11 @@ internal class SwitchKnob : TemplatedControl internal static readonly StyledProperty LoadingAnimationDurationProperty = AvaloniaProperty.Register(nameof(LoadingAnimationDuration)); - - internal static readonly StyledProperty LoadingBgOpacityProperty = - AvaloniaProperty.Register(nameof(LoadingBgOpacity)); + + internal static readonly DirectProperty LoadingBgOpacityProperty = + AvaloniaProperty.RegisterDirect(nameof(LoadingBgOpacity), + o => o.LoadingBgOpacity, + (o, v) => o.LoadingBgOpacity = v); internal int Rotation { @@ -105,21 +112,29 @@ internal class SwitchKnob : TemplatedControl set => SetValue(LoadingAnimationDurationProperty, value); } + private double _loadingBgOpacity; internal double LoadingBgOpacity { - get => GetValue(LoadingBgOpacityProperty); - set => SetValue(LoadingBgOpacityProperty, value); + get => _loadingBgOpacity; + set => SetAndRaise(LoadingBgOpacityProperty, ref _loadingBgOpacity, value); + } + + CompositeDisposable? IResourceBindingManager.ResourceBindingsDisposable + { + get => _resourceBindingsDisposable; + set => _resourceBindingsDisposable = value; } #endregion + private CompositeDisposable? _resourceBindingsDisposable; private bool _isLoading; private CancellationTokenSource? _cancellationTokenSource; static SwitchKnob() { AffectsRender( - RotationProperty, KnobRenderWidthProperty, LoadIndicatorBrushProperty, KnobBoxShadowProperty); + RotationProperty, KnobRenderWidthProperty, LoadIndicatorBrushProperty); AffectsMeasure(KnobSizeProperty); } @@ -196,12 +211,6 @@ internal class SwitchKnob : TemplatedControl return KnobSize; } - protected override void OnSizeChanged(SizeChangedEventArgs e) - { - base.OnSizeChanged(e); - ConfigureTransitions(false); - } - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { base.OnPropertyChanged(change); @@ -211,31 +220,52 @@ internal class SwitchKnob : TemplatedControl } else if (change.Property == KnobBoxShadowProperty) { - Effect = new DropShadowEffect + if (KnobBoxShadow != null) { - OffsetX = KnobBoxShadow.OffsetX, - OffsetY = KnobBoxShadow.OffsetY, - Color = KnobBoxShadow.Color, - BlurRadius = KnobBoxShadow.Blur - }; + Effect = new DropShadowEffect + { + OffsetX = KnobBoxShadow.Value.OffsetX, + OffsetY = KnobBoxShadow.Value.OffsetY, + Color = KnobBoxShadow.Value.Color, + BlurRadius = KnobBoxShadow.Value.Blur + }; + } } - + if (this.IsAttachedToVisualTree()) { if (change.Property == IsMotionEnabledProperty) { - ConfigureTransitions(true); + ConfigureTransitions(); } } } + protected override void OnSizeChanged(SizeChangedEventArgs e) + { + base.OnSizeChanged(e); + this.EnableTransitions(); + } + + protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e) + { + base.OnAttachedToLogicalTree(e); + this.AddResourceBindingDisposable(TokenResourceBinder.CreateTokenBinding(this, LoadingBgOpacityProperty, + ToggleSwitchTokenKey.SwitchDisabledOpacity)); + this.AddResourceBindingDisposable(TokenResourceBinder.CreateTokenBinding(this, LoadingAnimationDurationProperty, + ToggleSwitchTokenKey.LoadingAnimationDuration)); + } + protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e) { base.OnAttachedToVisualTree(e); + _resourceBindingsDisposable = new CompositeDisposable(); if (_isLoading) { StartLoadingAnimation(); } + ConfigureTransitions(); + this.DisableTransitions(); } protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e) @@ -245,8 +275,7 @@ internal class SwitchKnob : TemplatedControl { _cancellationTokenSource?.Cancel(); } - - Transitions = null; + this.DisposeTokenBindings(); } public sealed override void Render(DrawingContext context) @@ -279,24 +308,21 @@ internal class SwitchKnob : TemplatedControl var rotationMatrix = Matrix.CreateRotation(Rotation * Math.PI / 180); using var translateToCenterState = context.PushTransform(translateToCenterMatrix); using var rotationMatrixState = context.PushTransform(rotationMatrix); - using var bgOpacity = context.PushOpacity(LoadingBgOpacity); + using var bgOpacity = context.PushOpacity(_loadingBgOpacity); context.DrawArc(pen, loadingRect, 0, 90); } } - private void ConfigureTransitions(bool force) + private void ConfigureTransitions() { if (IsMotionEnabled) { - if (force || Transitions == null) + Transitions ??= new Transitions { - Transitions = new Transitions - { - TransitionUtils.CreateTransition(KnobRenderWidthProperty), - TransitionUtils.CreateTransition(OpacityProperty), - }; - } + TransitionUtils.CreateTransition(KnobRenderWidthProperty), + TransitionUtils.CreateTransition(OpacityProperty), + }; } else { diff --git a/src/AtomUI.Controls/Switch/Themes/SwitchKnobTheme.axaml b/src/AtomUI.Controls/Switch/Themes/SwitchKnobTheme.axaml deleted file mode 100644 index 5b245c95c..000000000 --- a/src/AtomUI.Controls/Switch/Themes/SwitchKnobTheme.axaml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/src/AtomUI.Controls/Switch/Themes/ToggleSwitchThemes.axaml b/src/AtomUI.Controls/Switch/Themes/ToggleSwitchThemes.axaml index b55088e4b..d386665c6 100644 --- a/src/AtomUI.Controls/Switch/Themes/ToggleSwitchThemes.axaml +++ b/src/AtomUI.Controls/Switch/Themes/ToggleSwitchThemes.axaml @@ -2,7 +2,6 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:ClassModifier="internal"> - \ No newline at end of file