diff --git a/samples/RenderDemo/Pages/AnimationsPage.xaml b/samples/RenderDemo/Pages/AnimationsPage.xaml
index 5287e4e373..473807ac50 100644
--- a/samples/RenderDemo/Pages/AnimationsPage.xaml
+++ b/samples/RenderDemo/Pages/AnimationsPage.xaml
@@ -107,9 +107,12 @@
+
+
+
Hover to activate Transform Keyframe Animations.
-
+
@@ -120,4 +123,4 @@
-
\ No newline at end of file
+
diff --git a/samples/RenderDemo/Pages/AnimationsPage.xaml.cs b/samples/RenderDemo/Pages/AnimationsPage.xaml.cs
index 5b02fd9297..2195b3d494 100644
--- a/samples/RenderDemo/Pages/AnimationsPage.xaml.cs
+++ b/samples/RenderDemo/Pages/AnimationsPage.xaml.cs
@@ -5,6 +5,7 @@ using Avalonia.Controls;
using Avalonia.Controls.Shapes;
using Avalonia.Data;
using Avalonia.Input;
+using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
using Avalonia.Media;
using RenderDemo.ViewModels;
@@ -23,5 +24,20 @@ namespace RenderDemo.Pages
{
AvaloniaXamlLoader.Load(this);
}
+
+ private void ToggleClock(object sender, RoutedEventArgs args)
+ {
+ var button = sender as Button;
+ var clock = button.Clock;
+
+ if (clock.PlayState == PlayState.Run)
+ {
+ clock.PlayState = PlayState.Pause;
+ }
+ else if (clock.PlayState == PlayState.Pause)
+ {
+ clock.PlayState = PlayState.Run;
+ }
+ }
}
}
diff --git a/samples/RenderDemo/ViewModels/AnimationsPageViewModel.cs b/samples/RenderDemo/ViewModels/AnimationsPageViewModel.cs
index f724baf3c6..7b89b7944c 100644
--- a/samples/RenderDemo/ViewModels/AnimationsPageViewModel.cs
+++ b/samples/RenderDemo/ViewModels/AnimationsPageViewModel.cs
@@ -6,27 +6,15 @@ namespace RenderDemo.ViewModels
{
public class AnimationsPageViewModel : ReactiveObject
{
- private string _playStateText = "Pause all animations";
+ private bool _isPlaying = true;
- public AnimationsPageViewModel()
- {
- ToggleGlobalPlayState = ReactiveCommand.Create(() => TogglePlayState());
- }
+ private string _playStateText = "Pause animations on this page";
- void TogglePlayState()
+ public void TogglePlayState()
{
- switch (Animation.GlobalPlayState)
- {
- case PlayState.Run:
- PlayStateText = "Resume all animations";
- Animation.GlobalPlayState = PlayState.Pause;
- break;
-
- case PlayState.Pause:
- PlayStateText = "Pause all animations";
- Animation.GlobalPlayState = PlayState.Run;
- break;
- }
+ PlayStateText = _isPlaying
+ ? "Resume animations on this page" : "Pause animations on this page";
+ _isPlaying = !_isPlaying;
}
public string PlayStateText
@@ -34,7 +22,5 @@ namespace RenderDemo.ViewModels
get { return _playStateText; }
set { this.RaiseAndSetIfChanged(ref _playStateText, value); }
}
-
- public ReactiveCommand ToggleGlobalPlayState { get; }
}
}
diff --git a/src/Android/Avalonia.Android/AndroidPlatform.cs b/src/Android/Avalonia.Android/AndroidPlatform.cs
index 2b46bfa492..5f0edadf63 100644
--- a/src/Android/Avalonia.Android/AndroidPlatform.cs
+++ b/src/Android/Avalonia.Android/AndroidPlatform.cs
@@ -52,7 +52,8 @@ namespace Avalonia.Android
.Bind().ToTransient()
.Bind().ToConstant(Instance)
.Bind().ToSingleton()
- .Bind().ToConstant(new DefaultRenderLoop(60))
+ .Bind().ToConstant(new DefaultRenderTimer(60))
+ .Bind().ToConstant(new RenderLoop())
.Bind().ToConstant(new AssetLoader(app.GetType().Assembly));
SkiaPlatform.Initialize();
diff --git a/src/Avalonia.Animation/Animatable.cs b/src/Avalonia.Animation/Animatable.cs
index 8a1a17a6fc..516f383b92 100644
--- a/src/Avalonia.Animation/Animatable.cs
+++ b/src/Avalonia.Animation/Animatable.cs
@@ -14,26 +14,14 @@ namespace Avalonia.Animation
/// Base class for all animatable objects.
///
public class Animatable : AvaloniaObject
- {
- ///
- /// Defines the property.
- ///
- public static readonly DirectProperty PlayStateProperty =
- AvaloniaProperty.RegisterDirect(
- nameof(PlayState),
- o => o.PlayState,
- (o, v) => o.PlayState = v);
-
- private PlayState _playState = PlayState.Run;
+ {
+ public static readonly StyledProperty ClockProperty =
+ AvaloniaProperty.Register(nameof(Clock), inherits: true);
- ///
- /// Gets or sets the state of the animation for this
- /// control.
- ///
- public PlayState PlayState
+ public IClock Clock
{
- get { return _playState; }
- set { SetAndRaise(PlayStateProperty, ref _playState, value); }
+ get => GetValue(ClockProperty);
+ set => SetValue(ClockProperty, value);
}
///
@@ -69,9 +57,9 @@ namespace Avalonia.Animation
if (match != null)
{
- match.Apply(this, e.OldValue, e.NewValue);
+ match.Apply(this, Clock ?? Avalonia.Animation.Clock.GlobalClock, e.OldValue, e.NewValue);
}
}
}
}
-}
\ No newline at end of file
+}
diff --git a/src/Avalonia.Animation/Animation.cs b/src/Avalonia.Animation/Animation.cs
index 2c359ecac3..d7efc69e10 100644
--- a/src/Avalonia.Animation/Animation.cs
+++ b/src/Avalonia.Animation/Animation.cs
@@ -17,11 +17,6 @@ namespace Avalonia.Animation
///
public class Animation : AvaloniaList, IAnimation
{
- ///
- /// Gets or sets the animation play state for all animations
- ///
- public static PlayState GlobalPlayState { get; set; } = PlayState.Run;
-
///
/// Gets or sets the active time of this animation.
///
@@ -149,12 +144,12 @@ namespace Avalonia.Animation
}
///
- public IDisposable Apply(Animatable control, IObservable match, Action onComplete)
+ public IDisposable Apply(Animatable control, IClock clock, IObservable match, Action onComplete)
{
var (animators, subscriptions) = InterpretKeyframes(control);
if (animators.Count == 1)
{
- subscriptions.Add(animators[0].Apply(this, control, match, onComplete));
+ subscriptions.Add(animators[0].Apply(this, control, clock, match, onComplete));
}
else
{
@@ -168,7 +163,7 @@ namespace Avalonia.Animation
animatorOnComplete = () => tcs.SetResult(null);
completionTasks.Add(tcs.Task);
}
- subscriptions.Add(animator.Apply(this, control, match, animatorOnComplete));
+ subscriptions.Add(animator.Apply(this, control, clock, match, animatorOnComplete));
}
if (onComplete != null)
@@ -180,7 +175,7 @@ namespace Avalonia.Animation
}
///
- public Task RunAsync(Animatable control)
+ public Task RunAsync(Animatable control, IClock clock = null)
{
var run = new TaskCompletionSource