|
|
@ -1,4 +1,5 @@ |
|
|
using System; |
|
|
using System; |
|
|
|
|
|
using System.Numerics; |
|
|
using System.Reactive.Linq; |
|
|
using System.Reactive.Linq; |
|
|
using System.Threading; |
|
|
using System.Threading; |
|
|
using Avalonia.Animation; |
|
|
using Avalonia.Animation; |
|
|
@ -7,25 +8,24 @@ using Avalonia.Controls.PullToRefresh; |
|
|
using Avalonia.Input; |
|
|
using Avalonia.Input; |
|
|
using Avalonia.Interactivity; |
|
|
using Avalonia.Interactivity; |
|
|
using Avalonia.Media; |
|
|
using Avalonia.Media; |
|
|
|
|
|
using Avalonia.Rendering.Composition; |
|
|
|
|
|
|
|
|
namespace Avalonia.Controls |
|
|
namespace Avalonia.Controls |
|
|
{ |
|
|
{ |
|
|
public class RefreshVisualizer : ContentControl |
|
|
public class RefreshVisualizer : ContentControl |
|
|
{ |
|
|
{ |
|
|
private const int DefaultIndicatorSize = 24; |
|
|
private const int DefaultIndicatorSize = 24; |
|
|
private const double MinimumIndicatorOpacity = 0.4; |
|
|
private const float MinimumIndicatorOpacity = 0.4f; |
|
|
private const string ArrowPathData = "M18.6195264,3.31842271 C19.0080059,3.31842271 19.3290603,3.60710385 19.3798716,3.9816481 L19.3868766,4.08577298 L19.3868766,6.97963208 C19.3868766,7.36811161 19.0981955,7.68916605 18.7236513,7.73997735 L18.6195264,7.74698235 L15.7256673,7.74698235 C15.3018714,7.74698235 14.958317,7.40342793 14.958317,6.97963208 C14.958317,6.59115255 15.2469981,6.27009811 15.6215424,6.21928681 L15.7256673,6.21228181 L16.7044011,6.21182461 C13.7917384,3.87107476 9.52212532,4.05209336 6.81933829,6.75488039 C3.92253872,9.65167996 3.92253872,14.34832 6.81933829,17.2451196 C9.71613786,20.1419192 14.4127779,20.1419192 17.3095775,17.2451196 C19.0725398,15.4821573 19.8106555,12.9925923 19.3476248,10.58925 C19.2674502,10.173107 19.5398064,9.77076216 19.9559494,9.69058758 C20.3720923,9.610413 20.7744372,9.88276918 20.8546118,10.2989121 C21.4129973,13.1971899 20.5217103,16.2033812 18.3947747,18.3303168 C14.8986373,21.8264542 9.23027854,21.8264542 5.73414113,18.3303168 C2.23800371,14.8341794 2.23800371,9.16582064 5.73414113,5.66968323 C9.05475132,2.34907304 14.3349409,2.18235834 17.8523166,5.16953912 L17.8521761,4.08577298 C17.8521761,3.66197713 18.1957305,3.31842271 18.6195264,3.31842271 Z"; |
|
|
private const string ArrowPathData = "M18.6195264,3.31842271 C19.0080059,3.31842271 19.3290603,3.60710385 19.3798716,3.9816481 L19.3868766,4.08577298 L19.3868766,6.97963208 C19.3868766,7.36811161 19.0981955,7.68916605 18.7236513,7.73997735 L18.6195264,7.74698235 L15.7256673,7.74698235 C15.3018714,7.74698235 14.958317,7.40342793 14.958317,6.97963208 C14.958317,6.59115255 15.2469981,6.27009811 15.6215424,6.21928681 L15.7256673,6.21228181 L16.7044011,6.21182461 C13.7917384,3.87107476 9.52212532,4.05209336 6.81933829,6.75488039 C3.92253872,9.65167996 3.92253872,14.34832 6.81933829,17.2451196 C9.71613786,20.1419192 14.4127779,20.1419192 17.3095775,17.2451196 C19.0725398,15.4821573 19.8106555,12.9925923 19.3476248,10.58925 C19.2674502,10.173107 19.5398064,9.77076216 19.9559494,9.69058758 C20.3720923,9.610413 20.7744372,9.88276918 20.8546118,10.2989121 C21.4129973,13.1971899 20.5217103,16.2033812 18.3947747,18.3303168 C14.8986373,21.8264542 9.23027854,21.8264542 5.73414113,18.3303168 C2.23800371,14.8341794 2.23800371,9.16582064 5.73414113,5.66968323 C9.05475132,2.34907304 14.3349409,2.18235834 17.8523166,5.16953912 L17.8521761,4.08577298 C17.8521761,3.66197713 18.1957305,3.31842271 18.6195264,3.31842271 Z"; |
|
|
private double _executingRatio = 0.8; |
|
|
private double _executingRatio = 0.8; |
|
|
|
|
|
|
|
|
private RotateTransform _visualizerRotateTransform; |
|
|
|
|
|
private TranslateTransform _contentTranslateTransform; |
|
|
|
|
|
private RefreshVisualizerState _refreshVisualizerState; |
|
|
private RefreshVisualizerState _refreshVisualizerState; |
|
|
private RefreshInfoProvider _refreshInfoProvider; |
|
|
private RefreshInfoProvider? _refreshInfoProvider; |
|
|
private IDisposable _isInteractingSubscription; |
|
|
private IDisposable? _isInteractingSubscription; |
|
|
private IDisposable _interactionRatioSubscription; |
|
|
private IDisposable? _interactionRatioSubscription; |
|
|
private bool _isInteractingForRefresh; |
|
|
private bool _isInteractingForRefresh; |
|
|
private Grid? _root; |
|
|
private Grid? _root; |
|
|
private Control _content; |
|
|
private Control? _content; |
|
|
private RefreshVisualizerOrientation _orientation; |
|
|
private RefreshVisualizerOrientation _orientation; |
|
|
private float _startingRotationAngle; |
|
|
private float _startingRotationAngle; |
|
|
private double _interactionRatio; |
|
|
private double _interactionRatio; |
|
|
@ -46,9 +46,11 @@ namespace Avalonia.Controls |
|
|
AvaloniaProperty.RegisterDirect<RefreshVisualizer, RefreshVisualizerOrientation>(nameof(Orientation), |
|
|
AvaloniaProperty.RegisterDirect<RefreshVisualizer, RefreshVisualizerOrientation>(nameof(Orientation), |
|
|
s => s.Orientation, (s, o) => s.Orientation = o); |
|
|
s => s.Orientation, (s, o) => s.Orientation = o); |
|
|
|
|
|
|
|
|
public DirectProperty<RefreshVisualizer, RefreshInfoProvider> RefreshInfoProviderProperty = |
|
|
public DirectProperty<RefreshVisualizer, RefreshInfoProvider?> RefreshInfoProviderProperty = |
|
|
AvaloniaProperty.RegisterDirect<RefreshVisualizer, RefreshInfoProvider>(nameof(RefreshInfoProvider), |
|
|
AvaloniaProperty.RegisterDirect<RefreshVisualizer, RefreshInfoProvider?>(nameof(RefreshInfoProvider), |
|
|
s => s.RefreshInfoProvider, (s, o) => s.RefreshInfoProvider = o); |
|
|
s => s.RefreshInfoProvider, (s, o) => s.RefreshInfoProvider = o); |
|
|
|
|
|
private Vector3 _defaultOffset; |
|
|
|
|
|
private bool _played; |
|
|
|
|
|
|
|
|
public RefreshVisualizerState RefreshVisualizerState |
|
|
public RefreshVisualizerState RefreshVisualizerState |
|
|
{ |
|
|
{ |
|
|
@ -88,7 +90,7 @@ namespace Avalonia.Controls |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public RefreshInfoProvider RefreshInfoProvider |
|
|
public RefreshInfoProvider? RefreshInfoProvider |
|
|
{ |
|
|
{ |
|
|
get => _refreshInfoProvider; internal set |
|
|
get => _refreshInfoProvider; internal set |
|
|
{ |
|
|
{ |
|
|
@ -106,20 +108,17 @@ namespace Avalonia.Controls |
|
|
remove => RemoveHandler(RefreshRequestedEvent, value); |
|
|
remove => RemoveHandler(RefreshRequestedEvent, value); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public RefreshVisualizer() |
|
|
|
|
|
{ |
|
|
|
|
|
_visualizerRotateTransform = new RotateTransform(); |
|
|
|
|
|
_contentTranslateTransform = new TranslateTransform(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
protected override void OnApplyTemplate(TemplateAppliedEventArgs e) |
|
|
protected override void OnApplyTemplate(TemplateAppliedEventArgs e) |
|
|
{ |
|
|
{ |
|
|
base.OnApplyTemplate(e); |
|
|
base.OnApplyTemplate(e); |
|
|
|
|
|
|
|
|
|
|
|
this.ClipToBounds = false; |
|
|
|
|
|
|
|
|
_root = e.NameScope.Find<Grid>("PART_Root"); |
|
|
_root = e.NameScope.Find<Grid>("PART_Root"); |
|
|
|
|
|
|
|
|
if (_root != null) |
|
|
if (_root != null) |
|
|
{ |
|
|
{ |
|
|
|
|
|
_content = Content as Control; |
|
|
if (_content == null) |
|
|
if (_content == null) |
|
|
{ |
|
|
{ |
|
|
Content = new PathIcon() |
|
|
Content = new PathIcon() |
|
|
@ -140,69 +139,113 @@ namespace Avalonia.Controls |
|
|
UpdateContent(); |
|
|
UpdateContent(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e) |
|
|
|
|
|
{ |
|
|
|
|
|
base.OnAttachedToVisualTree(e); |
|
|
|
|
|
|
|
|
|
|
|
UpdateContent(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
private void UpdateContent() |
|
|
private void UpdateContent() |
|
|
{ |
|
|
{ |
|
|
if (_content != null) |
|
|
if (_content != null && _root != null) |
|
|
{ |
|
|
{ |
|
|
switch (RefreshVisualizerState) |
|
|
var root = _root; |
|
|
|
|
|
var visual = _refreshInfoProvider?.Visual; |
|
|
|
|
|
var contentVisual = ElementComposition.GetElementVisual(_content); |
|
|
|
|
|
var visualizerVisual = ElementComposition.GetElementVisual(this); |
|
|
|
|
|
if (visual != null && contentVisual != null && visualizerVisual != null) |
|
|
{ |
|
|
{ |
|
|
case RefreshVisualizerState.Idle: |
|
|
contentVisual.CenterPoint = new Vector3((float)(_content.Bounds.Width / 2), (float)(_content.Bounds.Height / 2), 0); |
|
|
_content.Classes.Remove("refreshing"); |
|
|
switch (RefreshVisualizerState) |
|
|
_root.Classes.Remove("pending"); |
|
|
{ |
|
|
_content.RenderTransform = _visualizerRotateTransform; |
|
|
case RefreshVisualizerState.Idle: |
|
|
_content.Opacity = MinimumIndicatorOpacity; |
|
|
_played = false; |
|
|
_visualizerRotateTransform.Angle = _startingRotationAngle; |
|
|
contentVisual.Opacity = MinimumIndicatorOpacity; |
|
|
_contentTranslateTransform.X = 0; |
|
|
contentVisual.RotationAngle = (float)(_startingRotationAngle * Math.PI / 180f); |
|
|
_contentTranslateTransform.Y = 0; |
|
|
visualizerVisual.Offset = IsPullDirectionVertical ? |
|
|
break; |
|
|
new Vector3(visualizerVisual.Offset.X, 0, 0) : |
|
|
case RefreshVisualizerState.Interacting: |
|
|
new Vector3(0, visualizerVisual.Offset.Y, 0); |
|
|
_content.Classes.Remove("refreshing"); |
|
|
contentVisual.Scale = new Vector3(0.9f, 0.9f, 0.9f); |
|
|
_root.Classes.Remove("pending"); |
|
|
visual.Offset = default; |
|
|
_content.RenderTransform = _visualizerRotateTransform; |
|
|
break; |
|
|
_content.Opacity = MinimumIndicatorOpacity; |
|
|
case RefreshVisualizerState.Interacting: |
|
|
_visualizerRotateTransform.Angle = _startingRotationAngle + (_interactionRatio * 360); |
|
|
_played = false; |
|
|
_content.Height = DefaultIndicatorSize; |
|
|
contentVisual.Opacity = MinimumIndicatorOpacity; |
|
|
_content.Width = DefaultIndicatorSize; |
|
|
contentVisual.RotationAngle = (float)((_startingRotationAngle + (_interactionRatio * 360)) * Math.PI / 180f); |
|
|
if (IsPullDirectionVertical) |
|
|
Vector3 offset = default; |
|
|
{ |
|
|
if (IsPullDirectionVertical) |
|
|
_contentTranslateTransform.X = 0; |
|
|
{ |
|
|
_contentTranslateTransform.Y = _interactionRatio * (IsPullDirectionFar ? -1 : 1) * _root.Bounds.Height; |
|
|
offset = new Vector3(0, (float)(_interactionRatio * (IsPullDirectionFar ? -1 : 1) * root.Bounds.Height), 0); |
|
|
} |
|
|
} |
|
|
else |
|
|
else |
|
|
{ |
|
|
{ |
|
|
_contentTranslateTransform.Y = 0; |
|
|
offset = new Vector3((float)(_interactionRatio * (IsPullDirectionFar ? -1 : 1) * root.Bounds.Width), 0, 0); |
|
|
_contentTranslateTransform.X = _interactionRatio * (IsPullDirectionFar ? -1 : 1) * _root.Bounds.Width; |
|
|
} |
|
|
} |
|
|
visual.Offset = offset; |
|
|
break; |
|
|
visualizerVisual.Offset = IsPullDirectionVertical ? |
|
|
case RefreshVisualizerState.Pending: |
|
|
new Vector3(visualizerVisual.Offset.X, offset.Y, 0) : |
|
|
_content.Classes.Remove("refreshing"); |
|
|
new Vector3(offset.X, visualizerVisual.Offset.Y, 0); |
|
|
_content.Opacity = 1; |
|
|
contentVisual.Scale = new Vector3(0.9f, 0.9f, 0.9f); |
|
|
_content.RenderTransform = _visualizerRotateTransform; |
|
|
break; |
|
|
if (IsPullDirectionVertical) |
|
|
case RefreshVisualizerState.Pending: |
|
|
{ |
|
|
contentVisual.Opacity = 1; |
|
|
_contentTranslateTransform.X = 0; |
|
|
contentVisual.RotationAngle = (float)((_startingRotationAngle + 360) * Math.PI / 180f); |
|
|
_contentTranslateTransform.Y = _interactionRatio * (IsPullDirectionFar ? -1 : 1) * _root.Bounds.Height; |
|
|
if (IsPullDirectionVertical) |
|
|
} |
|
|
{ |
|
|
else |
|
|
offset = new Vector3(0, (float)(_interactionRatio * (IsPullDirectionFar ? -1 : 1) * root.Bounds.Height), 0); |
|
|
{ |
|
|
} |
|
|
_contentTranslateTransform.Y = 0; |
|
|
else |
|
|
_contentTranslateTransform.X = _interactionRatio * (IsPullDirectionFar ? -1 : 1) * _root.Bounds.Width; |
|
|
{ |
|
|
} |
|
|
offset = new Vector3((float)(_interactionRatio * (IsPullDirectionFar ? -1 : 1) * root.Bounds.Width), 0, 0); |
|
|
|
|
|
} |
|
|
_root.Classes.Add("pending"); |
|
|
visual.Offset = offset; |
|
|
break; |
|
|
visualizerVisual.Offset = IsPullDirectionVertical ? |
|
|
case RefreshVisualizerState.Refreshing: |
|
|
new Vector3(visualizerVisual.Offset.X, offset.Y, 0) : |
|
|
_root.Classes.Remove("pending"); |
|
|
new Vector3(offset.X, visualizerVisual.Offset.Y, 0); |
|
|
_content.Classes.Add("refreshing"); |
|
|
|
|
|
_content.Opacity = 1; |
|
|
if (!_played) |
|
|
_content.Height = DefaultIndicatorSize; |
|
|
{ |
|
|
_content.Width = DefaultIndicatorSize; |
|
|
_played = true; |
|
|
break; |
|
|
var scaleAnimation = contentVisual.Compositor!.CreateVector3KeyFrameAnimation(); |
|
|
case RefreshVisualizerState.Peeking: |
|
|
scaleAnimation.Target = "Scale"; |
|
|
_root.Classes.Remove("pending"); |
|
|
scaleAnimation.InsertKeyFrame(0.5f, new Vector3(1.5f, 1.5f, 1)); |
|
|
_content.Opacity = 1; |
|
|
scaleAnimation.InsertKeyFrame(1f, new Vector3(1f, 1f, 1)); |
|
|
_visualizerRotateTransform.Angle += _startingRotationAngle; |
|
|
scaleAnimation.Duration = TimeSpan.FromSeconds(0.3); |
|
|
break; |
|
|
|
|
|
|
|
|
contentVisual.StartAnimation("Scale", scaleAnimation); |
|
|
|
|
|
} |
|
|
|
|
|
break; |
|
|
|
|
|
case RefreshVisualizerState.Refreshing: |
|
|
|
|
|
var rotateAnimation = contentVisual.Compositor!.CreateScalarKeyFrameAnimation(); |
|
|
|
|
|
rotateAnimation.Target = "RotationAngle"; |
|
|
|
|
|
rotateAnimation.InsertKeyFrame(0, (float)(0)); |
|
|
|
|
|
rotateAnimation.InsertKeyFrame(0.5f, (float)(Math.PI)); |
|
|
|
|
|
rotateAnimation.InsertKeyFrame(1, (float)(2 * Math.PI)); |
|
|
|
|
|
rotateAnimation.Duration = TimeSpan.FromSeconds(1); |
|
|
|
|
|
rotateAnimation.IterationCount = 1000; |
|
|
|
|
|
|
|
|
|
|
|
contentVisual.StartAnimation("RotationAngle", rotateAnimation); |
|
|
|
|
|
contentVisual.Opacity = 1; |
|
|
|
|
|
contentVisual.Scale = new Vector3(0.9f, 0.9f, 0.9f); |
|
|
|
|
|
if (IsPullDirectionVertical) |
|
|
|
|
|
{ |
|
|
|
|
|
offset = new Vector3(0, (float)(_executingRatio * (IsPullDirectionFar ? -1 : 1) * root.Bounds.Height), 0); |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
{ |
|
|
|
|
|
offset = new Vector3((float)(_executingRatio * (IsPullDirectionFar ? -1 : 1) * root.Bounds.Width), 0, 0); |
|
|
|
|
|
} |
|
|
|
|
|
visual.Offset = offset; |
|
|
|
|
|
visualizerVisual.Offset = IsPullDirectionVertical ? |
|
|
|
|
|
new Vector3(visualizerVisual.Offset.X, offset.Y, 0) : |
|
|
|
|
|
new Vector3(offset.X, visualizerVisual.Offset.Y, 0); |
|
|
|
|
|
break; |
|
|
|
|
|
case RefreshVisualizerState.Peeking: |
|
|
|
|
|
contentVisual.Opacity = 1; |
|
|
|
|
|
contentVisual.RotationAngle = (float)(_startingRotationAngle * Math.PI / 180f); |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
@ -254,12 +297,6 @@ namespace Avalonia.Controls |
|
|
Width = DefaultIndicatorSize |
|
|
Width = DefaultIndicatorSize |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
var transformGroup = new TransformGroup(); |
|
|
|
|
|
transformGroup.Children.Add(_visualizerRotateTransform); |
|
|
|
|
|
|
|
|
|
|
|
_content.RenderTransform = _visualizerRotateTransform; |
|
|
|
|
|
_root.RenderTransform = _contentTranslateTransform; |
|
|
|
|
|
|
|
|
|
|
|
var transition = new Transitions |
|
|
var transition = new Transitions |
|
|
{ |
|
|
{ |
|
|
new DoubleTransition() |
|
|
new DoubleTransition() |
|
|
@ -270,16 +307,42 @@ namespace Avalonia.Controls |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
_content.Transitions = transition; |
|
|
_content.Transitions = transition; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var scalingGrid = new Grid(); |
|
|
_content.Loaded += (s, e) => |
|
|
scalingGrid.VerticalAlignment = Layout.VerticalAlignment.Center; |
|
|
{ |
|
|
scalingGrid.HorizontalAlignment = Layout.HorizontalAlignment.Center; |
|
|
var composition = ElementComposition.GetElementVisual(_content); |
|
|
scalingGrid.RenderTransform = new ScaleTransform(); |
|
|
var compositor = composition!.Compositor; |
|
|
|
|
|
composition.Opacity = 0; |
|
|
scalingGrid.Children.Add(_content); |
|
|
|
|
|
|
|
|
var smoothRotationAnimation |
|
|
|
|
|
= compositor.CreateScalarKeyFrameAnimation(); |
|
|
|
|
|
smoothRotationAnimation.Target = "RotationAngle"; |
|
|
|
|
|
smoothRotationAnimation.InsertExpressionKeyFrame(1.0f, "this.FinalValue"); |
|
|
|
|
|
smoothRotationAnimation.Duration = TimeSpan.FromMilliseconds(100); |
|
|
|
|
|
|
|
|
|
|
|
var offsetAnimation = compositor.CreateVector3KeyFrameAnimation(); |
|
|
|
|
|
offsetAnimation.Target = "Offset"; |
|
|
|
|
|
offsetAnimation.InsertExpressionKeyFrame(1.0f, "this.FinalValue"); |
|
|
|
|
|
offsetAnimation.Duration = TimeSpan.FromMilliseconds(150); |
|
|
|
|
|
|
|
|
|
|
|
var scaleAnimation |
|
|
|
|
|
= compositor.CreateVector3KeyFrameAnimation(); |
|
|
|
|
|
scaleAnimation.Target = "Scale"; |
|
|
|
|
|
scaleAnimation.InsertExpressionKeyFrame(1.0f, "this.FinalValue"); |
|
|
|
|
|
scaleAnimation.Duration = TimeSpan.FromMilliseconds(100); |
|
|
|
|
|
|
|
|
|
|
|
var animation = compositor.CreateImplicitAnimationCollection(); |
|
|
|
|
|
animation["RotationAngle"] = smoothRotationAnimation; |
|
|
|
|
|
animation["Offset"] = offsetAnimation; |
|
|
|
|
|
animation["Scale"] = scaleAnimation; |
|
|
|
|
|
|
|
|
|
|
|
composition.ImplicitAnimations = animation; |
|
|
|
|
|
|
|
|
|
|
|
UpdateContent(); |
|
|
|
|
|
}; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
_root.Children.Insert(0, scalingGrid); |
|
|
_root.Children.Add(_content); |
|
|
_content.VerticalAlignment = Layout.VerticalAlignment.Center; |
|
|
_content.VerticalAlignment = Layout.VerticalAlignment.Center; |
|
|
_content.HorizontalAlignment = Layout.HorizontalAlignment.Center; |
|
|
_content.HorizontalAlignment = Layout.HorizontalAlignment.Center; |
|
|
} |
|
|
} |
|
|
@ -294,25 +357,23 @@ namespace Avalonia.Controls |
|
|
} |
|
|
} |
|
|
else if (change.Property == BoundsProperty) |
|
|
else if (change.Property == BoundsProperty) |
|
|
{ |
|
|
{ |
|
|
if (_content != null) |
|
|
switch (PullDirection) |
|
|
{ |
|
|
{ |
|
|
var parent = _content.Parent as Control; |
|
|
case PullDirection.TopToBottom: |
|
|
switch (PullDirection) |
|
|
RenderTransform = new TranslateTransform(0, -Bounds.Height); |
|
|
{ |
|
|
break; |
|
|
case PullDirection.TopToBottom: |
|
|
case PullDirection.BottomToTop: |
|
|
parent.Margin = new Thickness(0, -Bounds.Height - DefaultIndicatorSize - (0.5 * DefaultIndicatorSize), 0, 0); |
|
|
RenderTransform = new TranslateTransform(0, Bounds.Height); |
|
|
break; |
|
|
break; |
|
|
case PullDirection.BottomToTop: |
|
|
case PullDirection.LeftToRight: |
|
|
parent.Margin = new Thickness(0, 0, 0, -Bounds.Height - DefaultIndicatorSize - (0.5 * DefaultIndicatorSize)); |
|
|
RenderTransform = new TranslateTransform(-Bounds.Width, 0); |
|
|
break; |
|
|
break; |
|
|
case PullDirection.LeftToRight: |
|
|
case PullDirection.RightToLeft: |
|
|
parent.Margin = new Thickness(-Bounds.Width - DefaultIndicatorSize - (0.5 * DefaultIndicatorSize), 0, 0, 0); |
|
|
RenderTransform = new TranslateTransform(Bounds.Width, 0); |
|
|
break; |
|
|
break; |
|
|
case PullDirection.RightToLeft: |
|
|
|
|
|
parent.Margin = new Thickness(0, 0, -Bounds.Width - DefaultIndicatorSize - (0.5 * DefaultIndicatorSize), 0); |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
UpdateContent(); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -354,16 +415,15 @@ namespace Avalonia.Controls |
|
|
_interactionRatioSubscription?.Dispose(); |
|
|
_interactionRatioSubscription?.Dispose(); |
|
|
_interactionRatioSubscription = null; |
|
|
_interactionRatioSubscription = null; |
|
|
|
|
|
|
|
|
if (_refreshInfoProvider != null) |
|
|
if (RefreshInfoProvider != null) |
|
|
{ |
|
|
{ |
|
|
_isInteractingSubscription = _refreshInfoProvider.GetObservable(RefreshInfoProvider.IsInteractingForRefreshProperty) |
|
|
_isInteractingSubscription = RefreshInfoProvider.GetObservable(RefreshInfoProvider.IsInteractingForRefreshProperty) |
|
|
.Subscribe(InteractingForRefreshObserver); |
|
|
.Subscribe(InteractingForRefreshObserver); |
|
|
|
|
|
|
|
|
_interactionRatioSubscription = _refreshInfoProvider.GetObservable(RefreshInfoProvider.InteractionRatioProperty) |
|
|
_interactionRatioSubscription = RefreshInfoProvider.GetObservable(RefreshInfoProvider.InteractionRatioProperty) |
|
|
.Subscribe(InteractionRatioObserver); |
|
|
.Subscribe(InteractionRatioObserver); |
|
|
|
|
|
|
|
|
var visual = _refreshInfoProvider.Visual; |
|
|
var visual = RefreshInfoProvider.Visual; |
|
|
visual.RenderTransform = _contentTranslateTransform; |
|
|
|
|
|
|
|
|
|
|
|
_executingRatio = RefreshInfoProvider.ExecutionRatio; |
|
|
_executingRatio = RefreshInfoProvider.ExecutionRatio; |
|
|
} |
|
|
} |
|
|
|