feat: Add Loading styles and demos.
This commit is contained in:
1 parent
db0ced2f00
commit
5bfbbe1904
8 files changed
+587
-1
No files matched your search
@@ -53,7 +53,8 @@
|
||||
[ "HoneycombPanel", "HoneycombPanelDemo", "Brush.PolygonHexagon", "", "Layout" ],
|
||||
[ "UniformSpacingPanel", "UniformSpacingPanelDemo", "Brush.IncreaseHorizontalSpacing", "", "Layout" ],
|
||||
[ "ProgressBar", "ProgressBarDemo", "Brush.ProgressBar", "", "Feedback" ],
|
||||
[ "Rate", "RateDemo", "Brush.Favorite", "", "Feedback" ]
|
||||
[ "Rate", "RateDemo", "Brush.Favorite", "", "Feedback" ],
|
||||
[ "Loading", "LoadingDemo", "Brush.Loading", "", "Feedback" ]
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,27 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:hc="https://handyorg.github.io/handycontrol"
|
||||
x:Class="HandyControlDemo.UserControl.LoadingDemo"
|
||||
Background="{DynamicResource RegionBrush}">
|
||||
<TransitioningContentControl>
|
||||
<StackPanel Width="600"
|
||||
Margin="32"
|
||||
VerticalAlignment="Center">
|
||||
<hc:LoadingLine />
|
||||
<hc:LoadingLine Margin="0,30"
|
||||
Foreground="BlueViolet"
|
||||
Theme="{StaticResource LoadingLineLarge}" />
|
||||
<StackPanel Orientation="Horizontal"
|
||||
HorizontalAlignment="Center">
|
||||
<hc:LoadingCircle />
|
||||
<Border VerticalAlignment="Center"
|
||||
Margin="32,0,0,0"
|
||||
Background="{DynamicResource PrimaryBrush}"
|
||||
CornerRadius="10">
|
||||
<hc:LoadingCircle Theme="{StaticResource LoadingCircleLight}"
|
||||
Margin="10" />
|
||||
</Border>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</TransitioningContentControl>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace HandyControlDemo.UserControl;
|
||||
|
||||
public partial class LoadingDemo : Avalonia.Controls.UserControl
|
||||
{
|
||||
public LoadingDemo()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Shapes;
|
||||
using Avalonia.Data;
|
||||
using Avalonia.Media;
|
||||
|
||||
namespace HandyControl.Controls;
|
||||
|
||||
public abstract class LoadingBase : ContentControl
|
||||
{
|
||||
protected readonly List<CancellationTokenSource> AnimationTokens = new();
|
||||
|
||||
public static readonly StyledProperty<bool> IsRunningProperty =
|
||||
AvaloniaProperty.Register<LoadingBase, bool>(nameof(IsRunning), true);
|
||||
|
||||
public static readonly StyledProperty<int> DotCountProperty =
|
||||
AvaloniaProperty.Register<LoadingBase, int>(nameof(DotCount), 5);
|
||||
|
||||
public static readonly StyledProperty<double> DotIntervalProperty =
|
||||
AvaloniaProperty.Register<LoadingBase, double>(nameof(DotInterval), 10d);
|
||||
|
||||
public static readonly StyledProperty<IBrush?> DotBorderBrushProperty =
|
||||
AvaloniaProperty.Register<LoadingBase, IBrush?>(nameof(DotBorderBrush));
|
||||
|
||||
public static readonly StyledProperty<double> DotBorderThicknessProperty =
|
||||
AvaloniaProperty.Register<LoadingBase, double>(nameof(DotBorderThickness), 0d);
|
||||
|
||||
public static readonly StyledProperty<double> DotDiameterProperty =
|
||||
AvaloniaProperty.Register<LoadingBase, double>(nameof(DotDiameter), 6d);
|
||||
|
||||
public static readonly StyledProperty<double> DotSpeedProperty =
|
||||
AvaloniaProperty.Register<LoadingBase, double>(nameof(DotSpeed), 4d);
|
||||
|
||||
public static readonly StyledProperty<double> DotDelayTimeProperty =
|
||||
AvaloniaProperty.Register<LoadingBase, double>(nameof(DotDelayTime), 80d);
|
||||
|
||||
protected readonly Canvas PrivateCanvas = new()
|
||||
{
|
||||
ClipToBounds = true
|
||||
};
|
||||
|
||||
protected LoadingBase()
|
||||
{
|
||||
Content = PrivateCanvas;
|
||||
}
|
||||
|
||||
public bool IsRunning
|
||||
{
|
||||
get => GetValue(IsRunningProperty);
|
||||
set => SetValue(IsRunningProperty, value);
|
||||
}
|
||||
|
||||
public int DotCount
|
||||
{
|
||||
get => GetValue(DotCountProperty);
|
||||
set => SetValue(DotCountProperty, value);
|
||||
}
|
||||
|
||||
public double DotInterval
|
||||
{
|
||||
get => GetValue(DotIntervalProperty);
|
||||
set => SetValue(DotIntervalProperty, value);
|
||||
}
|
||||
|
||||
public IBrush? DotBorderBrush
|
||||
{
|
||||
get => GetValue(DotBorderBrushProperty);
|
||||
set => SetValue(DotBorderBrushProperty, value);
|
||||
}
|
||||
|
||||
public double DotBorderThickness
|
||||
{
|
||||
get => GetValue(DotBorderThicknessProperty);
|
||||
set => SetValue(DotBorderThicknessProperty, value);
|
||||
}
|
||||
|
||||
public double DotDiameter
|
||||
{
|
||||
get => GetValue(DotDiameterProperty);
|
||||
set => SetValue(DotDiameterProperty, value);
|
||||
}
|
||||
|
||||
public double DotSpeed
|
||||
{
|
||||
get => GetValue(DotSpeedProperty);
|
||||
set => SetValue(DotSpeedProperty, value);
|
||||
}
|
||||
|
||||
public double DotDelayTime
|
||||
{
|
||||
get => GetValue(DotDelayTimeProperty);
|
||||
set => SetValue(DotDelayTimeProperty, value);
|
||||
}
|
||||
|
||||
protected abstract void UpdateDots();
|
||||
|
||||
protected void StopAnimations()
|
||||
{
|
||||
foreach (var cts in AnimationTokens)
|
||||
{
|
||||
try { cts.Cancel(); cts.Dispose(); } catch { }
|
||||
}
|
||||
AnimationTokens.Clear();
|
||||
}
|
||||
|
||||
protected override void OnSizeChanged(SizeChangedEventArgs e)
|
||||
{
|
||||
base.OnSizeChanged(e);
|
||||
if (IsRunning)
|
||||
{
|
||||
StopAnimations();
|
||||
UpdateDots();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
||||
{
|
||||
base.OnPropertyChanged(change);
|
||||
|
||||
if (change.Property == IsRunningProperty)
|
||||
{
|
||||
if (IsRunning)
|
||||
{
|
||||
UpdateDots();
|
||||
}
|
||||
else
|
||||
{
|
||||
StopAnimations();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (change.Property == DotCountProperty
|
||||
|| change.Property == DotIntervalProperty
|
||||
|| change.Property == DotBorderBrushProperty
|
||||
|| change.Property == DotBorderThicknessProperty
|
||||
|| change.Property == DotDiameterProperty
|
||||
|| change.Property == DotSpeedProperty
|
||||
|| change.Property == DotDelayTimeProperty
|
||||
|| change.Property == ForegroundProperty)
|
||||
{
|
||||
if (IsRunning)
|
||||
{
|
||||
StopAnimations();
|
||||
UpdateDots();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnLoaded(Avalonia.Interactivity.RoutedEventArgs e)
|
||||
{
|
||||
base.OnLoaded(e);
|
||||
if (IsRunning)
|
||||
{
|
||||
StopAnimations();
|
||||
UpdateDots();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnUnloaded(Avalonia.Interactivity.RoutedEventArgs e)
|
||||
{
|
||||
base.OnUnloaded(e);
|
||||
StopAnimations();
|
||||
}
|
||||
|
||||
protected virtual Ellipse CreateEllipse(int index)
|
||||
{
|
||||
var ellipse = new Ellipse();
|
||||
ellipse.Bind(WidthProperty, new Binding(nameof(DotDiameter)) { Source = this });
|
||||
ellipse.Bind(HeightProperty, new Binding(nameof(DotDiameter)) { Source = this });
|
||||
ellipse.Bind(Shape.FillProperty, new Binding(nameof(Foreground)) { Source = this });
|
||||
ellipse.Bind(Shape.StrokeThicknessProperty, new Binding(nameof(DotBorderThickness)) { Source = this });
|
||||
ellipse.Bind(Shape.StrokeProperty, new Binding(nameof(DotBorderBrush)) { Source = this });
|
||||
return ellipse;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using Avalonia;
|
||||
using Avalonia.Animation;
|
||||
using Avalonia.Animation.Easings;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Data;
|
||||
using Avalonia.Layout;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Styling;
|
||||
|
||||
namespace HandyControl.Controls;
|
||||
|
||||
public class LoadingCircle : LoadingBase
|
||||
{
|
||||
public static readonly StyledProperty<double> DotOffSetProperty =
|
||||
AvaloniaProperty.Register<LoadingCircle, double>(nameof(DotOffSet), 20d);
|
||||
|
||||
public double DotOffSet
|
||||
{
|
||||
get => GetValue(DotOffSetProperty);
|
||||
set => SetValue(DotOffSetProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<bool> NeedHiddenProperty =
|
||||
AvaloniaProperty.Register<LoadingCircle, bool>(nameof(NeedHidden), true);
|
||||
|
||||
public bool NeedHidden
|
||||
{
|
||||
get => GetValue(NeedHiddenProperty);
|
||||
set => SetValue(NeedHiddenProperty, value);
|
||||
}
|
||||
|
||||
static LoadingCircle()
|
||||
{
|
||||
DotSpeedProperty.OverrideDefaultValue<LoadingCircle>(6d);
|
||||
DotDelayTimeProperty.OverrideDefaultValue<LoadingCircle>(220d);
|
||||
}
|
||||
|
||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
||||
{
|
||||
if (change.Property == DotOffSetProperty || change.Property == NeedHiddenProperty)
|
||||
{
|
||||
if (IsRunning)
|
||||
{
|
||||
StopAnimations();
|
||||
UpdateDots();
|
||||
}
|
||||
}
|
||||
base.OnPropertyChanged(change);
|
||||
}
|
||||
|
||||
protected sealed override void UpdateDots()
|
||||
{
|
||||
var dotCount = DotCount;
|
||||
var dotInterval = DotInterval;
|
||||
var dotSpeed = DotSpeed;
|
||||
var dotDelayTime = DotDelayTime;
|
||||
var needHidden = NeedHidden;
|
||||
var dotOffset = DotOffSet;
|
||||
|
||||
if (dotCount < 1) return;
|
||||
PrivateCanvas.Children.Clear();
|
||||
|
||||
for (var i = 0; i < dotCount; i++)
|
||||
{
|
||||
var rotate = new RotateTransform();
|
||||
var border = CreateBorder(i, dotInterval, needHidden, rotate);
|
||||
PrivateCanvas.Children.Add(border);
|
||||
|
||||
var subAngle = -dotInterval * i;
|
||||
rotate.Angle = subAngle;
|
||||
|
||||
var rotateAnimation = new Animation
|
||||
{
|
||||
Duration = TimeSpan.FromSeconds(dotSpeed),
|
||||
Delay = TimeSpan.FromMilliseconds(dotDelayTime * i),
|
||||
IterationCount = IterationCount.Infinite,
|
||||
FillMode = FillMode.Forward,
|
||||
Easing = new LinearEasing(),
|
||||
Children =
|
||||
{
|
||||
BuildAngleFrame(0d / 7d, 0 + subAngle, null),
|
||||
BuildAngleFrame(0.75d / 7d, 180 + subAngle, EaseOutSpline),
|
||||
BuildAngleFrame(2.75d / 7d, 180 + dotOffset + subAngle, null),
|
||||
BuildAngleFrame(3.5d / 7d, 360 + subAngle, EaseInSpline),
|
||||
BuildAngleFrame(4.25d / 7d, 540 + subAngle, EaseOutSpline),
|
||||
BuildAngleFrame(6.25d / 7d, 540 + dotOffset + subAngle, null),
|
||||
BuildAngleFrame(1d, 720 + subAngle, EaseInSpline),
|
||||
}
|
||||
};
|
||||
|
||||
var rotateCts = new CancellationTokenSource();
|
||||
AnimationTokens.Add(rotateCts);
|
||||
_ = rotateAnimation.RunAsync(border, rotateCts.Token);
|
||||
|
||||
if (needHidden)
|
||||
{
|
||||
var totalSeconds = dotSpeed + 0.4d;
|
||||
var visibleCue = dotSpeed / totalSeconds;
|
||||
|
||||
var opacityAnimation = new Animation
|
||||
{
|
||||
Duration = TimeSpan.FromSeconds(totalSeconds),
|
||||
Delay = TimeSpan.FromMilliseconds(dotDelayTime * i),
|
||||
IterationCount = IterationCount.Infinite,
|
||||
FillMode = FillMode.Forward,
|
||||
Easing = new LinearEasing(),
|
||||
Children =
|
||||
{
|
||||
new KeyFrame
|
||||
{
|
||||
Cue = new Cue(0d),
|
||||
Setters = { new Setter(Visual.OpacityProperty, 1d) }
|
||||
},
|
||||
new KeyFrame
|
||||
{
|
||||
Cue = new Cue(Math.Max(0d, visibleCue - 0.0001d)),
|
||||
Setters = { new Setter(Visual.OpacityProperty, 1d) }
|
||||
},
|
||||
new KeyFrame
|
||||
{
|
||||
Cue = new Cue(visibleCue),
|
||||
Setters = { new Setter(Visual.OpacityProperty, 0d) }
|
||||
},
|
||||
new KeyFrame
|
||||
{
|
||||
Cue = new Cue(1d),
|
||||
Setters = { new Setter(Visual.OpacityProperty, 0d) }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var opacityCts = new CancellationTokenSource();
|
||||
AnimationTokens.Add(opacityCts);
|
||||
_ = opacityAnimation.RunAsync(border, opacityCts.Token);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly KeySpline EaseOutSpline = new(0d, 0d, 0.5d, 1d);
|
||||
private static readonly KeySpline EaseInSpline = new(0.5d, 0d, 1d, 1d);
|
||||
|
||||
private static KeyFrame BuildAngleFrame(double cue, double angle, KeySpline? spline)
|
||||
{
|
||||
var frame = new KeyFrame
|
||||
{
|
||||
Cue = new Cue(Math.Min(1d, Math.Max(0d, cue))),
|
||||
Setters = { new Setter(RotateTransform.AngleProperty, angle) }
|
||||
};
|
||||
if (spline != null)
|
||||
{
|
||||
frame.KeySpline = spline;
|
||||
}
|
||||
return frame;
|
||||
}
|
||||
|
||||
private Border CreateBorder(int index, double dotInterval, bool needHidden, RotateTransform rotate)
|
||||
{
|
||||
var ellipse = CreateEllipse(index);
|
||||
ellipse.HorizontalAlignment = HorizontalAlignment.Center;
|
||||
ellipse.VerticalAlignment = VerticalAlignment.Bottom;
|
||||
|
||||
var border = new Border
|
||||
{
|
||||
Child = ellipse,
|
||||
RenderTransformOrigin = RelativePoint.Center,
|
||||
RenderTransform = rotate,
|
||||
Opacity = needHidden ? 0d : 1d
|
||||
};
|
||||
border.Bind(WidthProperty, new Binding(nameof(Width)) { Source = this });
|
||||
border.Bind(HeightProperty, new Binding(nameof(Height)) { Source = this });
|
||||
|
||||
return border;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using Avalonia;
|
||||
using Avalonia.Animation;
|
||||
using Avalonia.Animation.Easings;
|
||||
using Avalonia.Controls.Shapes;
|
||||
using Avalonia.Data;
|
||||
using Avalonia.Layout;
|
||||
using Avalonia.Styling;
|
||||
|
||||
namespace HandyControl.Controls;
|
||||
|
||||
public class LoadingLine : LoadingBase
|
||||
{
|
||||
private const double MoveLength = 80;
|
||||
private const double UniformScale = 0.6;
|
||||
|
||||
private static readonly KeySpline EaseOutSpline = new(0d, 0d, 0.5d, 1d);
|
||||
private static readonly KeySpline EaseInSpline = new(0.5d, 0d, 1d, 1d);
|
||||
|
||||
public LoadingLine()
|
||||
{
|
||||
this.Bind(HeightProperty, new Binding(nameof(DotDiameter)) { Source = this });
|
||||
}
|
||||
|
||||
protected sealed override void UpdateDots()
|
||||
{
|
||||
var dotCount = DotCount;
|
||||
var dotInterval = DotInterval;
|
||||
var dotDiameter = DotDiameter;
|
||||
var dotSpeed = DotSpeed;
|
||||
var dotDelayTime = DotDelayTime;
|
||||
|
||||
if (dotCount < 1) return;
|
||||
PrivateCanvas.Children.Clear();
|
||||
|
||||
var actualWidth = Bounds.Width;
|
||||
if (double.IsNaN(actualWidth) || actualWidth <= 0)
|
||||
{
|
||||
// Bounds 还没准备好;OnSizeChanged 之后会再触发一次
|
||||
return;
|
||||
}
|
||||
|
||||
var centerWidth = dotDiameter * dotCount + dotInterval * (dotCount - 1) + MoveLength;
|
||||
var speedDownLength = (actualWidth - MoveLength) / 2;
|
||||
var speedUniformLength = centerWidth / 2;
|
||||
|
||||
for (var i = 0; i < dotCount; i++)
|
||||
{
|
||||
var ellipse = CreateLineEllipse(i, dotInterval, dotDiameter);
|
||||
PrivateCanvas.Children.Add(ellipse);
|
||||
|
||||
var startLeft = ellipse.Margin.Left;
|
||||
|
||||
var animation = new Animation
|
||||
{
|
||||
Duration = TimeSpan.FromSeconds(dotSpeed),
|
||||
Delay = TimeSpan.FromMilliseconds(dotDelayTime * i),
|
||||
IterationCount = IterationCount.Infinite,
|
||||
FillMode = FillMode.Forward,
|
||||
// WPF 用 PowerEase EaseOut/EaseIn + Linear,Avalonia 单缓动近似为 LinearEasing,
|
||||
// 关键帧自身位置已经表达了"快/匀/慢"的节奏。
|
||||
Easing = new LinearEasing(),
|
||||
Children =
|
||||
{
|
||||
new KeyFrame
|
||||
{
|
||||
Cue = new Cue(0d),
|
||||
Setters = { new Setter(MarginProperty, new Thickness(startLeft, 0, 0, 0)) }
|
||||
},
|
||||
new KeyFrame
|
||||
{
|
||||
Cue = new Cue((1 - UniformScale) / 2),
|
||||
KeySpline = EaseOutSpline,
|
||||
Setters = { new Setter(MarginProperty, new Thickness(speedDownLength + startLeft, 0, 0, 0)) }
|
||||
},
|
||||
new KeyFrame
|
||||
{
|
||||
Cue = new Cue((1 + UniformScale) / 2),
|
||||
Setters = { new Setter(MarginProperty, new Thickness(speedDownLength + speedUniformLength + startLeft, 0, 0, 0)) }
|
||||
},
|
||||
new KeyFrame
|
||||
{
|
||||
Cue = new Cue(1d),
|
||||
KeySpline = EaseInSpline,
|
||||
Setters = { new Setter(MarginProperty, new Thickness(actualWidth + startLeft + speedUniformLength, 0, 0, 0)) }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var cts = new CancellationTokenSource();
|
||||
AnimationTokens.Add(cts);
|
||||
_ = animation.RunAsync(ellipse, cts.Token);
|
||||
}
|
||||
}
|
||||
|
||||
private Ellipse CreateLineEllipse(int index, double dotInterval, double dotDiameter)
|
||||
{
|
||||
var ellipse = base.CreateEllipse(index);
|
||||
ellipse.HorizontalAlignment = HorizontalAlignment.Left;
|
||||
ellipse.VerticalAlignment = VerticalAlignment.Top;
|
||||
ellipse.Margin = new Thickness(-(dotInterval + dotDiameter) * index, 0, 0, 0);
|
||||
return ellipse;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
<ResourceDictionary xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
x:ClassModifier="internal"
|
||||
xmlns:hc="clr-namespace:HandyControl.Controls">
|
||||
|
||||
<ControlTheme x:Key="LoadingBaseStyle"
|
||||
TargetType="hc:LoadingBase">
|
||||
<Setter Property="Focusable" Value="False" />
|
||||
<Setter Property="DotDiameter" Value="10" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource PrimaryBrush}" />
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<ContentPresenter Content="{TemplateBinding Content}"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
</ControlTheme>
|
||||
|
||||
<!-- LoadingLine -->
|
||||
<ControlTheme x:Key="LoadingLineBaseStyle"
|
||||
BasedOn="{StaticResource LoadingBaseStyle}"
|
||||
TargetType="hc:LoadingLine">
|
||||
<Setter Property="DotDiameter" Value="5" />
|
||||
</ControlTheme>
|
||||
|
||||
<ControlTheme x:Key="{x:Type hc:LoadingLine}"
|
||||
BasedOn="{StaticResource LoadingLineBaseStyle}"
|
||||
TargetType="hc:LoadingLine" />
|
||||
|
||||
<ControlTheme x:Key="LoadingLineLight"
|
||||
BasedOn="{StaticResource LoadingLineBaseStyle}"
|
||||
TargetType="hc:LoadingLine">
|
||||
<Setter Property="Foreground" Value="{DynamicResource TextIconBrush}" />
|
||||
</ControlTheme>
|
||||
|
||||
<ControlTheme x:Key="LoadingLineLarge"
|
||||
BasedOn="{StaticResource LoadingLineBaseStyle}"
|
||||
TargetType="hc:LoadingLine">
|
||||
<Setter Property="DotDiameter" Value="10" />
|
||||
</ControlTheme>
|
||||
|
||||
<ControlTheme x:Key="LoadingLineLargeLight"
|
||||
BasedOn="{StaticResource LoadingLineLarge}"
|
||||
TargetType="hc:LoadingLine">
|
||||
<Setter Property="Foreground" Value="{DynamicResource TextIconBrush}" />
|
||||
</ControlTheme>
|
||||
|
||||
<!-- LoadingCircle -->
|
||||
<ControlTheme x:Key="LoadingCircleBaseStyle"
|
||||
BasedOn="{StaticResource LoadingBaseStyle}"
|
||||
TargetType="hc:LoadingCircle">
|
||||
<Setter Property="Width" Value="40" />
|
||||
<Setter Property="Height" Value="40" />
|
||||
<Setter Property="DotDiameter" Value="5" />
|
||||
<Setter Property="DotInterval" Value="30" />
|
||||
<Setter Property="DotOffSet" Value="60" />
|
||||
<Setter Property="DotDelayTime" Value="90" />
|
||||
<Setter Property="DotSpeed" Value="4" />
|
||||
</ControlTheme>
|
||||
|
||||
<ControlTheme x:Key="{x:Type hc:LoadingCircle}"
|
||||
BasedOn="{StaticResource LoadingCircleBaseStyle}"
|
||||
TargetType="hc:LoadingCircle" />
|
||||
|
||||
<ControlTheme x:Key="LoadingCircleLight"
|
||||
BasedOn="{StaticResource LoadingCircleBaseStyle}"
|
||||
TargetType="hc:LoadingCircle">
|
||||
<Setter Property="Foreground" Value="{DynamicResource TextIconBrush}" />
|
||||
</ControlTheme>
|
||||
|
||||
<ControlTheme x:Key="LoadingCircleLarge"
|
||||
BasedOn="{StaticResource LoadingCircleBaseStyle}"
|
||||
TargetType="hc:LoadingCircle">
|
||||
<Setter Property="Width" Value="100" />
|
||||
<Setter Property="Height" Value="100" />
|
||||
<Setter Property="DotDiameter" Value="10" />
|
||||
<Setter Property="DotInterval" Value="20" />
|
||||
<Setter Property="DotOffSet" Value="40" />
|
||||
<Setter Property="DotDelayTime" Value="120" />
|
||||
</ControlTheme>
|
||||
|
||||
<ControlTheme x:Key="LoadingCircleLargeLight"
|
||||
BasedOn="{StaticResource LoadingCircleLarge}"
|
||||
TargetType="hc:LoadingCircle">
|
||||
<Setter Property="Foreground" Value="{DynamicResource TextIconBrush}" />
|
||||
</ControlTheme>
|
||||
|
||||
</ResourceDictionary>
|
||||
@@ -51,6 +51,7 @@
|
||||
<MergeResourceInclude Source="avares://HandyControl/Themes/Styles/Rate.axaml" />
|
||||
<MergeResourceInclude Source="avares://HandyControl/Themes/Styles/Expander.axaml" />
|
||||
<MergeResourceInclude Source="avares://HandyControl/Themes/Styles/ProgressBar.axaml" />
|
||||
<MergeResourceInclude Source="avares://HandyControl/Themes/Styles/Loading.axaml" />
|
||||
<MergeResourceInclude Source="avares://HandyControl/Themes/Styles/Calendar.axaml" />
|
||||
<MergeResourceInclude Source="avares://HandyControl/Themes/Styles/CalendarDatePicker.axaml" />
|
||||
<MergeResourceInclude Source="avares://HandyControl/Themes/Styles/DatePicker.axaml" />
|
||||
|
||||
Reference in new issue
Block a user