Add ColorSliderThumb

This commit is contained in:
qinware
2025-08-28 16:19:48 +08:00
parent 4ebe47877f
commit a82eee5346
6 changed files with 119 additions and 29 deletions
@@ -11,6 +11,7 @@ using Avalonia.Controls;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Primitives.PopupPositioning;
using Avalonia.Data;
using Avalonia.Interactivity;
using Avalonia.LogicalTree;
using Avalonia.Media;
@@ -178,12 +179,15 @@ public abstract class AbstractColorPicker : AvaloniaButton,
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
if (change.Property == IsMotionEnabledProperty)
if (IsLoaded)
{
ConfigureTransitions();
if (change.Property == IsMotionEnabledProperty)
{
ConfigureTransitions(true);
}
}
else if (change.Property == IsShowTextProperty ||
change.Property == FormatProperty)
if (change.Property == IsShowTextProperty || change.Property == FormatProperty)
{
GenerateValueText();
}
@@ -192,25 +196,33 @@ public abstract class AbstractColorPicker : AvaloniaButton,
protected abstract void GenerateValueText();
protected abstract void GenerateColorBlockBackground();
private void ConfigureTransitions()
private void ConfigureTransitions(bool force)
{
if (IsMotionEnabled)
{
Transitions = new Transitions()
if (force || Transitions == null)
{
TransitionUtils.CreateTransition<SolidColorBrushTransition>(BorderBrushProperty)
};
Transitions =
[
TransitionUtils.CreateTransition<SolidColorBrushTransition>(BorderBrushProperty)
];
}
}
else
{
Transitions?.Clear();
Transitions = null;
}
}
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
protected override void OnLoaded(RoutedEventArgs e)
{
base.OnApplyTemplate(e);
ConfigureTransitions();
base.OnLoaded(e);
ConfigureTransitions(false);
}
protected override void OnUnloaded(RoutedEventArgs e)
{
base.OnUnloaded(e);
Transitions = null;
}
}
@@ -66,6 +66,16 @@ public class ColorPickerToken : AbstractControlDesignToken
/// </summary>
public double ColorPickerSliderTrackSize { get; set; }
/// <summary>
/// ColorPicker 轨道 handle 的大小
/// </summary>
public double ColorPickerSliderThumbSize { get; set; }
/// <summary>
/// ColorPicker 轨道 handle 的阴影
/// </summary>
public BoxShadows ColorPickerSliderThumbShadow { get; set; }
/// <summary>
/// ColorPicker 预览尺寸
/// Preview size of ColorPicker
@@ -127,6 +137,7 @@ public class ColorPickerToken : AbstractControlDesignToken
ColorPickerPresetColorSize = 24;
ColorPickerSliderSize = ColorPickerHandlerSizeSM;
ColorPickerSliderTrackSize = 8;
ColorPickerSliderThumbSize = ColorPickerHandlerSizeSM + SharedToken.LineWidth * 2;
ColorPickerPreviewSize = ColorPickerSliderSize * 2 + SharedToken.UniformlyMarginSM;
ColorPickerInsetShadow = new BoxShadows(new BoxShadow()
{
@@ -137,6 +148,25 @@ public class ColorPickerToken : AbstractControlDesignToken
Spread = 0,
Color = SharedToken.ColorTextQuaternary
});
ColorPickerSliderThumbShadow = new BoxShadows(new BoxShadow()
{
IsInset = true,
OffsetX = 0,
OffsetY = 0,
Blur = 1,
Spread = 0,
Color = SharedToken.ColorTextQuaternary
}, [
new BoxShadow
{
OffsetX = 0,
OffsetY = 0,
Blur = 0,
Spread = 1,
Color = SharedToken.ColorFillSecondary
}
]);
ColorBlockInnerShadows = new BoxShadows(new BoxShadow()
{
IsInset = true,
@@ -1,9 +1,43 @@
using System.Diagnostics;
using System.Reactive.Disposables;
using AtomUI.Controls.Primitives;
using AtomUI.Theme;
using AtomUI.Theme.Data;
using AtomUI.Theme.Styling;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Data;
using Avalonia.LogicalTree;
using Avalonia.Utilities;
namespace AtomUI.Controls;
internal class ColorSliderThumb : Thumb
internal class ColorSliderThumb : Thumb, IResourceBindingManager
{
#region 内部属性定义
CompositeDisposable? IResourceBindingManager.ResourceBindingsDisposable { get; set; }
#endregion
protected override void OnSizeChanged(SizeChangedEventArgs e)
{
base.OnSizeChanged(e);
Debug.Assert(MathUtilities.AreClose(e.NewSize.Width, e.NewSize.Height));
CornerRadius = new CornerRadius(e.NewSize.Width / 2);
}
protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e)
{
base.OnAttachedToLogicalTree(e);
this.AddResourceBindingDisposable(TokenResourceBinder.CreateTokenBinding(this, BorderThicknessProperty,
SharedTokenKey.BorderThickness,
BindingPriority.Template,
new RenderScaleAwareThicknessConfigure(this)));
}
protected override void OnDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e)
{
base.OnDetachedFromLogicalTree(e);
this.DisposeTokenBindings();
}
}
@@ -6,6 +6,4 @@ public class ColorPickerView : AbstractColorPickerView
{
#region 公共属性定义
#endregion
}
@@ -5,26 +5,40 @@
x:ClassModifier="internal">
<ControlTheme x:Key="{x:Type atom:ColorSliderThumb}" TargetType="atom:ColorSliderThumb">
<Setter Property="Background" Value="Transparent" />
<Setter Property="UseLayoutRounding" Value="False" />
<Setter Property="BorderBrush" Value="Red" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="CornerRadius" Value="8" />
<Setter Property="Width" Value="12" />
<Setter Property="Height" Value="12" />
<Setter Property="Template">
<ControlTemplate>
<Border Name="{x:Static atom:ColorSliderThumbThemeConstants.FramePart}"
Background="{TemplateBinding Background}">
<Ellipse x:Name="SelectionEllipse"
<Border Name="{x:Static atom:ColorSliderThumbThemeConstants.FramePart}"
Background="Transparent"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding CornerRadius}"
ClipToBounds="False">
<Ellipse Name="SelectionEllipse"
StrokeThickness="2"
Stroke="{TemplateBinding BorderBrush}"
IsHitTestVisible="False"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" />
</Border>
</ControlTemplate>
</Setter>
<Setter Property="ClipToBounds" Value="False" />
<Setter Property="Cursor" Value="Hand" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="UseLayoutRounding" Value="False" />
<Setter Property="Focusable" Value="True" />
<Setter Property="BorderBrush" Value="{DynamicResource {x:Static atom:SharedTokenKey.ColorFillSecondary}}" />
<Setter Property="Width" Value="{DynamicResource {x:Static atom:ColorPickerTokenKey.ColorPickerSliderThumbSize}}" />
<Setter Property="Height"
Value="{DynamicResource {x:Static atom:ColorPickerTokenKey.ColorPickerSliderThumbSize}}" />
<Style Selector="^ /template/ Ellipse#SelectionEllipse">
<Setter Property="Stroke" Value="{DynamicResource {x:Static atom:SharedTokenKey.ColorBgElevated}}" />
</Style>
<Style Selector="^:focus">
<Setter Property="BorderBrush" Value="{DynamicResource {x:Static atom:SharedTokenKey.ColorPrimaryActive}}" />
</Style>
</ControlTheme>
</ResourceDictionary>
@@ -248,6 +248,8 @@ namespace AtomUI.Theme.Styling
public static readonly TokenResourceKey ColorPickerPresetColorSize = new TokenResourceKey("ColorPicker.ColorPickerPresetColorSize");
public static readonly TokenResourceKey ColorPickerPreviewSize = new TokenResourceKey("ColorPicker.ColorPickerPreviewSize");
public static readonly TokenResourceKey ColorPickerSliderSize = new TokenResourceKey("ColorPicker.ColorPickerSliderSize");
public static readonly TokenResourceKey ColorPickerSliderThumbShadow = new TokenResourceKey("ColorPicker.ColorPickerSliderThumbShadow");
public static readonly TokenResourceKey ColorPickerSliderThumbSize = new TokenResourceKey("ColorPicker.ColorPickerSliderThumbSize");
public static readonly TokenResourceKey ColorPickerSliderTrackSize = new TokenResourceKey("ColorPicker.ColorPickerSliderTrackSize");
public static readonly TokenResourceKey ColorPickerWidth = new TokenResourceKey("ColorPicker.ColorPickerWidth");
public static readonly TokenResourceKey ColorSpectrumHeight = new TokenResourceKey("ColorPicker.ColorSpectrumHeight");