diff options
author | E.Z. Hart <hartez@users.noreply.github.com> | 2017-03-20 13:09:41 -0600 |
---|---|---|
committer | Rui Marinho <me@ruimarinho.net> | 2017-03-20 19:09:41 +0000 |
commit | 14a740dd5e705f3f5177bcc8c84b1ac51bf70362 (patch) | |
tree | bd7436d6918a245fbb09a4906e1284bbeb64bfde | |
parent | ea4673c8cb3e9155a86abc7e8ae49655ee765d3b (diff) | |
download | xamarin-forms-14a740dd5e705f3f5177bcc8c84b1ac51bf70362.tar.gz xamarin-forms-14a740dd5e705f3f5177bcc8c84b1ac51bf70362.tar.bz2 xamarin-forms-14a740dd5e705f3f5177bcc8c84b1ac51bf70362.zip |
Make Entry completed behavior on UWP/WinRT match Android/iOS (#747)
* Make Entry completed behavior on UWP/WinRT match Android/iOS
* Accessibility test
4 files changed, 121 insertions, 3 deletions
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla45067.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla45067.cs new file mode 100644 index 00000000..c4292fb4 --- /dev/null +++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla45067.cs @@ -0,0 +1,76 @@ +using Xamarin.Forms.CustomAttributes; +using Xamarin.Forms.Internals; + +namespace Xamarin.Forms.Controls.Issues +{ + [Preserve(AllMembers = true)] + [Issue(IssueTracker.Bugzilla, 45067, "[UWP] No way of cleanly dismissing soft keyboard", PlatformAffected.WinRT)] + public class Bugzilla45067 : TestContentPage + { + protected override void Init() + { + var button = new Button { Text = "Start" }; + + button.Clicked += (sender, args) => + { + SwitchMainPage(); + }; + + Content = button; + } + + void SwitchMainPage() + { + Application.Current.MainPage = new _45067Content(); + } + + class _45067Content : TestContentPage + { + protected override void Init() + { + var instructions1 = new Label { Text = "Enter text in the 'Username' Entry, then hit 'Enter/Return' on the soft keyboard. The keyboard should be dismissed." }; + + var instructions2 = new Label { Text = "Enter text in the 'Password' Entry, then hit 'Enter/Return' on the soft keyboard. The keyboard should be dismissed." }; + + var username = new Entry + { + Placeholder = "Username" + }; + + username.SetValue(Accessibility.LabeledByProperty, instructions1); + + var password = new Entry + { + Placeholder = "Password", + IsPassword = true + }; + + password.SetValue(Accessibility.LabeledByProperty, instructions2); + + var button = new Button { Text = "Submit", IsEnabled = false }; + + username.Completed += (s, e) => + { + button.Focus(); + }; + + password.Completed += (s, e) => + { + button.Focus(); + }; + + Content = new StackLayout + { + Children = + { + instructions1, + username, + instructions2, + password, + button + } + }; + } + } + } +}
\ No newline at end of file diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems index d8b688dd..1b060efa 100644 --- a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems +++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems @@ -165,6 +165,7 @@ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla42832.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Bugzilla44044.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Bugzilla44338.cs" /> + <Compile Include="$(MSBuildThisFileDirectory)Bugzilla45067.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Bugzilla45027.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Bugzilla45330.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Bugzilla44955.cs" /> diff --git a/Xamarin.Forms.Platform.WinRT/EntryRenderer.cs b/Xamarin.Forms.Platform.WinRT/EntryRenderer.cs index a02b11cc..06ec6f2b 100644 --- a/Xamarin.Forms.Platform.WinRT/EntryRenderer.cs +++ b/Xamarin.Forms.Platform.WinRT/EntryRenderer.cs @@ -1,8 +1,10 @@ using System; using System.ComponentModel; +using System.Diagnostics; using System.Reflection; using Windows.Foundation.Metadata; using Windows.System; +using Windows.UI.Xaml; using Windows.UI.Xaml.Input; using Windows.UI.Xaml.Media; using Xamarin.Forms.Internals; @@ -111,6 +113,14 @@ namespace Xamarin.Forms.Platform.WinRT if (args?.Key != VirtualKey.Enter) return; +#if WINDOWS_UWP + // Hide the soft keyboard; this matches the behavior of Forms on Android/iOS + Windows.UI.ViewManagement.InputPane.GetForCurrentView().TryHide(); +#else + // WinRT doesn't have TryHide(), so the best we can do is force the control to unfocus + UnfocusControl(Control); +#endif + ((IEntryController)Element).SendCompleted(); } diff --git a/Xamarin.Forms.Platform.WinRT/VisualElementRenderer.cs b/Xamarin.Forms.Platform.WinRT/VisualElementRenderer.cs index 9c3a4c94..e1bf2ef0 100644 --- a/Xamarin.Forms.Platform.WinRT/VisualElementRenderer.cs +++ b/Xamarin.Forms.Platform.WinRT/VisualElementRenderer.cs @@ -6,6 +6,7 @@ using Windows.UI.Xaml; using Windows.UI.Xaml.Automation; using Windows.UI.Xaml.Automation.Peers; using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Media; #if WINDOWS_UWP @@ -25,6 +26,7 @@ namespace Xamarin.Forms.Platform.WinRT bool _disposed; EventHandler<VisualElementChangedEventArgs> _elementChangedHandlers; VisualElementTracker<TElement, TNativeElement> _tracker; + Windows.UI.Xaml.Controls.Page _containingPage; // Cache of containing page used for unfocusing public TNativeElement Control { get; private set; } @@ -477,11 +479,40 @@ namespace Xamarin.Forms.Platform.WinRT internal void UnfocusControl(Control control) { - if (control == null || !control.IsEnabled) + if (control == null || !control.IsEnabled || !control.IsTabStop) return; - control.IsEnabled = false; - control.IsEnabled = true; + // "Unfocusing" doesn't really make sense on Windows; for accessibility reasons, + // something always has focus. So forcing the unfocusing of a control would normally + // just move focus to the next control, or leave it on the current control if no other + // focus targets are available. This is what happens if you use the "disable/enable" + // hack. What we *can* do is set the focus to the Page which contains Control; + // this will cause Control to lose focus without shifting focus to, say, the next Entry + + if (_containingPage == null) + { + // Work our way up the tree to find the containing Page + DependencyObject parent = Control as Control; + while (parent != null && !(parent is Windows.UI.Xaml.Controls.Page)) + { + parent = VisualTreeHelper.GetParent(parent); + } + _containingPage = parent as Windows.UI.Xaml.Controls.Page; + } + + if (_containingPage != null) + { + // Cache the tabstop setting + var wasTabStop = _containingPage.IsTabStop; + + // Controls can only get focus if they're a tabstop + _containingPage.IsTabStop = true; + _containingPage.Focus(FocusState.Programmatic); + + // Restore the tabstop setting; that may cause the Page to lose focus, + // but it won't restore the focus to Control + _containingPage.IsTabStop = wasTabStop; + } } void OnControlGotFocus(object sender, RoutedEventArgs args) |