feat: add progress ring.

This commit is contained in:
rabbitism 2023-07-03 11:49:11 +08:00
parent 8bdfe2b7de
commit 27e344950a
3 changed files with 126 additions and 1 deletions

View File

@ -8,12 +8,27 @@
d:DesignWidth="800"
mc:Ignorable="d">
<StackPanel HorizontalAlignment="Left" Spacing="20">
<ProgressBar
Width="100"
Height="100"
IsIndeterminate="True"
Maximum="{Binding #slider.Maximum}"
Minimum="{Binding #slider.Minimum}"
Theme="{DynamicResource ProgressRing}"
Value="{Binding #slider.Value}" />
<Slider
Name="slider"
Width="300"
IsSnapToTickEnabled="True"
Maximum="100"
Minimum="0"
TickFrequency="10" />
<ProgressBar
Width="200"
Maximum="100"
Minimum="0"
ShowProgressText="True"
Value="20" />
Value="{Binding #slider.Value}" />
<ProgressBar
Width="200"
IsIndeterminate="True"

View File

@ -2,6 +2,7 @@
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:converters="using:Avalonia.Controls.Converters"
xmlns:semiConverters="clr-namespace:Semi.Avalonia.Converters"
x:CompileBindings="True">
<Design.PreviewWith>
<StackPanel Margin="20" Spacing="20">
@ -326,4 +327,86 @@
</Style>
</Style>
</ControlTheme>
<semiConverters:PositionToAngleConverter x:Key="AngleConverter" />
<ControlTheme x:Key="ProgressRing" TargetType="ProgressBar">
<Setter Property="Foreground" Value="{DynamicResource ProgressBarIndicatorBrush}" />
<Setter Property="Background" Value="{DynamicResource ProgressBarBackground}" />
<Setter Property="Template">
<ControlTemplate TargetType="ProgressBar">
<Panel>
<Border Name="PART_Indicator" />
<Arc
Name="Background"
RenderOptions.EdgeMode="Antialias"
StartAngle="-90"
Stroke="{TemplateBinding Background}"
StrokeJoin="Round"
StrokeLineCap="Round"
StrokeThickness="6"
SweepAngle="360" />
<Arc
Name="Indicator"
RenderOptions.EdgeMode="Antialias"
StartAngle="-90"
Stroke="{TemplateBinding Foreground}"
StrokeJoin="Round"
StrokeLineCap="Round"
StrokeThickness="6"
SweepAngle="{TemplateBinding Percentage,
Converter={StaticResource AngleConverter}}" />
<Arc
Name="IndeterminateIndicator"
Opacity="0"
RenderOptions.EdgeMode="Antialias"
StartAngle="-90"
Stroke="{TemplateBinding Foreground}"
StrokeJoin="Round"
StrokeLineCap="Round"
StrokeThickness="6"
SweepAngle="{TemplateBinding Percentage,
Converter={StaticResource AngleConverter}}" />
<TextBlock
Name="PART_ProgressText"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontWeight="{DynamicResource ProgressBarTextFontWeight}"
Foreground="{DynamicResource ProgressBarTextForeground}">
<TextBlock.Text>
<MultiBinding Converter="{StaticResource StringFormatConverter}">
<TemplateBinding Property="ProgressTextFormat" />
<TemplateBinding Property="Value" />
<TemplateBinding Property="Percentage" />
<TemplateBinding Property="Minimum" />
<TemplateBinding Property="Maximum" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</Panel>
</ControlTemplate>
</Setter>
<Style Selector="^:indeterminate /template/ Arc#Indicator">
<Setter Property="Opacity" Value="0" />
</Style>
<Style Selector="^:indeterminate /template/ Arc#IndeterminateIndicator">
<Setter Property="Opacity" Value="1" />
<Style.Animations>
<Animation IterationCount="Infinite" Duration="0:0:2">
<KeyFrame KeyTime="0:0:0">
<Setter Property="StartAngle" Value="-90" />
<Setter Property="SweepAngle" Value="20" />
</KeyFrame>
<KeyFrame KeyTime="0:0:1.5">
<Setter Property="StartAngle" Value="90" />
<Setter Property="SweepAngle" Value="160" />
</KeyFrame>
<KeyFrame KeyTime="0:0:2">
<Setter Property="StartAngle" Value="270" />
<Setter Property="SweepAngle" Value="20" />
</KeyFrame>
</Animation>
</Style.Animations>
</Style>
</ControlTheme>
</ResourceDictionary>

View File

@ -0,0 +1,27 @@
using System;
using System.Globalization;
using Avalonia.Data.Converters;
namespace Semi.Avalonia.Converters;
public class PositionToAngleConverter: IValueConverter
{
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
if (value is double d)
{
return d * 3.6;
}
return 0;
}
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
if (value is double d)
{
return d / 3.6;
}
return 0;
}
}