diff --git a/src/Uno.UI/Microsoft/UI/Xaml/Controls/PullToRefresh/Native/NativeRefreshInfoProviderAdapter.cs b/src/Uno.UI/Microsoft/UI/Xaml/Controls/PullToRefresh/Native/NativeRefreshInfoProviderAdapter.cs index 304f871c57b9..ebc22f249f36 100644 --- a/src/Uno.UI/Microsoft/UI/Xaml/Controls/PullToRefresh/Native/NativeRefreshInfoProviderAdapter.cs +++ b/src/Uno.UI/Microsoft/UI/Xaml/Controls/PullToRefresh/Native/NativeRefreshInfoProviderAdapter.cs @@ -37,7 +37,7 @@ private void OnRefreshCompleted(IRefreshInfoProvider sender, object args) public void SetAnimations(UIElement refreshVisualizerAnimatableContainer) { // TODO: Make visible - //refreshVisualizerAnimatableContainer.Visibility = Visibility.Collapsed; + refreshVisualizerAnimatableContainer.Visibility = Visibility.Collapsed; } public void Dispose() diff --git a/src/Uno.UI/Microsoft/UI/Xaml/Controls/PullToRefresh/Native/RefreshContainer.iOS.cs b/src/Uno.UI/Microsoft/UI/Xaml/Controls/PullToRefresh/Native/RefreshContainer.iOS.cs index 5fbc62891702..730094e68c69 100644 --- a/src/Uno.UI/Microsoft/UI/Xaml/Controls/PullToRefresh/Native/RefreshContainer.iOS.cs +++ b/src/Uno.UI/Microsoft/UI/Xaml/Controls/PullToRefresh/Native/RefreshContainer.iOS.cs @@ -11,6 +11,7 @@ using Windows.Foundation; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Media; namespace Microsoft.UI.Xaml.Controls; @@ -18,17 +19,22 @@ public partial class RefreshContainer : ContentControl { private readonly SerialDisposable _refreshSubscription = new SerialDisposable(); private readonly SerialDisposable _nativeScrollViewAttachment = new SerialDisposable(); - private NativeRefreshControl _refreshControl = null!; + private NativeRefreshControl? _refreshControl = null; private UIScrollView? _ownerScrollView = null; partial void InitializePlatformPartial() { - this.Loaded += OnLoaded; - this.Unloaded += OnUnloaded; + Loaded += OnLoaded; + Unloaded += OnUnloaded; } internal void RequestRefreshPlatform() { + if (_refreshControl is null) + { + return; + } + if (!_refreshControl.Refreshing) { _refreshControl.BeginRefreshing(); @@ -38,19 +44,23 @@ internal void RequestRefreshPlatform() } } - private void OnLoaded(object sender, RoutedEventArgs e) => InitializeRefreshControl(); - - private void OnUnloaded(object sender, RoutedEventArgs e) + private void OnLoaded(object sender, RoutedEventArgs e) { - _refreshControl.EndRefreshing(); - _refreshSubscription.Disposable = null; + InitializeRefreshControl(); + OnRefreshVisualizerChangedPartial(); } - private void OnRefreshControlValueChanged(object? sender, EventArgs e) => OnNativeRefreshingChanged(); + private void OnUnloaded(object sender, RoutedEventArgs e) => CleanupRefreshControl(); - private bool IsNativeRefreshing => _refreshControl.Refreshing; + private void OnRefreshControlValueChanged(object? sender, EventArgs e) => OnNativeRefreshingChanged(); - internal void EndNativeRefreshing() => _refreshControl.EndRefreshing(); + internal void EndNativeRefreshing() + { + if (_refreshControl is not null) + { + _refreshControl.EndRefreshing(); + } + } private void InitializeRefreshControl() { @@ -72,10 +82,19 @@ private void InitializeRefreshControl() _refreshSubscription.Disposable = Disposable.Create(() => _refreshControl.ValueChanged -= OnRefreshControlValueChanged); } + private void CleanupRefreshControl() + { + if (_refreshControl is not null) + { + _refreshControl.EndRefreshing(); + _refreshSubscription.Disposable = null; + } + } + protected override void OnContentChanged(object oldValue, object newValue) { base.OnContentChanged(oldValue, newValue); - + _nativeScrollViewAttachment.Disposable = null; AttachToNativeScrollView(); @@ -83,6 +102,11 @@ protected override void OnContentChanged(object oldValue, object newValue) private void AttachToNativeScrollView() { + if (_refreshControl is null) + { + return; + } + // Inject the UIRefreshControl into the first scrollable element found in the hierarchy if (this.FindFirstChild() is { } scrollView) { @@ -121,33 +145,42 @@ private void AttachToNativeScrollView() } scrollView.AlwaysBounceVertical = originalBounceSetting; }); - } + } } private SerialDisposable _refreshVisualizerSubscriptions = new SerialDisposable(); - + partial void OnRefreshVisualizerChangedPartial() { _refreshVisualizerSubscriptions.Disposable = null; - if (Visualizer is null) + + if (_refreshControl is null || Visualizer is null) { return; } + var visualizer = Visualizer; - if (visualizer is NativeRefreshVisualizer) + var compositeDisposable = new CompositeDisposable(); + compositeDisposable.Add(visualizer.RegisterDisposablePropertyChangedCallback(RefreshVisualizer.ForegroundProperty, OnVisualizerPropertyChanged)); + compositeDisposable.Add(visualizer.RegisterDisposablePropertyChangedCallback(RefreshVisualizer.BackgroundProperty, OnVisualizerPropertyChanged)); + _refreshVisualizerSubscriptions.Disposable = compositeDisposable; + } + + private void OnVisualizerPropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args) + { + if (_refreshControl is null || Visualizer is not { } visualizer) + { + return; + } + + if (visualizer.Foreground is SolidColorBrush foregroundBrush) { - InitializeRefreshControl(); + _refreshControl.TintColor = foregroundBrush.ColorWithOpacity; } - else + + if (visualizer.Background is SolidColorBrush backgroundBrush) { - var subviews = _refreshControl.Subviews.ToArray(); - foreach (var subview in subviews) - { - subview.RemoveFromSuperview(); - } - _refreshControl.AddSubview(visualizer); - visualizer.Bounds = _refreshControl.Bounds; - _refreshVisualizerSubscriptions.Disposable = Disposable.Create(() => visualizer.RemoveFromSuperview()); + _refreshControl.BackgroundColor = backgroundBrush.ColorWithOpacity; } } }