Skip to content

Commit

Permalink
fix(animation): not defaulting starting value from animated value
Browse files Browse the repository at this point in the history
  • Loading branch information
Xiaoy312 committed Apr 3, 2023
1 parent e4bada5 commit 60537a3
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 4 deletions.
9 changes: 9 additions & 0 deletions src/Uno.UI/FeatureConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -771,5 +771,14 @@ public static class Cursors
public static bool UseHandForInteraction { get; set; } = true;
#endif
}

public static class Animation
{
/// <summary>
/// Determines if the default animation starting value
/// will be from the animated value or local value, when the From property is omitted.
/// </summary>
public static bool DefaultsStartingValueFromAnimatedValue { get; } = true;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -332,10 +332,55 @@ private static ValueAnimator GetRelativeAnimator(Java.Lang.Object target, string
}

/// <summary>
/// Ensures that scale value is without the android accepted values
/// Ensures that scale value is within the android accepted values
/// </summary>
private static double ToNativeScale(double value)
=> double.IsNaN(value) ? 1 : value;

internal static bool TryGetNativeAnimatedValue(Timeline timeline, out object value)
{
value = null;

if (timeline.GetIsDependantAnimation() || timeline.GetIsDurationZero())
{
return false;
}

var info = timeline.PropertyInfo.GetPathItems().Last();
var target = info.DataContext;
var property = info.PropertyName
.Split(new[] { '.' }).Last()
.Replace("(", "").Replace(")", "");

if (target is Transform { IsAnimating: false })
{
// While not animating, these native properties will be reset.
// In that case, the dp actual value should be read instead (by return false here).
return false;
}

value = property switch
{
nameof(FrameworkElement.Opacity) when target is View view => (double)view.Alpha,
nameof(TranslateTransform.X) when target is TranslateTransform translate => ViewHelper.PhysicalToLogicalPixels(translate.View.TranslationX),
nameof(TranslateTransform.Y) when target is TranslateTransform translate => ViewHelper.PhysicalToLogicalPixels(translate.View.TranslationY),
nameof(RotateTransform.Angle) when target is RotateTransform rotate => (double)rotate.View.Rotation,
nameof(ScaleTransform.ScaleX) when target is ScaleTransform scale => (double)scale.View.ScaleX,
nameof(ScaleTransform.ScaleY) when target is ScaleTransform scale => (double)scale.View.ScaleY,
//nameof(SkewTransform.AngleX) when target is SkewTransform skew => ViewHelper.PhysicalToLogicalPixels(skew.View.ScaleX), // copied as is from GetGPUAnimator
//nameof(SkewTransform.AngleY) when target is SkewTransform skew => ViewHelper.PhysicalToLogicalPixels(skew.View.ScaleY),
nameof(CompositeTransform.TranslateX) when target is CompositeTransform composite => ViewHelper.PhysicalToLogicalPixels(composite.View.TranslationX),
nameof(CompositeTransform.TranslateY) when target is CompositeTransform composite => ViewHelper.PhysicalToLogicalPixels(composite.View.TranslationY),
nameof(CompositeTransform.Rotation) when target is CompositeTransform composite => (double)composite.View.Rotation,
nameof(CompositeTransform.ScaleX) when target is CompositeTransform composite => (double)composite.View.ScaleX,
nameof(CompositeTransform.ScaleY) when target is CompositeTransform composite => (double)composite.View.ScaleY,
//nameof(CompositeTransform.SkewX) when target is CompositeTransform composite => ViewHelper.PhysicalToLogicalPixels(composite.View.ScaleX),
//nameof(CompositeTransform.SkewY) when target is CompositeTransform composite => ViewHelper.PhysicalToLogicalPixels(composite.View.ScaleY),

_ => null,
};

return value != null;
}
}
}
30 changes: 27 additions & 3 deletions src/Uno.UI/UI/Xaml/Media/Animation/Timeline.animation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using Uno.Foundation.Logging;
using Uno.UI.DataBinding;
using System.Diagnostics;
using Uno.UI;

namespace Windows.UI.Xaml.Media.Animation
{
Expand Down Expand Up @@ -69,11 +70,14 @@ private TimelineState State
private BindingPath PropertyInfo => _owner?.PropertyInfo;

private string[] GetTraceProperties() => _owner?.GetTraceProperties();

private void ClearValue() => _owner?.ClearValue();
private void SetValue(object value) => _owner?.SetValue(value);
private bool NeedsRepeat(Stopwatch activeDuration, int replayCount) => _owner?.NeedsRepeat(activeDuration, replayCount) ?? false;
private object GetValue() => _owner?.GetValue();
private object GetNonAnimatedValue() => _owner?.GetNonAnimatedValue();

private bool NeedsRepeat(Stopwatch activeDuration, int replayCount) => _owner?.NeedsRepeat(activeDuration, replayCount) ?? false;

public void Begin()
{
if (_trace.IsEnabled)
Expand Down Expand Up @@ -431,8 +435,9 @@ private T ComputeFromValue()
}
else
{
var value = GetNonAnimatedValue();

var value = FeatureConfiguration.Animation.DefaultsStartingValueFromAnimatedValue
? GetValueCore()
: GetNonAnimatedValue();
if (value != null)
{
return AnimationOwner.Convert(value);
Expand All @@ -442,6 +447,25 @@ private T ComputeFromValue()
return null;
}

private object GetValueCore()
{
#if !__ANDROID__
return GetValue();
#else
// On android, animation may target a native property implementing the behavior instead of the specified dependency property.
// When starting a new animation midst another, in order to continue from the current animated value,
// we need to retrieve the value of that native property, as reading the dp value will just give the final value.
if (AnimatorFactory.TryGetNativeAnimatedValue(_owner, out var value))
{
return value;
}
else
{
return GetValue();
}
#endif
}

/// <summary>
/// Calculates the To value of the animation
/// For simplicity, animations are based on to and from values
Expand Down

0 comments on commit 60537a3

Please sign in to comment.