Skip to content

Commit 5ae33d1

Browse files
committed
RefreshView: add new internal property IsRefreshAllowed to fix xamarin#14350
Platform renderers can use IsRefreshAllowed to disable swipe to refresh in a controlled fashion - letting any pending refresh/command finish first to avoid that ongoing refresh indication is stopped prematurely (even if the refresh command is still executing).
1 parent 941e797 commit 5ae33d1

File tree

4 files changed

+37
-6
lines changed

4 files changed

+37
-6
lines changed

Xamarin.Forms.Core/RefreshView.cs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.ComponentModel;
23
using System.Runtime.CompilerServices;
34
using System.Windows.Input;
45
using Xamarin.Forms.Platform;
@@ -49,6 +50,9 @@ static object OnIsRefreshingPropertyCoerced(BindableObject bindable, object valu
4950
if (!view.IsEnabled)
5051
return false;
5152

53+
if (!view.IsRefreshAllowed)
54+
return false;
55+
5256
if (view.Command == null)
5357
return value;
5458

@@ -98,12 +102,22 @@ public object CommandParameter
98102
set { SetValue(CommandParameterProperty, value); }
99103
}
100104

105+
public static readonly BindableProperty IsRefreshAllowedProperty =
106+
BindableProperty.Create(nameof(IsRefreshAllowed), typeof(bool), typeof(RefreshView), false, BindingMode.TwoWay);
107+
108+
[EditorBrowsable(EditorBrowsableState.Never)]
109+
public bool IsRefreshAllowed
110+
{
111+
get { return (bool)GetValue(IsRefreshAllowedProperty); }
112+
set { SetValue(IsRefreshAllowedProperty, value); }
113+
}
114+
101115
void RefreshCommandCanExecuteChanged(object sender, EventArgs eventArgs)
102116
{
103117
if (Command != null)
104-
SetValueCore(IsEnabledProperty, Command.CanExecute(CommandParameter));
118+
SetValueCore(IsRefreshAllowedProperty, Command.CanExecute(CommandParameter));
105119
else
106-
SetValueCore(IsEnabledProperty, true);
120+
SetValueCore(IsRefreshAllowedProperty, true);
107121
}
108122

109123
public static readonly BindableProperty RefreshColorProperty =

Xamarin.Forms.Platform.Android/Renderers/RefreshViewRenderer.cs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ public override bool Refreshing
5757
RefreshView.SetValueFromRenderer(RefreshView.IsRefreshingProperty, _refreshing);
5858

5959
base.Refreshing = _refreshing;
60+
61+
// Allow to disable SwipeToRefresh layout AFTER refresh is done
62+
UpdateIsEnabled();
6063
}
6164
}
6265

@@ -140,8 +143,16 @@ void UpdateColors()
140143
}
141144

142145
void UpdateIsRefreshing() => Refreshing = RefreshView.IsRefreshing;
143-
144-
void UpdateIsEnabled() => SwipeRefreshLayout.Enabled = RefreshView.IsEnabled;
146+
147+
void UpdateIsEnabled()
148+
{
149+
// NOTE: only disable while NOT refreshing, otherwise Command bindings CanExecute behavior will effectively
150+
// cancel refresh animation. If not possible right now we will be called by UpdateIsRefreshing().
151+
// For details see https://github.com/xamarin/Xamarin.Forms/issues/14350
152+
var isEnabled = RefreshView.IsEnabled && RefreshView.IsRefreshAllowed;
153+
if (isEnabled || !SwipeRefreshLayout.Refreshing)
154+
SwipeRefreshLayout.Enabled = isEnabled;
155+
}
145156

146157
bool CanScrollUp(AView view)
147158
{
@@ -207,6 +218,8 @@ void HandlePropertyChanged(object sender, PropertyChangedEventArgs e)
207218
UpdateContent();
208219
else if (e.PropertyName == VisualElement.IsEnabledProperty.PropertyName)
209220
UpdateIsEnabled();
221+
else if (e.PropertyName == RefreshView.IsRefreshAllowedProperty.PropertyName)
222+
UpdateIsEnabled();
210223
else if (e.PropertyName == RefreshView.IsRefreshingProperty.PropertyName)
211224
UpdateIsRefreshing();
212225
else if (e.IsOneOf(RefreshView.RefreshColorProperty, VisualElement.BackgroundColorProperty, VisualElement.BackgroundProperty))

Xamarin.Forms.Platform.UAP/RefreshViewRenderer.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ protected override void OnElementPropertyChanged(object sender, PropertyChangedE
105105
UpdateContent();
106106
else if (e.PropertyName == VisualElement.IsEnabledProperty.PropertyName)
107107
UpdateIsEnabled();
108+
else if (e.PropertyName == RefreshView.IsRefreshAllowedProperty.PropertyName)
109+
UpdateIsEnabled();
108110
else if (e.PropertyName == RefreshView.IsRefreshingProperty.PropertyName)
109111
UpdateIsRefreshing();
110112
else if (e.PropertyName == RefreshView.RefreshColorProperty.PropertyName)
@@ -135,7 +137,7 @@ void UpdateContent()
135137

136138
void UpdateIsEnabled()
137139
{
138-
Control.IsEnabled = Element.IsEnabled;
140+
Control.IsEnabled = Element.IsEnabled && Element.IsRefreshAllowed;
139141
}
140142

141143
void UpdateIsRefreshing()

Xamarin.Forms.Platform.iOS/Renderers/RefreshViewRenderer.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ protected override void OnElementPropertyChanged(object sender, PropertyChangedE
8181

8282
if (e.PropertyName == VisualElement.IsEnabledProperty.PropertyName)
8383
UpdateIsEnabled();
84+
else if (e.PropertyName == RefreshView.IsRefreshAllowedProperty.PropertyName)
85+
UpdateIsEnabled();
8486
else if (e.PropertyName == RefreshView.IsRefreshingProperty.PropertyName)
8587
UpdateIsRefreshing();
8688
else if (e.IsOneOf(RefreshView.RefreshColorProperty, VisualElement.BackgroundColorProperty))
@@ -252,7 +254,7 @@ void UpdateIsRefreshing()
252254

253255
void UpdateIsEnabled()
254256
{
255-
bool isRefreshViewEnabled = Element.IsEnabled;
257+
bool isRefreshViewEnabled = Element.IsEnabled && Element.IsRefreshAllowed;
256258
_refreshControl.Enabled = isRefreshViewEnabled;
257259

258260
UserInteractionEnabled = true;

0 commit comments

Comments
 (0)