Make Entry completed behavior on UWP/WinRT match Android/iOS (#747)

* Make Entry completed behavior on UWP/WinRT match Android/iOS

* Accessibility test
This commit is contained in:
E.Z. Hart 2017-03-20 13:09:41 -06:00 коммит произвёл Rui Marinho
Родитель ea4673c8cb
Коммит 14a740dd5e
4 изменённых файлов: 121 добавлений и 3 удалений

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

@ -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
}
};
}
}
}
}

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

@ -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" />

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

@ -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();
}

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

@ -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)