Browse Source

Implement ProgressBar animation in XAML. Contributes to #1670.

pull/1768/head
Jeremy Koritzinsky 8 years ago
parent
commit
b1cb87b770
  1. 71
      src/Avalonia.Controls/ProgressBar.cs
  2. 41
      src/Avalonia.Themes.Default/ProgressBar.xaml

71
src/Avalonia.Controls/ProgressBar.cs

@ -21,18 +21,18 @@ namespace Avalonia.Controls
public static readonly StyledProperty<Orientation> OrientationProperty =
AvaloniaProperty.Register<ProgressBar, Orientation>(nameof(Orientation), Orientation.Horizontal);
private static readonly StyledProperty<double> IndeterminateStartingOffsetProperty =
AvaloniaProperty.Register<ProgressBar, double>(nameof(IndeterminateStartingOffset));
private Border _indicator;
private IndeterminateAnimation _indeterminateAnimation;
static ProgressBar()
{
PseudoClass(OrientationProperty, o => o == Avalonia.Controls.Orientation.Vertical, ":vertical");
PseudoClass(OrientationProperty, o => o == Avalonia.Controls.Orientation.Horizontal, ":horizontal");
PseudoClass(IsIndeterminateProperty, ":indeterminate");
ValueProperty.Changed.AddClassHandler<ProgressBar>(x => x.ValueChanged);
IsIndeterminateProperty.Changed.AddClassHandler<ProgressBar>(
(p, e) => { if (p._indicator != null) p.UpdateIsIndeterminate((bool)e.NewValue); });
}
public bool IsIndeterminate
@ -47,6 +47,12 @@ namespace Avalonia.Controls
set => SetValue(OrientationProperty, value);
}
private double IndeterminateStartingOffset
{
get => GetValue(IndeterminateStartingOffsetProperty);
set => SetValue(IndeterminateStartingOffsetProperty, value);
}
/// <inheritdoc/>
protected override Size ArrangeOverride(Size finalSize)
{
@ -60,7 +66,6 @@ namespace Avalonia.Controls
_indicator = e.NameScope.Get<Border>("PART_Indicator");
UpdateIndicator(Bounds.Size);
UpdateIsIndeterminate(IsIndeterminate);
}
private void UpdateIndicator(Size bounds)
@ -70,9 +75,17 @@ namespace Avalonia.Controls
if (IsIndeterminate)
{
if (Orientation == Orientation.Horizontal)
_indicator.Width = bounds.Width / 5.0;
{
var width = bounds.Width / 5.0;
IndeterminateStartingOffset = -width;
_indicator.Width = width;
}
else
_indicator.Height = bounds.Height / 5.0;
{
var height = bounds.Height / 5.0;
IndeterminateStartingOffset = -height;
_indicator.Height = height;
}
}
else
{
@ -86,53 +99,9 @@ namespace Avalonia.Controls
}
}
private void UpdateIsIndeterminate(bool isIndeterminate)
{
if (isIndeterminate)
{
if (_indeterminateAnimation == null || _indeterminateAnimation.Disposed)
_indeterminateAnimation = IndeterminateAnimation.StartAnimation(this);
}
else
_indeterminateAnimation?.Dispose();
}
private void ValueChanged(AvaloniaPropertyChangedEventArgs e)
{
UpdateIndicator(Bounds.Size);
}
// TODO: Implement Indeterminate Progress animation
// in xaml (most ideal) or if it's not possible
// then on this class.
private class IndeterminateAnimation : IDisposable
{
private WeakReference<ProgressBar> _progressBar;
private bool _disposed;
public bool Disposed => _disposed;
private IndeterminateAnimation(ProgressBar progressBar)
{
_progressBar = new WeakReference<ProgressBar>(progressBar);
}
public static IndeterminateAnimation StartAnimation(ProgressBar progressBar)
{
return new IndeterminateAnimation(progressBar);
}
private Rect GetAnimationRect(TimeSpan time)
{
return Rect.Empty;
}
public void Dispose()
{
_disposed = true;
}
}
}
}

41
src/Avalonia.Themes.Default/ProgressBar.xaml

@ -7,14 +7,11 @@
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<Border Name="PART_Track"
BorderThickness="1"
BorderBrush="{TemplateBinding Background}"/>
<Canvas>
<Border Name="PART_Indicator"
BorderThickness="1"
Background="{TemplateBinding Foreground}" />
</Grid>
Background="{TemplateBinding Foreground}"/>
</Canvas>
</Border>
</ControlTemplate>
</Setter>
@ -22,10 +19,12 @@
<Style Selector="ProgressBar:horizontal /template/ Border#PART_Indicator">
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="VerticalAlignment" Value="Stretch"/>
<Setter Property="Height" Value="{Binding Bounds.Height, RelativeSource={RelativeSource TemplatedParent}}" />
</Style>
<Style Selector="ProgressBar:vertical /template/ Border#PART_Indicator">
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="VerticalAlignment" Value="Bottom"/>
<Setter Property="Width" Value="{Binding Bounds.Width, RelativeSource={RelativeSource TemplatedParent}}" />
</Style>
<Style Selector="ProgressBar:horizontal">
<Setter Property="MinWidth" Value="200"/>
@ -35,4 +34,32 @@
<Setter Property="MinWidth" Value="14"/>
<Setter Property="MinHeight" Value="200"/>
</Style>
</Styles>
<Style Selector="ProgressBar:horizontal:indeterminate /template/ Border#PART_Indicator">
<Style.Animations>
<Animation Duration="0:0:3"
RepeatCount="Loop"
Easing="LinearEasing">
<KeyFrame Cue="0%">
<Setter Property="Canvas.Left" Value="{Binding IndeterminateStartingOffset, RelativeSource={RelativeSource TemplatedParent}}" />
</KeyFrame>
<KeyFrame Cue="100%">
<Setter Property="Canvas.Left" Value="{Binding Bounds.Width, RelativeSource={RelativeSource TemplatedParent}}" />
</KeyFrame>
</Animation>
</Style.Animations>
</Style>
<Style Selector="ProgressBar:vertical:indeterminate /template/ Border#PART_Indicator">
<Style.Animations>
<Animation Duration="0:0:3"
RepeatCount="Loop"
Easing="LinearEasing">
<KeyFrame Cue="0%">
<Setter Property="Canvas.Top" Value="{Binding IndeterminateStartingOffset, RelativeSource={RelativeSource TemplatedParent}}" />
</KeyFrame>
<KeyFrame Cue="100%">
<Setter Property="Canvas.Top" Value="{Binding Bounds.Height, RelativeSource={RelativeSource TemplatedParent}}" />
</KeyFrame>
</Animation>
</Style.Animations>
</Style>
</Styles>

Loading…
Cancel
Save