Force iOS to end editing when pushing a navigation page; fixes #2247 (#2497)

This commit is contained in:
E.Z. Hart 2018-04-24 06:02:28 -06:00 коммит произвёл Rui Marinho
Родитель a7289bd6c0
Коммит e30cc43424
6 изменённых файлов: 90 добавлений и 18 удалений

Просмотреть файл

@ -1,14 +1,14 @@
using System;
using Xamarin.Forms.CustomAttributes;
using Xamarin.Forms.Internals;
using System.Linq;
using System.Threading.Tasks;
using Xamarin.Forms.CustomAttributes;
using Xamarin.Forms.Internals;
namespace Xamarin.Forms.Controls
{
[Preserve(AllMembers = true)]
[Issue(IssueTracker.Bugzilla, 33561, "ListView Pull-to-Refresh ActivityIndicator animation stuck when navigating away and then back again")]
[Issue(IssueTracker.Bugzilla, 33561,
"ListView Pull-to-Refresh ActivityIndicator animation stuck when navigating away and then back again")]
public class Bugzilla33561 : TestTabbedPage
{
public class ListPage : ContentPage
@ -21,7 +21,7 @@ namespace Xamarin.Forms.Controls
var template = new DataTemplate(typeof(TextCell));
template.SetBinding(TextCell.TextProperty, ".");
_listView = new ListView()
_listView = new ListView
{
IsPullToRefreshEnabled = true,
ItemsSource = Enumerable.Range(0, 10).Select(no => $"FAIL {no}"),
@ -29,7 +29,7 @@ namespace Xamarin.Forms.Controls
IsRefreshing = true
};
_listView.Refreshing += async (object sender, EventArgs e) =>
_listView.Refreshing += async (sender, e) =>
{
if (_isRefreshing)
return;
@ -50,8 +50,8 @@ namespace Xamarin.Forms.Controls
protected override void Init()
{
Children.Add(new NavigationPage(new ListPage()) { Title = "page 1" });
Children.Add(new ContentPage() { Title = "page 2" });
Children.Add(new ContentPage() { Title = "page 3" });
Children.Add(new ContentPage { Title = "page 2" });
Children.Add(new ContentPage { Title = "page 3" });
}
}
}

Просмотреть файл

@ -0,0 +1,43 @@
using System.Linq;
using Xamarin.Forms.CustomAttributes;
using Xamarin.Forms.Internals;
namespace Xamarin.Forms.Controls
{
// This test covers the issue reported in https://github.com/xamarin/Xamarin.Forms/issues/2247
// for NavigationBehavior.PushAsync. Coverage for NavigationBehavior.PushModalAsync is provided by Bugzilla33561.
[Preserve(AllMembers = true)]
[Issue(IssueTracker.Github, 2247,
"[iOS] ListView.IsRefreshing not showing activity indicator on iOS", NavigationBehavior.PushAsync)]
public class Issue2247 : TestContentPage
{
ListView _listView;
bool _isRefreshing;
protected override void Init()
{
var instructions = new Label
{
Text = "The ListView on this page should be displaying the 'refreshing' activity indicator."
+ " If it is not, the test has failed"
};
var template = new DataTemplate(typeof(TextCell));
template.SetBinding(TextCell.TextProperty, ".");
_listView = new ListView
{
IsPullToRefreshEnabled = true,
ItemsSource = Enumerable.Range(0, 10).Select(no => $"Item {no}"),
ItemTemplate = template,
IsRefreshing = true
};
Content = new StackLayout
{
Children = { instructions, _listView }
};
}
}
}

Просмотреть файл

@ -238,6 +238,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla59457.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla59580.cs" />
<Compile Include="$(MSBuildThisFileDirectory)GitHub1878.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue2247.cs" />
<Compile Include="$(MSBuildThisFileDirectory)GroupListViewHeaderIndexOutOfRange.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue1975.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue1601.cs" />

Просмотреть файл

@ -125,6 +125,7 @@ namespace Xamarin.Forms.Controls
}
readonly List<IssueModel> _issues;
TableSection _section;
void VerifyNoDuplicates()
{
@ -161,10 +162,6 @@ namespace Xamarin.Forms.Controls
Action = ActivatePageAndNavigate (attribute, typeInfo.AsType ())
}).ToList();
var root = new TableRoot ();
var section = new TableSection ("Bug Repro");
root.Add (section);
VerifyNoDuplicates();
FilterIssues();
@ -196,10 +193,6 @@ namespace Xamarin.Forms.Controls
PageToAction.Clear();
var root = new TableRoot ();
var section = new TableSection ("Bug Repro");
root.Add (section);
var issueCells = Enumerable.Empty<TextCell>();
if (!_filterBugzilla)
@ -234,12 +227,19 @@ namespace Xamarin.Forms.Controls
issueCells = issueCells.Concat(untrackedIssueCells);
}
if (_section != null)
{
Root.Remove(_section);
}
_section = new TableSection("Bug Repro");
foreach (var issueCell in issueCells) {
section.Add (issueCell);
_section.Add (issueCell);
}
Root = root;
Root.Add(_section);
}
// Legacy reasons, do not add to this list

Просмотреть файл

@ -163,6 +163,8 @@ namespace Xamarin.Forms.Platform.iOS
Task INavigation.PushModalAsync(Page modal, bool animated)
{
EndEditing();
_modals.Add(modal);
modal.Platform = this;
@ -476,10 +478,30 @@ namespace Xamarin.Forms.Platform.iOS
// One might wonder why these delays are here... well thats a great question. It turns out iOS will claim the
// presentation is complete before it really is. It does not however inform you when it is really done (and thus
// would be safe to dismiss the VC). Fortunately this is almost never an issue
await _renderer.PresentViewControllerAsync(wrapper, animated);
await Task.Delay(5);
}
void EndEditing()
{
// If any text entry controls have focus, we need to end their editing session
// so that they are not the first responder; if we don't some things (like the activity indicator
// on pull-to-refresh) will not work correctly.
// The topmost modal on the stack will have the Window; we can use that to end any current
// editing that's going on
if (_modals.Count > 0)
{
var uiViewController = GetRenderer(_modals[_modals.Count - 1]) as UIViewController;
uiViewController?.View?.Window?.EndEditing(true);
return;
}
// If there aren't any modals, then the platform renderer will have the Window
_renderer.View?.Window?.EndEditing(true);
}
internal class DefaultRenderer : VisualElementRenderer<VisualElement>
{
public override UIView HitTest(CGPoint point, UIEvent uievent)

Просмотреть файл

@ -4,6 +4,7 @@ using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Threading.Tasks;
using ObjCRuntime;
using UIKit;
using Xamarin.Forms.Internals;
using Xamarin.Forms.PlatformConfiguration.iOSSpecific;
@ -527,6 +528,11 @@ namespace Xamarin.Forms.Platform.iOS
void OnPushRequested(object sender, NavigationRequestedEventArgs e)
{
// If any text entry controls have focus, we need to end their editing session
// so that they are not the first responder; if we don't some things (like the activity indicator
// on pull-to-refresh) will not work correctly.
View?.Window?.EndEditing(true);
e.Task = PushPageAsync(e.Page, e.Animated);
}