[iOS] Adjust SearchBar to allow functional Korean text input (#1103)
authorPaul DiPietro <pauldipietro@users.noreply.github.com>
Tue, 5 Dec 2017 17:13:06 +0000 (12:13 -0500)
committerRui Marinho <me@ruimarinho.net>
Tue, 5 Dec 2017 17:13:06 +0000 (17:13 +0000)
Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla51825.cs [new file with mode: 0644]
Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems
Xamarin.Forms.Platform.iOS/Renderers/SearchBarRenderer.cs

diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla51825.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla51825.cs
new file mode 100644 (file)
index 0000000..acd4ba9
--- /dev/null
@@ -0,0 +1,62 @@
+using Xamarin.Forms.CustomAttributes;
+using Xamarin.Forms.Internals;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+#endif
+
+namespace Xamarin.Forms.Controls.Issues
+{
+       [Preserve(AllMembers = true)]
+       [Issue(IssueTracker.Bugzilla, 51825, "[iOS] Korean input in SearchBar doesn't work", PlatformAffected.iOS)]
+       public class Bugzilla51815 : TestContentPage
+       {
+               protected override void Init()
+               {
+                       var sb = new SearchBar { AutomationId = "Bugzilla51825SearchBar" };
+                       var text = new Label { AutomationId = "Bugzilla51825Label" };
+                       sb.TextChanged += (sender, e) =>
+                       {
+                               text.Text = sb.Text;
+                       };
+
+                       Content = new StackLayout
+                       {
+                               Children =
+                               {
+                                       sb,
+                                       new Button
+                                       {
+                                               AutomationId = "Bugzilla51825Button",
+                                               Text = "Change SearchBar text",
+                                               Command = new Command(() =>
+                                               {
+                                                       sb.Text = "Test";
+                                               })
+                                       },
+                                       text,
+                                       new Label
+                                       {
+                                               Text = "The label above should match the text in the SearchBar; " +
+                                                       "additionally, typing Korean characters should properly combine them."
+                                       }
+                               }
+                       };
+               }
+
+#if UITEST
+               [Test]
+               public void Bugzilla51825Test ()
+               {
+                       RunningApp.WaitForElement (q => q.Marked ("Bugzilla51825SearchBar"));
+                       RunningApp.EnterText(q => q.Marked("Bugzilla51825SearchBar"), "Hello");
+                       var entry = RunningApp.Query(q => q.Marked("Bugzilla51825Label"))[0];
+                       Assert.AreEqual("Hello", entry.Text);
+                       RunningApp.Tap("Bugzilla51825Button");
+                       entry = RunningApp.Query(q => q.Marked("Bugzilla51825Label"))[0];
+                       Assert.AreEqual("Test", entry.Text);
+               }
+#endif
+       }
+}
\ No newline at end of file
index 8f7cfcc..6a3ccd0 100644 (file)
     <Compile Include="$(MSBuildThisFileDirectory)ButtonFastRendererTest.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)DesktopSupportTestPage.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Bugzilla58779.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Bugzilla51825.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Bugzilla31688.cs" />
   </ItemGroup>
   <ItemGroup>
index 7a8f09c..654686b 100644 (file)
@@ -14,6 +14,8 @@ namespace Xamarin.Forms.Platform.iOS
                UIColor _defaultTextColor;
                UIColor _defaultTintColor;
                UITextField _textField;
+               bool _textWasTyped;
+               string _typedText;
 
                IElementController ElementController => Element as IElementController;
 
@@ -153,7 +155,11 @@ namespace Xamarin.Forms.Platform.iOS
 
                void OnTextChanged(object sender, UISearchBarTextChangedEventArgs a)
                {
-                       ElementController.SetValueFromRenderer(SearchBar.TextProperty, Control.Text);
+                       // This only fires when text has been typed into the SearchBar; see UpdateText()
+                       // for why this is handled in this manner.
+                       _textWasTyped = true;
+                       _typedText = a.SearchText;
+                       UpdateOnTextChanged();
                }
 
                void UpdateAlignment()
@@ -226,10 +232,24 @@ namespace Xamarin.Forms.Platform.iOS
 
                void UpdateText()
                {
-                       Control.Text = Element.Text;
+                       // There is at least one scenario where modifying the Element's Text value from TextChanged
+                       // can cause issues with a Korean keyboard. The characters normally combine into larger
+                       // characters as they are typed, but if SetValueFromRenderer is used in that manner,
+                       // it ignores the combination and outputs them individually. This hook only fires 
+                       // when typing, so by keeping track of whether or not text was typed, we can respect
+                       // other changes to Element.Text.
+                       if (!_textWasTyped)
+                               Control.Text = Element.Text;
+                       
                        UpdateCancelButton();
                }
 
+               void UpdateOnTextChanged()
+               {
+                       ElementController?.SetValueFromRenderer(SearchBar.TextProperty, _typedText);
+                       _textWasTyped = false;
+               }
+
                void UpdateTextColor()
                {
                        _textField = _textField ?? Control.FindDescendantView<UITextField>();