From 5e2c75fb08dee97dea2aa6c043095509ee9f3e3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Burak=20Kaan=20K=C3=B6se?= Date: Fri, 12 Mar 2021 01:43:21 +0100 Subject: [PATCH 01/48] Base code for handlers. --- src/Core/src/Core/ITextInput.cs | 5 +++++ src/Core/src/Handlers/Entry/EntryHandler.Android.cs | 5 +++++ src/Core/src/Handlers/Entry/EntryHandler.Standard.cs | 1 + src/Core/src/Handlers/Entry/EntryHandler.cs | 3 ++- src/Core/src/Handlers/Entry/EntryHandler.iOS.cs | 5 +++++ 5 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/Core/src/Core/ITextInput.cs b/src/Core/src/Core/ITextInput.cs index c8a269041e9c..33c0c2575243 100644 --- a/src/Core/src/Core/ITextInput.cs +++ b/src/Core/src/Core/ITextInput.cs @@ -19,5 +19,10 @@ public interface ITextInput : IText /// Gets a value indicating whether or not the view is read-only. /// bool IsReadOnly { get; } + + /// + /// Gets the keyboard type for the given input control. + /// + Keyboard Keyboard{ get; } } } \ No newline at end of file diff --git a/src/Core/src/Handlers/Entry/EntryHandler.Android.cs b/src/Core/src/Handlers/Entry/EntryHandler.Android.cs index e75eb9d414ba..c1dc8368993f 100644 --- a/src/Core/src/Handlers/Entry/EntryHandler.Android.cs +++ b/src/Core/src/Handlers/Entry/EntryHandler.Android.cs @@ -63,6 +63,11 @@ public static void MapIsReadOnly(EntryHandler handler, IEntry entry) handler.TypedNativeView?.UpdateIsReadOnly(entry); } + public static void MapKeyboard(EntryHandler handler, IEntry entry) + { + handler.TypedNativeView?.UpdateKeyboard(entry); + } + void OnTextChanged(string? text) { if (VirtualView == null || TypedNativeView == null) diff --git a/src/Core/src/Handlers/Entry/EntryHandler.Standard.cs b/src/Core/src/Handlers/Entry/EntryHandler.Standard.cs index 8a57d80761ca..ef3927ba62f4 100644 --- a/src/Core/src/Handlers/Entry/EntryHandler.Standard.cs +++ b/src/Core/src/Handlers/Entry/EntryHandler.Standard.cs @@ -12,5 +12,6 @@ public static void MapIsPassword(IViewHandler handler, IEntry entry) { } public static void MapIsTextPredictionEnabled(IViewHandler handler, IEntry entry) { } public static void MapPlaceholder(IViewHandler handler, IEntry entry) { } public static void MapIsReadOnly(IViewHandler handler, IEntry entry) { } + public static void MapKeyboard(IViewHandler handler, IEntry entry) { } } } \ No newline at end of file diff --git a/src/Core/src/Handlers/Entry/EntryHandler.cs b/src/Core/src/Handlers/Entry/EntryHandler.cs index 95a7515bdca8..0091cc64f813 100644 --- a/src/Core/src/Handlers/Entry/EntryHandler.cs +++ b/src/Core/src/Handlers/Entry/EntryHandler.cs @@ -9,7 +9,8 @@ public partial class EntryHandler [nameof(IEntry.IsPassword)] = MapIsPassword, [nameof(IEntry.IsTextPredictionEnabled)] = MapIsTextPredictionEnabled, [nameof(IEntry.Placeholder)] = MapPlaceholder, - [nameof(IEntry.IsReadOnly)] = MapIsReadOnly + [nameof(IEntry.IsReadOnly)] = MapIsReadOnly, + [nameof(IEntry.IsReadOnly)] = MapKeyboard }; public EntryHandler() : base(EntryMapper) diff --git a/src/Core/src/Handlers/Entry/EntryHandler.iOS.cs b/src/Core/src/Handlers/Entry/EntryHandler.iOS.cs index 8043df913f2e..0770fd51032c 100644 --- a/src/Core/src/Handlers/Entry/EntryHandler.iOS.cs +++ b/src/Core/src/Handlers/Entry/EntryHandler.iOS.cs @@ -71,6 +71,11 @@ public static void MapIsReadOnly(EntryHandler handler, IEntry entry) handler.TypedNativeView?.UpdateIsReadOnly(entry); } + public static void MapKeyboard(EntryHandler handler, IEntry entry) + { + handler.TypedNativeView?.UpdateKeyboard(entry); + } + void OnEditingChanged(object? sender, EventArgs e) => OnTextChanged(); void OnEditingEnded(object? sender, EventArgs e) => OnTextChanged(); From c53ac07385f6edd3ac7bca262935cf88382a9fcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Burak=20Kaan=20K=C3=B6se?= Date: Fri, 12 Mar 2021 01:43:53 +0100 Subject: [PATCH 02/48] Platform specific extension parts in the handlers and partially implementing Android handler. --- .../src/Platform/Android/EntryExtensions.cs | 60 +++++++++--- .../Platform/Android/KeyboardExtensions.cs | 94 +++++++++++++++++++ src/Core/src/Platform/iOS/EntryExtensions.cs | 5 + 3 files changed, 148 insertions(+), 11 deletions(-) create mode 100644 src/Core/src/Platform/Android/KeyboardExtensions.cs diff --git a/src/Core/src/Platform/Android/EntryExtensions.cs b/src/Core/src/Platform/Android/EntryExtensions.cs index ce2fbeb938bc..5d2a0f2beb5e 100644 --- a/src/Core/src/Platform/Android/EntryExtensions.cs +++ b/src/Core/src/Platform/Android/EntryExtensions.cs @@ -1,6 +1,8 @@ using Android.Content.Res; using Android.Text; +using Android.Text.Method; using Android.Widget; +using Microsoft.Maui.Platform.Android; namespace Microsoft.Maui { @@ -46,20 +48,43 @@ public static void UpdateIsPassword(this EditText editText, IEntry entry) internal static void SetInputType(this EditText editText, IEntry entry) { - editText.InputType = InputTypes.ClassText; - editText.InputType |= InputTypes.TextFlagMultiLine; + if (entry.IsReadOnly) + editText.InputType = InputTypes.Null; + else + { + var keyboard = entry.Keyboard; + var nativeInputTypeToUpdate = keyboard.ToInputType(); - if (entry.IsPassword && ((editText.InputType & InputTypes.ClassText) == InputTypes.ClassText)) - editText.InputType |= InputTypes.TextVariationPassword; + if (!(keyboard is CustomKeyboard)) + { + // TODO: IsSpellCheckEnabled handling must be here. - if (entry.IsPassword && ((editText.InputType & InputTypes.ClassNumber) == InputTypes.ClassNumber)) - editText.InputType |= InputTypes.NumberVariationPassword; + if ((nativeInputTypeToUpdate & InputTypes.TextFlagNoSuggestions) != InputTypes.TextFlagNoSuggestions) + { + if (!entry.IsTextPredictionEnabled) + nativeInputTypeToUpdate = nativeInputTypeToUpdate | InputTypes.TextFlagNoSuggestions; + } + } - if (!entry.IsTextPredictionEnabled && ((editText.InputType & InputTypes.TextFlagNoSuggestions) != InputTypes.TextFlagNoSuggestions)) - editText.InputType |= InputTypes.TextFlagNoSuggestions; - - if (entry.IsReadOnly) - editText.InputType = InputTypes.Null; + if (keyboard == Keyboard.Numeric) + { + // editText.KeyListener = GetDigitsKeyListener(editText.InputType); + } + + if (entry.IsPassword) + { + if (((nativeInputTypeToUpdate & InputTypes.ClassText) == InputTypes.ClassText)) + nativeInputTypeToUpdate = nativeInputTypeToUpdate | InputTypes.TextVariationPassword; + + if (((nativeInputTypeToUpdate & InputTypes.ClassNumber) == InputTypes.ClassNumber)) + nativeInputTypeToUpdate = nativeInputTypeToUpdate | InputTypes.NumberVariationPassword; + } + + if (!entry.IsTextPredictionEnabled && ((nativeInputTypeToUpdate & InputTypes.TextFlagNoSuggestions) != InputTypes.TextFlagNoSuggestions)) + nativeInputTypeToUpdate |= InputTypes.TextFlagNoSuggestions; + + editText.InputType = nativeInputTypeToUpdate; + } } public static void UpdateIsTextPredictionEnabled(this EditText editText, IEntry entry) @@ -67,6 +92,11 @@ public static void UpdateIsTextPredictionEnabled(this EditText editText, IEntry editText.SetInputType(entry); } + public static void UpdateKeyboard(this EditText editText, IEntry entry) + { + editText.SetInputType(entry); + } + public static void UpdatePlaceholder(this EditText editText, IEntry entry) { if (editText.Hint == entry.Placeholder) @@ -84,5 +114,13 @@ public static void UpdateIsReadOnly(this EditText editText, IEntry entry) editText.FocusableInTouchMode = isEditable; editText.Focusable = isEditable; } + + //protected virtual NumberKeyListener GetDigitsKeyListener(InputTypes inputTypes) + //{ + // // Override this in a custom renderer to use a different NumberKeyListener + // // or to filter out input types you don't want to allow + // // (e.g., inputTypes &= ~InputTypes.NumberFlagSigned to disallow the sign) + // return LocalizedDigitsKeyListener.Create(inputTypes); + //} } } diff --git a/src/Core/src/Platform/Android/KeyboardExtensions.cs b/src/Core/src/Platform/Android/KeyboardExtensions.cs new file mode 100644 index 000000000000..639c8b48fcb1 --- /dev/null +++ b/src/Core/src/Platform/Android/KeyboardExtensions.cs @@ -0,0 +1,94 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Android.Text; + +namespace Microsoft.Maui.Platform.Android +{ + public static class KeyboardExtensions + { + public static InputTypes ToInputType(this Keyboard self) + { + var result = new InputTypes(); + + // ClassText: !autocaps, spellcheck, suggestions + // TextFlagNoSuggestions: !autocaps, !spellcheck, !suggestions + // InputTypes.ClassText | InputTypes.TextFlagCapSentences autocaps, spellcheck, suggestions + // InputTypes.ClassText | InputTypes.TextFlagCapSentences | InputTypes.TextFlagNoSuggestions; autocaps, !spellcheck, !suggestions + + if (self == Keyboard.Default) + result = InputTypes.ClassText | InputTypes.TextVariationNormal; + else if (self == Keyboard.Chat) + result = InputTypes.ClassText | InputTypes.TextFlagCapSentences | InputTypes.TextFlagNoSuggestions; + else if (self == Keyboard.Email) + result = InputTypes.ClassText | InputTypes.TextVariationEmailAddress; + else if (self == Keyboard.Numeric) + result = InputTypes.ClassNumber | InputTypes.NumberFlagDecimal | InputTypes.NumberFlagSigned; + else if (self == Keyboard.Telephone) + result = InputTypes.ClassPhone; + else if (self == Keyboard.Text) + result = InputTypes.ClassText | InputTypes.TextFlagCapSentences; + else if (self == Keyboard.Url) + result = InputTypes.ClassText | InputTypes.TextVariationUri; + else if (self is CustomKeyboard) + { + var custom = (CustomKeyboard)self; + var capitalizedSentenceEnabled = (custom.Flags & KeyboardFlags.CapitalizeSentence) == KeyboardFlags.CapitalizeSentence; + var capitalizedWordsEnabled = (custom.Flags & KeyboardFlags.CapitalizeWord) == KeyboardFlags.CapitalizeWord; + var capitalizedCharacterEnabled = (custom.Flags & KeyboardFlags.CapitalizeCharacter) == KeyboardFlags.CapitalizeCharacter; + + var spellcheckEnabled = (custom.Flags & KeyboardFlags.Spellcheck) == KeyboardFlags.Spellcheck; + var suggestionsEnabled = (custom.Flags & KeyboardFlags.Suggestions) == KeyboardFlags.Suggestions; + + if (!capitalizedSentenceEnabled && !spellcheckEnabled && !suggestionsEnabled) + result = InputTypes.ClassText | InputTypes.TextFlagNoSuggestions; + + if (!capitalizedSentenceEnabled && !spellcheckEnabled && suggestionsEnabled) + { + // Due to the nature of android, TextFlagAutoCorrect includes Spellcheck + // Log.Warning(null, "On Android, KeyboardFlags.Suggestions enables KeyboardFlags.Spellcheck as well due to a platform limitation."); + result = InputTypes.ClassText | InputTypes.TextFlagAutoCorrect; + } + + if (!capitalizedSentenceEnabled && spellcheckEnabled && !suggestionsEnabled) + result = InputTypes.ClassText | InputTypes.TextFlagAutoComplete; + + if (!capitalizedSentenceEnabled && spellcheckEnabled && suggestionsEnabled) + result = InputTypes.ClassText | InputTypes.TextFlagAutoCorrect; + + if (capitalizedSentenceEnabled && !spellcheckEnabled && !suggestionsEnabled) + result = InputTypes.ClassText | InputTypes.TextFlagCapSentences | InputTypes.TextFlagNoSuggestions; + + if (capitalizedSentenceEnabled && !spellcheckEnabled && suggestionsEnabled) + { + // Due to the nature of android, TextFlagAutoCorrect includes Spellcheck + // Log.Warning(null, "On Android, KeyboardFlags.Suggestions enables KeyboardFlags.Spellcheck as well due to a platform limitation."); + result = InputTypes.ClassText | InputTypes.TextFlagCapSentences | InputTypes.TextFlagAutoCorrect; + } + + if (capitalizedSentenceEnabled && spellcheckEnabled && !suggestionsEnabled) + result = InputTypes.ClassText | InputTypes.TextFlagCapSentences | InputTypes.TextFlagAutoComplete; + + if (capitalizedSentenceEnabled && spellcheckEnabled && suggestionsEnabled) + result = InputTypes.ClassText | InputTypes.TextFlagCapSentences | InputTypes.TextFlagAutoCorrect; + + // All existed before these settings. This ensures these changes are backwards compatible + // without this check TextFlagCapCharacters would win + if (custom.Flags != KeyboardFlags.All) + { + if (capitalizedWordsEnabled) + result = result | InputTypes.TextFlagCapWords; + + if (capitalizedCharacterEnabled) + result = result | InputTypes.TextFlagCapCharacters; + } + } + else + { + // Should never happens + result = InputTypes.TextVariationNormal; + } + return result; + } + } +} diff --git a/src/Core/src/Platform/iOS/EntryExtensions.cs b/src/Core/src/Platform/iOS/EntryExtensions.cs index e10c92c18b4f..fecf1fc39802 100644 --- a/src/Core/src/Platform/iOS/EntryExtensions.cs +++ b/src/Core/src/Platform/iOS/EntryExtensions.cs @@ -55,5 +55,10 @@ public static void UpdateIsReadOnly(this UITextField textField, IEntry entry) { textField.UserInteractionEnabled = !entry.IsReadOnly; } + + public static void UpdateKeyboard(this UITextField textField, IEntry entry) + { + // TODO + } } } \ No newline at end of file From 84d43aa2af7a9b2c671d776005d02c73de465101 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Burak=20Kaan=20K=C3=B6se?= Date: Fri, 12 Mar 2021 01:44:40 +0100 Subject: [PATCH 03/48] Test code in sample for numeric keyboard input type. --- src/Controls/samples/Controls.Sample/Pages/MainPage.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Controls/samples/Controls.Sample/Pages/MainPage.cs b/src/Controls/samples/Controls.Sample/Pages/MainPage.cs index 2bfec77fbf7b..2f85ebb050f7 100644 --- a/src/Controls/samples/Controls.Sample/Pages/MainPage.cs +++ b/src/Controls/samples/Controls.Sample/Pages/MainPage.cs @@ -35,6 +35,12 @@ void SetupMauiLayout() verticalStack.Add(new Label { Text = "This should be a CUSTOM font!", FontFamily = "Dokdo" }); verticalStack.Add(new Label { Text = "This should have padding", Padding = new Thickness(40), BackgroundColor = Color.LightBlue }); + var passwordEntry = new Entry() { IsPassword = true }; + var numericEntry = new Entry() { Keyboard = Keyboard.Numeric }; + + verticalStack.Add(passwordEntry); + verticalStack.Add(numericEntry); + var button = new Button() { Text = _viewModel.Text, WidthRequest = 200 }; var button2 = new Button() { From ab7c3f75098ab3df33a623b4f386fadd7502185b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Burak=20Kaan=20K=C3=B6se?= Date: Sat, 13 Mar 2021 03:33:50 +0100 Subject: [PATCH 04/48] iOS Handler port. --- src/Core/src/Platform/iOS/EntryExtensions.cs | 8 +- .../src/Platform/iOS/KeyboardExtensions.cs | 79 +++++++++++++++++++ 2 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 src/Core/src/Platform/iOS/KeyboardExtensions.cs diff --git a/src/Core/src/Platform/iOS/EntryExtensions.cs b/src/Core/src/Platform/iOS/EntryExtensions.cs index fecf1fc39802..8ba63b6eae03 100644 --- a/src/Core/src/Platform/iOS/EntryExtensions.cs +++ b/src/Core/src/Platform/iOS/EntryExtensions.cs @@ -1,4 +1,5 @@ -using UIKit; +using Microsoft.Maui.Platform.iOS; +using UIKit; namespace Microsoft.Maui { @@ -58,7 +59,10 @@ public static void UpdateIsReadOnly(this UITextField textField, IEntry entry) public static void UpdateKeyboard(this UITextField textField, IEntry entry) { - // TODO + var keyboard = entry.Keyboard; + + textField.ApplyKeyboard(keyboard); + textField.ReloadInputViews(); } } } \ No newline at end of file diff --git a/src/Core/src/Platform/iOS/KeyboardExtensions.cs b/src/Core/src/Platform/iOS/KeyboardExtensions.cs new file mode 100644 index 000000000000..53fa83450ceb --- /dev/null +++ b/src/Core/src/Platform/iOS/KeyboardExtensions.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; +using System.Text; +using UIKit; + +namespace Microsoft.Maui.Platform.iOS +{ + public static class KeyboardExtensions + { + public static void ApplyKeyboard(this IUITextInput textInput, Keyboard keyboard) + { + if (textInput is IUITextInputTraits traits) + ApplyKeyboard(traits, keyboard); + } + + public static void ApplyKeyboard(this IUITextInputTraits textInput, Keyboard keyboard) + { + textInput.AutocapitalizationType = UITextAutocapitalizationType.None; + textInput.AutocorrectionType = UITextAutocorrectionType.No; + textInput.SpellCheckingType = UITextSpellCheckingType.No; + textInput.KeyboardType = UIKeyboardType.Default; + + if (keyboard == Keyboard.Default) + { + textInput.AutocapitalizationType = UITextAutocapitalizationType.Sentences; + textInput.AutocorrectionType = UITextAutocorrectionType.Default; + textInput.SpellCheckingType = UITextSpellCheckingType.Default; + } + else if (keyboard == Keyboard.Chat) + { + textInput.AutocapitalizationType = UITextAutocapitalizationType.Sentences; + textInput.AutocorrectionType = UITextAutocorrectionType.Yes; + } + else if (keyboard == Keyboard.Email) + textInput.KeyboardType = UIKeyboardType.EmailAddress; + else if (keyboard == Keyboard.Numeric) + textInput.KeyboardType = UIKeyboardType.DecimalPad; + else if (keyboard == Keyboard.Telephone) + textInput.KeyboardType = UIKeyboardType.PhonePad; + else if (keyboard == Keyboard.Text) + { + textInput.AutocapitalizationType = UITextAutocapitalizationType.Sentences; + textInput.AutocorrectionType = UITextAutocorrectionType.Yes; + textInput.SpellCheckingType = UITextSpellCheckingType.Yes; + } + else if (keyboard == Keyboard.Url) + textInput.KeyboardType = UIKeyboardType.Url; + else if (keyboard is CustomKeyboard) + { + var custom = (CustomKeyboard)keyboard; + + var capitalizedSentenceEnabled = (custom.Flags & KeyboardFlags.CapitalizeSentence) == KeyboardFlags.CapitalizeSentence; + var capitalizedWordsEnabled = (custom.Flags & KeyboardFlags.CapitalizeWord) == KeyboardFlags.CapitalizeWord; + var capitalizedCharacterEnabled = (custom.Flags & KeyboardFlags.CapitalizeCharacter) == KeyboardFlags.CapitalizeCharacter; + var capitalizedNone = (custom.Flags & KeyboardFlags.None) == KeyboardFlags.None; + + var spellcheckEnabled = (custom.Flags & KeyboardFlags.Spellcheck) == KeyboardFlags.Spellcheck; + var suggestionsEnabled = (custom.Flags & KeyboardFlags.Suggestions) == KeyboardFlags.Suggestions; + + + UITextAutocapitalizationType capSettings = UITextAutocapitalizationType.None; + + // Sentence being first ensures that the behavior of ALL is backwards compatible + if (capitalizedSentenceEnabled) + capSettings = UITextAutocapitalizationType.Sentences; + else if (capitalizedWordsEnabled) + capSettings = UITextAutocapitalizationType.Words; + else if (capitalizedCharacterEnabled) + capSettings = UITextAutocapitalizationType.AllCharacters; + else if (capitalizedNone) + capSettings = UITextAutocapitalizationType.None; + + textInput.AutocapitalizationType = capSettings; + textInput.AutocorrectionType = suggestionsEnabled ? UITextAutocorrectionType.Yes : UITextAutocorrectionType.No; + textInput.SpellCheckingType = spellcheckEnabled ? UITextSpellCheckingType.Yes : UITextSpellCheckingType.No; + } + } + } +} From 505020de2a67ec6e1968619741c3d1950f0f1d43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Burak=20Kaan=20K=C3=B6se?= Date: Sat, 13 Mar 2021 03:37:06 +0100 Subject: [PATCH 05/48] KeyListener implementation for Android handler. --- .../src/Platform/Android/EntryExtensions.cs | 20 +- .../Android/LocalizedDigitsKeyListener.cs | 224 ++++++++++++++++++ 2 files changed, 229 insertions(+), 15 deletions(-) create mode 100644 src/Core/src/Platform/Android/LocalizedDigitsKeyListener.cs diff --git a/src/Core/src/Platform/Android/EntryExtensions.cs b/src/Core/src/Platform/Android/EntryExtensions.cs index 5d2a0f2beb5e..1d3ff52bbdbd 100644 --- a/src/Core/src/Platform/Android/EntryExtensions.cs +++ b/src/Core/src/Platform/Android/EntryExtensions.cs @@ -1,4 +1,5 @@ using Android.Content.Res; +using Android.OS; using Android.Text; using Android.Text.Method; using Android.Widget; @@ -62,27 +63,24 @@ internal static void SetInputType(this EditText editText, IEntry entry) if ((nativeInputTypeToUpdate & InputTypes.TextFlagNoSuggestions) != InputTypes.TextFlagNoSuggestions) { if (!entry.IsTextPredictionEnabled) - nativeInputTypeToUpdate = nativeInputTypeToUpdate | InputTypes.TextFlagNoSuggestions; + nativeInputTypeToUpdate |= InputTypes.TextFlagNoSuggestions; } } if (keyboard == Keyboard.Numeric) { - // editText.KeyListener = GetDigitsKeyListener(editText.InputType); + editText.KeyListener = LocalizedDigitsKeyListener.Create(editText.InputType); } if (entry.IsPassword) { if (((nativeInputTypeToUpdate & InputTypes.ClassText) == InputTypes.ClassText)) - nativeInputTypeToUpdate = nativeInputTypeToUpdate | InputTypes.TextVariationPassword; + nativeInputTypeToUpdate |= InputTypes.TextVariationPassword; if (((nativeInputTypeToUpdate & InputTypes.ClassNumber) == InputTypes.ClassNumber)) - nativeInputTypeToUpdate = nativeInputTypeToUpdate | InputTypes.NumberVariationPassword; + nativeInputTypeToUpdate |= InputTypes.NumberVariationPassword; } - if (!entry.IsTextPredictionEnabled && ((nativeInputTypeToUpdate & InputTypes.TextFlagNoSuggestions) != InputTypes.TextFlagNoSuggestions)) - nativeInputTypeToUpdate |= InputTypes.TextFlagNoSuggestions; - editText.InputType = nativeInputTypeToUpdate; } } @@ -114,13 +112,5 @@ public static void UpdateIsReadOnly(this EditText editText, IEntry entry) editText.FocusableInTouchMode = isEditable; editText.Focusable = isEditable; } - - //protected virtual NumberKeyListener GetDigitsKeyListener(InputTypes inputTypes) - //{ - // // Override this in a custom renderer to use a different NumberKeyListener - // // or to filter out input types you don't want to allow - // // (e.g., inputTypes &= ~InputTypes.NumberFlagSigned to disallow the sign) - // return LocalizedDigitsKeyListener.Create(inputTypes); - //} } } diff --git a/src/Core/src/Platform/Android/LocalizedDigitsKeyListener.cs b/src/Core/src/Platform/Android/LocalizedDigitsKeyListener.cs new file mode 100644 index 000000000000..c537fc3ac6b9 --- /dev/null +++ b/src/Core/src/Platform/Android/LocalizedDigitsKeyListener.cs @@ -0,0 +1,224 @@ +using System.Collections.Generic; +using Android.Text; +using Android.Text.Method; +using Java.Lang; +using Java.Text; + +namespace Microsoft.Maui.Platform.Android +{ + internal class LocalizedDigitsKeyListener : NumberKeyListener + { + readonly char _decimalSeparator; + + // I'm not aware of a situation/locale where this would need to be something different, + // but we'll make it easy to localize the sign in the future just in case + const char SignCharacter = '-'; + + static Dictionary? s_unsignedCache; + static Dictionary? s_signedCache; + + static char GetDecimalSeparator() + { + if (!(NumberFormat.Instance is DecimalFormat format)) + return '.'; + + + DecimalFormatSymbols? sym = format.DecimalFormatSymbols; + + return sym == null ? '.' : sym.DecimalSeparator; + } + + public static NumberKeyListener Create(InputTypes inputTypes) + { + if ((inputTypes & InputTypes.NumberFlagDecimal) == 0) + { + // If decimal isn't allowed, we can just use the Android version +#pragma warning disable 0618 + return DigitsKeyListener.GetInstance(inputTypes.HasFlag(InputTypes.NumberFlagSigned), false); +#pragma warning restore 0618 + } + + // Figure out what the decimal separator is for the current locale + char decimalSeparator = GetDecimalSeparator(); + + if (decimalSeparator == '.') + { + // If it's '.', then we can just use the default Android version +#pragma warning disable 0618 + return DigitsKeyListener.GetInstance(inputTypes.HasFlag(InputTypes.NumberFlagSigned), true); +#pragma warning restore 0618 + } + + // If decimals are enabled and the locale's decimal separator is not '.' + // (which is hard-coded in the Android DigitKeyListener), then use + // our custom one with a configurable decimal separator + return GetInstance(inputTypes, decimalSeparator); + } + + public static LocalizedDigitsKeyListener GetInstance(InputTypes inputTypes, char decimalSeparator) + { + if (s_signedCache == null) + s_signedCache = new Dictionary(); + + if ((inputTypes & InputTypes.NumberFlagSigned) != 0) + { + return GetInstance(inputTypes, decimalSeparator, ref s_signedCache); + } + + if (s_unsignedCache == null) + s_unsignedCache = new Dictionary(); + + return GetInstance(inputTypes, decimalSeparator, ref s_unsignedCache); + } + + static LocalizedDigitsKeyListener GetInstance(InputTypes inputTypes, char decimalSeparator, ref Dictionary cache) + { + if (cache == null) + { + cache = new Dictionary(1); + } + + if (!cache.ContainsKey(decimalSeparator)) + { + cache.Add(decimalSeparator, new LocalizedDigitsKeyListener(inputTypes, decimalSeparator)); + } + + return cache[decimalSeparator]; + } + + protected LocalizedDigitsKeyListener(InputTypes inputTypes, char decimalSeparator) + + { + _decimalSeparator = decimalSeparator; + InputType = inputTypes; + } + + public override InputTypes InputType { get; } + + char[]? _acceptedChars; + + protected override char[] GetAcceptedChars() + { + if ((InputType & InputTypes.NumberFlagSigned) == 0) + { + return _acceptedChars ?? + (_acceptedChars = new[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', _decimalSeparator }); + } + + return _acceptedChars ?? + (_acceptedChars = new[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', SignCharacter, _decimalSeparator }); + } + + static bool IsSignChar(char c) + { + return c == SignCharacter; + } + + bool IsDecimalPointChar(char c) + { + return c == _decimalSeparator; + } + +#pragma warning disable CS8602 // Dereference of a possibly null reference. + public override ICharSequence? FilterFormatted(ICharSequence? source, int start, int end, ISpanned? dest, int dstart, int dend) + { + // Borrowed heavily from the Android source + ICharSequence? filterFormatted = base.FilterFormatted(source, start, end, dest, dstart, dend); + + if (filterFormatted != null) + { + source = filterFormatted; + start = 0; + end = filterFormatted.Length(); + } + + int sign = -1; + int dec = -1; + + int dlen = dest.Length(); + + + // Find out if the existing text has a sign or decimal point characters. + for (var i = 0; i < dstart; i++) + { + char c = dest.CharAt(i); + if (IsSignChar(c)) + { + sign = i; + } + else if (IsDecimalPointChar(c)) + { + dec = i; + } + } + + for (int i = dend; i < dlen; i++) + { + char c = dest.CharAt(i); + if (IsSignChar(c)) + { + return new String(""); // Nothing can be inserted in front of a sign character. + } + + if (IsDecimalPointChar(c)) + { + dec = i; + } + } + + // If it does, we must strip them out from the source. + // In addition, a sign character must be the very first character, + // and nothing can be inserted before an existing sign character. + // Go in reverse order so the offsets are stable. + SpannableStringBuilder? stripped = null; + for (int i = end - 1; i >= start; i--) + { + char c = source.CharAt(i); + var strip = false; + + if (IsSignChar(c)) + { + if (i != start || dstart != 0) + { + strip = true; + } + else if (sign >= 0) + { + strip = true; + } + else + { + sign = i; + } + } + else if (IsDecimalPointChar(c)) + { + if (dec >= 0) + { + strip = true; + } + else + { + dec = i; + } + } + + if (strip) + { + if (end == start + 1) + { + return new String(""); // Only one character, and it was stripped. + } + if (stripped == null) + { + stripped = new SpannableStringBuilder(source, start, end); + } + stripped.Delete(i - start, i + 1 - start); + } + } + + return stripped == null ? (filterFormatted != null ? filterFormatted : new String("")) : stripped; + } +#pragma warning restore CS8602 // Dereference of a possibly null reference. + } +} From 633956929e8a7482b29107746ccbed45f7ebd0c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Burak=20Kaan=20K=C3=B6se?= Date: Sat, 13 Mar 2021 03:37:20 +0100 Subject: [PATCH 06/48] Keyboard added for EntryStub. --- src/Core/tests/DeviceTests/Stubs/EntryStub.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Core/tests/DeviceTests/Stubs/EntryStub.cs b/src/Core/tests/DeviceTests/Stubs/EntryStub.cs index 32d8347a986d..136edf20e10a 100644 --- a/src/Core/tests/DeviceTests/Stubs/EntryStub.cs +++ b/src/Core/tests/DeviceTests/Stubs/EntryStub.cs @@ -30,5 +30,7 @@ void OnTextChanged(string oldValue, string newValue) => TextChanged?.Invoke(this, new StubPropertyChangedEventArgs(oldValue, newValue)); public Font Font { get; set; } + + public Keyboard Keyboard { get; set; } } } \ No newline at end of file From 3795b0a9be368093bbcede6c4e4a4243ebff2c86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Burak=20Kaan=20K=C3=B6se?= Date: Sun, 14 Mar 2021 17:54:35 +0100 Subject: [PATCH 07/48] fix for wrong property name mapping --- src/Core/src/Handlers/Entry/EntryHandler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Core/src/Handlers/Entry/EntryHandler.cs b/src/Core/src/Handlers/Entry/EntryHandler.cs index 0091cc64f813..d1ebe9d1ca67 100644 --- a/src/Core/src/Handlers/Entry/EntryHandler.cs +++ b/src/Core/src/Handlers/Entry/EntryHandler.cs @@ -10,7 +10,7 @@ public partial class EntryHandler [nameof(IEntry.IsTextPredictionEnabled)] = MapIsTextPredictionEnabled, [nameof(IEntry.Placeholder)] = MapPlaceholder, [nameof(IEntry.IsReadOnly)] = MapIsReadOnly, - [nameof(IEntry.IsReadOnly)] = MapKeyboard + [nameof(IEntry.Keyboard)] = MapKeyboard }; public EntryHandler() : base(EntryMapper) From 407d314488e8849a25ae92fc4a44aaf7e7cfb022 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Burak=20Kaan=20K=C3=B6se?= Date: Sun, 14 Mar 2021 17:55:10 +0100 Subject: [PATCH 08/48] better property summary --- src/Core/src/Core/ITextInput.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Core/src/Core/ITextInput.cs b/src/Core/src/Core/ITextInput.cs index 33c0c2575243..999ce0d4359a 100644 --- a/src/Core/src/Core/ITextInput.cs +++ b/src/Core/src/Core/ITextInput.cs @@ -21,8 +21,8 @@ public interface ITextInput : IText bool IsReadOnly { get; } /// - /// Gets the keyboard type for the given input control. + /// Gets the keyboard input type. /// - Keyboard Keyboard{ get; } + Keyboard Keyboard { get; } } } \ No newline at end of file From 3e7b632851e7a7cb3c5a2e07aa79e014c5545c3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Burak=20Kaan=20K=C3=B6se?= Date: Sun, 14 Mar 2021 18:00:25 +0100 Subject: [PATCH 09/48] bindable proeprty added to Entry --- src/Controls/src/Core/Entry.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Controls/src/Core/Entry.cs b/src/Controls/src/Core/Entry.cs index 42d4d83f6f1d..e16dd95e0f5f 100644 --- a/src/Controls/src/Core/Entry.cs +++ b/src/Controls/src/Core/Entry.cs @@ -22,6 +22,7 @@ public partial class Entry : InputView, IFontElement, ITextAlignmentElement, IEn public new static readonly BindableProperty TextProperty = InputView.TextProperty; public new static readonly BindableProperty TextColorProperty = InputView.TextColorProperty; + public new static readonly BindableProperty KeyboardProperty = InputView.KeyboardProperty; public new static readonly BindableProperty CharacterSpacingProperty = InputView.CharacterSpacingProperty; From e80c40738a733048d6dec37288a8d1cd58922ec1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Burak=20Kaan=20K=C3=B6se?= Date: Sun, 14 Mar 2021 23:49:50 +0100 Subject: [PATCH 10/48] Device tests for all non custom keyboard types are implemented for both iOS and Android. --- .../DeviceTests/Data/KeyboardClassData.cs | 126 ++++++++++++++++++ .../Entry/EntryHandlerTests.Android.cs | 51 +++++++ .../Handlers/Entry/EntryHandlerTests.cs | 56 ++++++++ .../Handlers/Entry/EntryHandlerTests.iOS.cs | 29 ++++ src/Core/tests/DeviceTests/Stubs/EntryStub.cs | 2 +- 5 files changed, 263 insertions(+), 1 deletion(-) create mode 100644 src/Core/tests/DeviceTests/Data/KeyboardClassData.cs diff --git a/src/Core/tests/DeviceTests/Data/KeyboardClassData.cs b/src/Core/tests/DeviceTests/Data/KeyboardClassData.cs new file mode 100644 index 000000000000..756b35a5a199 --- /dev/null +++ b/src/Core/tests/DeviceTests/Data/KeyboardClassData.cs @@ -0,0 +1,126 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; + +namespace Microsoft.Maui.Core.DeviceTests.Data +{ + public class NumericKeyboardClassData : IEnumerable + { + public IEnumerator GetEnumerator() + { + yield return new object[] { Keyboard.Numeric, true }; + yield return new object[] { Keyboard.Default, false }; + yield return new object[] { Keyboard.Chat, false }; + yield return new object[] { Keyboard.Email, false }; + yield return new object[] { Keyboard.Plain, false }; + yield return new object[] { Keyboard.Telephone, false }; + yield return new object[] { Keyboard.Text, false }; + yield return new object[] { Keyboard.Url, false }; + } + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + } + + public class ChatKeyboardClassData : IEnumerable + { + public IEnumerator GetEnumerator() + { + yield return new object[] { Keyboard.Chat, true }; + yield return new object[] { Keyboard.Default, false }; + yield return new object[] { Keyboard.Numeric, false }; + yield return new object[] { Keyboard.Email, false }; + yield return new object[] { Keyboard.Plain, false }; + yield return new object[] { Keyboard.Telephone, false }; + yield return new object[] { Keyboard.Text, false }; + yield return new object[] { Keyboard.Url, false }; + } + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + } + + public class EmailKeyboardClassData : IEnumerable + { + public IEnumerator GetEnumerator() + { + yield return new object[] { Keyboard.Email, true }; + yield return new object[] { Keyboard.Default, false }; + yield return new object[] { Keyboard.Numeric, false }; + yield return new object[] { Keyboard.Chat, false }; + yield return new object[] { Keyboard.Plain, false }; + yield return new object[] { Keyboard.Telephone, false }; + yield return new object[] { Keyboard.Text, false }; + yield return new object[] { Keyboard.Url, false }; + } + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + } + + public class PlainKeyboardClassData : IEnumerable + { + public IEnumerator GetEnumerator() + { + yield return new object[] { Keyboard.Plain, true }; + yield return new object[] { Keyboard.Default, false }; + yield return new object[] { Keyboard.Numeric, false }; + yield return new object[] { Keyboard.Chat, false }; + yield return new object[] { Keyboard.Email, false }; + yield return new object[] { Keyboard.Telephone, false }; + yield return new object[] { Keyboard.Text, false }; + yield return new object[] { Keyboard.Url, false }; + } + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + } + + public class TelephoneKeyboardClassData : IEnumerable + { + public IEnumerator GetEnumerator() + { + yield return new object[] { Keyboard.Telephone, true }; + yield return new object[] { Keyboard.Default, false }; + yield return new object[] { Keyboard.Numeric, false }; + yield return new object[] { Keyboard.Chat, false }; + yield return new object[] { Keyboard.Email, false }; + yield return new object[] { Keyboard.Plain, false }; + yield return new object[] { Keyboard.Text, false }; + yield return new object[] { Keyboard.Url, false }; + } + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + } + + public class TextKeyboardClassData : IEnumerable + { + public IEnumerator GetEnumerator() + { + yield return new object[] { Keyboard.Text, true }; + yield return new object[] { Keyboard.Default, false }; + yield return new object[] { Keyboard.Numeric, false }; + yield return new object[] { Keyboard.Chat, false }; + yield return new object[] { Keyboard.Email, false }; + yield return new object[] { Keyboard.Plain, false }; + yield return new object[] { Keyboard.Telephone, false }; + yield return new object[] { Keyboard.Url, false }; + } + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + } + + public class UrlKeyboardClassData : IEnumerable + { + public IEnumerator GetEnumerator() + { + yield return new object[] { Keyboard.Url, true }; + yield return new object[] { Keyboard.Default, false }; + yield return new object[] { Keyboard.Numeric, false }; + yield return new object[] { Keyboard.Chat, false }; + yield return new object[] { Keyboard.Email, false }; + yield return new object[] { Keyboard.Plain, false }; + yield return new object[] { Keyboard.Telephone, false }; + yield return new object[] { Keyboard.Text, false }; + } + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + } +} diff --git a/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.Android.cs b/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.Android.cs index 2142fbe02e15..eea2b315868e 100644 --- a/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.Android.cs +++ b/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.Android.cs @@ -1,4 +1,5 @@ using Android.Text; +using Android.Text.Method; using Android.Widget; using Microsoft.Maui.Handlers; using AColor = global::Android.Graphics.Color; @@ -42,5 +43,55 @@ bool GetNativeIsReadOnly(EntryHandler entryHandler) return !editText.Focusable && !editText.FocusableInTouchMode; } + + bool GetNativeIsNumericKeyboard(EntryHandler entryHandler) + { + var editText = GetNativeEntry(entryHandler); + var inputTypes = editText.InputType; + + return editText.KeyListener is NumberKeyListener + && (inputTypes.HasFlag(InputTypes.NumberFlagDecimal) && inputTypes.HasFlag(InputTypes.ClassNumber) && inputTypes.HasFlag(InputTypes.NumberFlagSigned)); + } + + bool GetNativeIsChatKeyboard(EntryHandler entryHandler) + { + var editText = GetNativeEntry(entryHandler); + var inputTypes = editText.InputType; + + return (inputTypes.HasFlag(InputTypes.ClassText) && inputTypes.HasFlag(InputTypes.TextFlagCapSentences) && inputTypes.HasFlag(InputTypes.TextFlagNoSuggestions)); + } + + + bool GetNativeIsEmailKeyboard(EntryHandler entryHandler) + { + var editText = GetNativeEntry(entryHandler); + var inputTypes = editText.InputType; + + return (inputTypes.HasFlag(InputTypes.ClassText) && inputTypes.HasFlag(InputTypes.TextVariationEmailAddress)); + } + + bool GetNativeIsTelephoneKeyboard(EntryHandler entryHandler) + { + var editText = GetNativeEntry(entryHandler); + var inputTypes = editText.InputType; + + return inputTypes.HasFlag(InputTypes.ClassPhone); + } + + bool GetNativeIsUrlKeyboard(EntryHandler entryHandler) + { + var editText = GetNativeEntry(entryHandler); + var inputTypes = editText.InputType; + + return inputTypes.HasFlag(InputTypes.ClassText) && inputTypes.HasFlag(InputTypes.TextVariationUri); + } + + bool GetNativeIsTextKeyboard(EntryHandler entryHandler) + { + var editText = GetNativeEntry(entryHandler); + var inputTypes = editText.InputType; + + return inputTypes.HasFlag(InputTypes.ClassText) && inputTypes.HasFlag(InputTypes.TextFlagCapSentences); + } } } \ No newline at end of file diff --git a/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.cs b/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.cs index d3b96d554690..17d5c1b26185 100644 --- a/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.cs +++ b/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.cs @@ -1,7 +1,9 @@ using System.Threading.Tasks; using Microsoft.Maui.DeviceTests.Stubs; using Microsoft.Maui.Handlers; +using Microsoft.Maui.Core.DeviceTests.Data; using Xunit; +using Xunit.Extensions; namespace Microsoft.Maui.DeviceTests { @@ -207,5 +209,59 @@ public async Task TextChangeEventsFireCorrectly(string initialText, string newTe else Assert.Equal(0, eventFiredCount); } + + [Theory(DisplayName = "Validates Numeric Keyboard")] + [ClassData(typeof(NumericKeyboardClassData))] + public async Task ValidateNumericKeyboard(Keyboard keyboard, bool expected) + { + var entryStub = new EntryStub() { Keyboard = keyboard }; + + await ValidatePropertyInitValue(entryStub, () => expected, GetNativeIsNumericKeyboard, expected); + } + + [Theory(DisplayName = "Validates Email Keyboard")] + [ClassData(typeof(EmailKeyboardClassData))] + public async Task ValidateEmailKeyboard(Keyboard keyboard, bool expected) + { + var entryStub = new EntryStub() { Keyboard = keyboard }; + + await ValidatePropertyInitValue(entryStub, () => expected, GetNativeIsEmailKeyboard, expected); + } + + [Theory(DisplayName = "Validates Telephone Keyboard")] + [ClassData(typeof(TelephoneKeyboardClassData))] + public async Task ValidateTelephoneKeyboard(Keyboard keyboard, bool expected) + { + var entryStub = new EntryStub() { Keyboard = keyboard }; + + await ValidatePropertyInitValue(entryStub, () => expected, GetNativeIsTelephoneKeyboard, expected); + } + + [Theory(DisplayName = "Validates Url Keyboard")] + [ClassData(typeof(UrlKeyboardClassData))] + public async Task ValidateUrlKeyboard(Keyboard keyboard, bool expected) + { + var entryStub = new EntryStub() { Keyboard = keyboard }; + + await ValidatePropertyInitValue(entryStub, () => expected, GetNativeIsUrlKeyboard, expected); + } + + [Theory(DisplayName = "Validates Text Keyboard")] + [ClassData(typeof(TextKeyboardClassData))] + public async Task ValidateTextKeyboard(Keyboard keyboard, bool expected) + { + var entryStub = new EntryStub() { Keyboard = keyboard }; + + await ValidatePropertyInitValue(entryStub, () => expected, GetNativeIsTextKeyboard, expected); + } + + [Theory(DisplayName = "Validates Chat Keyboard")] + [ClassData(typeof(ChatKeyboardClassData))] + public async Task ValidateChatKeyboard(Keyboard keyboard, bool expected) + { + var entryStub = new EntryStub() { Keyboard = keyboard }; + + await ValidatePropertyInitValue(entryStub, () => expected, GetNativeIsChatKeyboard, expected); + } } } diff --git a/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.iOS.cs b/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.iOS.cs index a5a888890b85..32c59a817085 100644 --- a/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.iOS.cs +++ b/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.iOS.cs @@ -28,5 +28,34 @@ bool GetNativeIsTextPredictionEnabled(EntryHandler entryHandler) => bool GetNativeIsReadOnly(EntryHandler entryHandler) => !GetNativeEntry(entryHandler).UserInteractionEnabled; + + bool GetNativeIsNumericKeyboard(EntryHandler entryHandler) => + GetNativeEntry(entryHandler).KeyboardType == UIKeyboardType.DecimalPad; + + bool GetNativeIsEmailKeyboard(EntryHandler entryHandler) => + GetNativeEntry(entryHandler).KeyboardType == UIKeyboardType.EmailAddress; + + bool GetNativeIsTelephoneKeyboard(EntryHandler entryHandler) => + GetNativeEntry(entryHandler).KeyboardType == UIKeyboardType.PhonePad; + + bool GetNativeIsUrlKeyboard(EntryHandler entryHandler) => + GetNativeEntry(entryHandler).KeyboardType == UIKeyboardType.Url; + + bool GetNativeIsTextKeyboard(EntryHandler entryHandler) + { + var nativeEntry = GetNativeEntry(entryHandler); + + return nativeEntry.AutocapitalizationType == UITextAutocapitalizationType.Sentences && + nativeEntry.AutocorrectionType == UITextAutocorrectionType.Yes && + nativeEntry.SpellCheckingType == UITextSpellCheckingType.Yes; + } + + bool GetNativeIsChatKeyboard(EntryHandler entryHandler) + { + var nativeEntry = GetNativeEntry(entryHandler); + + return nativeEntry.AutocapitalizationType == UITextAutocapitalizationType.Sentences && + nativeEntry.AutocorrectionType == UITextAutocorrectionType.Yes; + } } } \ No newline at end of file diff --git a/src/Core/tests/DeviceTests/Stubs/EntryStub.cs b/src/Core/tests/DeviceTests/Stubs/EntryStub.cs index 136edf20e10a..4263985bd5fd 100644 --- a/src/Core/tests/DeviceTests/Stubs/EntryStub.cs +++ b/src/Core/tests/DeviceTests/Stubs/EntryStub.cs @@ -31,6 +31,6 @@ void OnTextChanged(string oldValue, string newValue) => public Font Font { get; set; } - public Keyboard Keyboard { get; set; } + public Keyboard Keyboard { get; set; } = Keyboard.Default; } } \ No newline at end of file From 27595c55403baed6b7faaf5c60f38211d1911a10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Burak=20Kaan=20K=C3=B6se?= Date: Mon, 15 Mar 2021 00:45:05 +0100 Subject: [PATCH 11/48] MapKeyboard order changed in order to prevent unwanted changes to other properties like IsTextPredictionEnabled --- src/Core/src/Handlers/Entry/EntryHandler.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Core/src/Handlers/Entry/EntryHandler.cs b/src/Core/src/Handlers/Entry/EntryHandler.cs index d1ebe9d1ca67..32ac20976808 100644 --- a/src/Core/src/Handlers/Entry/EntryHandler.cs +++ b/src/Core/src/Handlers/Entry/EntryHandler.cs @@ -4,13 +4,13 @@ public partial class EntryHandler { public static PropertyMapper EntryMapper = new PropertyMapper(ViewHandler.ViewMapper) { + [nameof(IEntry.Keyboard)] = MapKeyboard, [nameof(IEntry.Text)] = MapText, [nameof(IEntry.TextColor)] = MapTextColor, [nameof(IEntry.IsPassword)] = MapIsPassword, [nameof(IEntry.IsTextPredictionEnabled)] = MapIsTextPredictionEnabled, [nameof(IEntry.Placeholder)] = MapPlaceholder, - [nameof(IEntry.IsReadOnly)] = MapIsReadOnly, - [nameof(IEntry.Keyboard)] = MapKeyboard + [nameof(IEntry.IsReadOnly)] = MapIsReadOnly }; public EntryHandler() : base(EntryMapper) From bc5daa5506b8b25a2a8aedc575f3b903aca5049a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Burak=20Kaan=20K=C3=B6se?= Date: Mon, 15 Mar 2021 00:48:17 +0100 Subject: [PATCH 12/48] Numeric entry to samples with placeholder. --- src/Controls/samples/Controls.Sample/Pages/MainPage.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Controls/samples/Controls.Sample/Pages/MainPage.cs b/src/Controls/samples/Controls.Sample/Pages/MainPage.cs index 2f85ebb050f7..6c28cd2eaa72 100644 --- a/src/Controls/samples/Controls.Sample/Pages/MainPage.cs +++ b/src/Controls/samples/Controls.Sample/Pages/MainPage.cs @@ -36,7 +36,7 @@ void SetupMauiLayout() verticalStack.Add(new Label { Text = "This should have padding", Padding = new Thickness(40), BackgroundColor = Color.LightBlue }); var passwordEntry = new Entry() { IsPassword = true }; - var numericEntry = new Entry() { Keyboard = Keyboard.Numeric }; + var numericEntry = new Entry() { Keyboard = Keyboard.Numeric, Placeholder = "Numeric Entry" }; verticalStack.Add(passwordEntry); verticalStack.Add(numericEntry); From 0fa4eaaa8a1ccce240512eb462af8f66106c691f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Burak=20Kaan=20K=C3=B6se?= Date: Mon, 15 Mar 2021 01:10:21 +0100 Subject: [PATCH 13/48] Fixed merging error with namespaces. --- src/Core/src/Platform/Android/EntryExtensions.cs | 7 +------ .../Handlers/Entry/EntryHandlerTests.Android.cs | 4 +--- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/src/Core/src/Platform/Android/EntryExtensions.cs b/src/Core/src/Platform/Android/EntryExtensions.cs index 433754ccb293..4df98b5858ca 100644 --- a/src/Core/src/Platform/Android/EntryExtensions.cs +++ b/src/Core/src/Platform/Android/EntryExtensions.cs @@ -1,13 +1,8 @@ using Android.Content.Res; -using Android.OS; using Android.Text; -using Android.Text.Method; -using Android.Widget; -using Microsoft.Maui.Platform.Android; using Android.Util; -using Android.Content.Res; -using Android.Text; using AndroidX.AppCompat.Widget; +using Microsoft.Maui.Platform.Android; namespace Microsoft.Maui { diff --git a/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.Android.cs b/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.Android.cs index 76602da1685c..8c4943d2423d 100644 --- a/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.Android.cs +++ b/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.Android.cs @@ -1,8 +1,6 @@ -using Android.Text; -using Android.Text.Method; -using Android.Widget; using System.Threading.Tasks; using Android.Text; +using Android.Text.Method; using AndroidX.AppCompat.Widget; using Microsoft.Extensions.DependencyInjection; using Microsoft.Maui.DeviceTests.Stubs; From 220d27deacb3e5f2f301d90d686b9af7e0bbdd90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Burak=20Kaan=20K=C3=B6se?= Date: Mon, 15 Mar 2021 02:27:07 +0100 Subject: [PATCH 14/48] Better PortHandler for UpdateInputType in Android renderer. --- src/Compatibility/Core/src/Android/Renderers/EntryRenderer.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Compatibility/Core/src/Android/Renderers/EntryRenderer.cs b/src/Compatibility/Core/src/Android/Renderers/EntryRenderer.cs index c92869d31ee9..491d0c5ba8a7 100644 --- a/src/Compatibility/Core/src/Android/Renderers/EntryRenderer.cs +++ b/src/Compatibility/Core/src/Android/Renderers/EntryRenderer.cs @@ -318,7 +318,8 @@ protected virtual void UpdateFont() EditText.SetTextSize(ComplexUnitType.Sp, (float)Element.FontSize); } - [PortHandler("Partially ported")] + [PortHandler("IsSpellCheckEnabled is missing.")] + [PortHandler("No override for GetDigitsKeyListener")] void UpdateInputType() { Entry model = Element; From 37eba9a711effe792280a7e81aea4eaa2028f8d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Burak=20Kaan=20K=C3=B6se?= Date: Mon, 15 Mar 2021 09:26:39 +0100 Subject: [PATCH 15/48] pattern matching usage in keyboard extensions for android. --- src/Core/src/Platform/Android/KeyboardExtensions.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Core/src/Platform/Android/KeyboardExtensions.cs b/src/Core/src/Platform/Android/KeyboardExtensions.cs index 639c8b48fcb1..0acf3d56ede6 100644 --- a/src/Core/src/Platform/Android/KeyboardExtensions.cs +++ b/src/Core/src/Platform/Android/KeyboardExtensions.cs @@ -30,9 +30,8 @@ public static InputTypes ToInputType(this Keyboard self) result = InputTypes.ClassText | InputTypes.TextFlagCapSentences; else if (self == Keyboard.Url) result = InputTypes.ClassText | InputTypes.TextVariationUri; - else if (self is CustomKeyboard) + else if (self is CustomKeyboard custom) { - var custom = (CustomKeyboard)self; var capitalizedSentenceEnabled = (custom.Flags & KeyboardFlags.CapitalizeSentence) == KeyboardFlags.CapitalizeSentence; var capitalizedWordsEnabled = (custom.Flags & KeyboardFlags.CapitalizeWord) == KeyboardFlags.CapitalizeWord; var capitalizedCharacterEnabled = (custom.Flags & KeyboardFlags.CapitalizeCharacter) == KeyboardFlags.CapitalizeCharacter; @@ -49,7 +48,6 @@ public static InputTypes ToInputType(this Keyboard self) // Log.Warning(null, "On Android, KeyboardFlags.Suggestions enables KeyboardFlags.Spellcheck as well due to a platform limitation."); result = InputTypes.ClassText | InputTypes.TextFlagAutoCorrect; } - if (!capitalizedSentenceEnabled && spellcheckEnabled && !suggestionsEnabled) result = InputTypes.ClassText | InputTypes.TextFlagAutoComplete; From a38ab4c2839de1d0e6798d2f01da8f6b1b76d249 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Burak=20Kaan=20K=C3=B6se?= Date: Mon, 15 Mar 2021 11:11:24 +0100 Subject: [PATCH 16/48] Moved LocalizedDigitsKeyListener to Core.Android project --- .../src/Android/Cells/EntryCellRenderer.cs | 1 + .../src/Android/Compatibility.Android.csproj | 1 + .../Core/src/Android/PopupManager.cs | 1 + .../src/Android/Renderers/EditorRenderer.cs | 1 + .../src/Android/Renderers/EntryRenderer.cs | 1 + .../Renderers/LocalizedDigitsKeyListener.cs | 215 ------------------ .../Android/Renderers/SearchBarRenderer.cs | 1 + .../SearchHandlerAppearanceTracker.cs | 1 + .../Android/LocalizedDigitsKeyListener.cs | 2 +- 9 files changed, 8 insertions(+), 216 deletions(-) delete mode 100644 src/Compatibility/Core/src/Android/Renderers/LocalizedDigitsKeyListener.cs diff --git a/src/Compatibility/Core/src/Android/Cells/EntryCellRenderer.cs b/src/Compatibility/Core/src/Android/Cells/EntryCellRenderer.cs index ba2ce1fb8376..36d4d5bea45a 100644 --- a/src/Compatibility/Core/src/Android/Cells/EntryCellRenderer.cs +++ b/src/Compatibility/Core/src/Android/Cells/EntryCellRenderer.cs @@ -3,6 +3,7 @@ using Android.Text; using Android.Text.Method; using Android.Views; +using Microsoft.Maui.Platform.Android; namespace Microsoft.Maui.Controls.Compatibility.Platform.Android { diff --git a/src/Compatibility/Core/src/Android/Compatibility.Android.csproj b/src/Compatibility/Core/src/Android/Compatibility.Android.csproj index 6b1f36910b4e..c4afcd4fc132 100644 --- a/src/Compatibility/Core/src/Android/Compatibility.Android.csproj +++ b/src/Compatibility/Core/src/Android/Compatibility.Android.csproj @@ -13,6 +13,7 @@ + diff --git a/src/Compatibility/Core/src/Android/PopupManager.cs b/src/Compatibility/Core/src/Android/PopupManager.cs index 7798f3d275cf..d3885ea07172 100644 --- a/src/Compatibility/Core/src/Android/PopupManager.cs +++ b/src/Compatibility/Core/src/Android/PopupManager.cs @@ -7,6 +7,7 @@ using Android.Views; using Android.Widget; using Microsoft.Maui.Controls.Internals; +using Microsoft.Maui.Platform.Android; using AppCompatActivity = AndroidX.AppCompat.App.AppCompatActivity; using AppCompatAlertDialog = AndroidX.AppCompat.App.AlertDialog; diff --git a/src/Compatibility/Core/src/Android/Renderers/EditorRenderer.cs b/src/Compatibility/Core/src/Android/Renderers/EditorRenderer.cs index 0a9c3b842c24..41ab4ed003ee 100644 --- a/src/Compatibility/Core/src/Android/Renderers/EditorRenderer.cs +++ b/src/Compatibility/Core/src/Android/Renderers/EditorRenderer.cs @@ -9,6 +9,7 @@ using Android.Views.InputMethods; using Android.Widget; using Java.Lang; +using Microsoft.Maui.Platform.Android; namespace Microsoft.Maui.Controls.Compatibility.Platform.Android { diff --git a/src/Compatibility/Core/src/Android/Renderers/EntryRenderer.cs b/src/Compatibility/Core/src/Android/Renderers/EntryRenderer.cs index 491d0c5ba8a7..89b8835544c7 100644 --- a/src/Compatibility/Core/src/Android/Renderers/EntryRenderer.cs +++ b/src/Compatibility/Core/src/Android/Renderers/EntryRenderer.cs @@ -12,6 +12,7 @@ using AndroidX.Core.Content; using Java.Lang; using Microsoft.Maui.Controls.PlatformConfiguration.AndroidSpecific; +using Microsoft.Maui.Platform.Android; namespace Microsoft.Maui.Controls.Compatibility.Platform.Android { diff --git a/src/Compatibility/Core/src/Android/Renderers/LocalizedDigitsKeyListener.cs b/src/Compatibility/Core/src/Android/Renderers/LocalizedDigitsKeyListener.cs deleted file mode 100644 index d35990ce5628..000000000000 --- a/src/Compatibility/Core/src/Android/Renderers/LocalizedDigitsKeyListener.cs +++ /dev/null @@ -1,215 +0,0 @@ -using System.Collections.Generic; -using Android.Text; -using Android.Text.Method; -using Java.Lang; -using Java.Text; - -namespace Microsoft.Maui.Controls.Compatibility.Platform.Android -{ - internal class LocalizedDigitsKeyListener : NumberKeyListener - { - readonly char _decimalSeparator; - - // I'm not aware of a situation/locale where this would need to be something different, - // but we'll make it easy to localize the sign in the future just in case - const char SignCharacter = '-'; - - static Dictionary s_unsignedCache; - static Dictionary s_signedCache; - - static char GetDecimalSeparator() - { - var format = NumberFormat.Instance as DecimalFormat; - if (format == null) - { - return '.'; - } - - DecimalFormatSymbols sym = format.DecimalFormatSymbols; - return sym.DecimalSeparator; - } - - public static NumberKeyListener Create(InputTypes inputTypes) - { - if ((inputTypes & InputTypes.NumberFlagDecimal) == 0) - { - // If decimal isn't allowed, we can just use the Android version -#pragma warning disable 0618 - return DigitsKeyListener.GetInstance(inputTypes.HasFlag(InputTypes.NumberFlagSigned), false); -#pragma warning restore 0618 - } - - // Figure out what the decimal separator is for the current locale - char decimalSeparator = GetDecimalSeparator(); - - if (decimalSeparator == '.') - { - // If it's '.', then we can just use the default Android version -#pragma warning disable 0618 - return DigitsKeyListener.GetInstance(inputTypes.HasFlag(InputTypes.NumberFlagSigned), true); -#pragma warning restore 0618 - } - - // If decimals are enabled and the locale's decimal separator is not '.' - // (which is hard-coded in the Android DigitKeyListener), then use - // our custom one with a configurable decimal separator - return GetInstance(inputTypes, decimalSeparator); - } - - public static LocalizedDigitsKeyListener GetInstance(InputTypes inputTypes, char decimalSeparator) - { - if ((inputTypes & InputTypes.NumberFlagSigned) != 0) - { - return GetInstance(inputTypes, decimalSeparator, ref s_signedCache); - } - - return GetInstance(inputTypes, decimalSeparator, ref s_unsignedCache); - } - - static LocalizedDigitsKeyListener GetInstance(InputTypes inputTypes, char decimalSeparator, ref Dictionary cache) - { - if (cache == null) - { - cache = new Dictionary(1); - } - - if (!cache.ContainsKey(decimalSeparator)) - { - cache.Add(decimalSeparator, new LocalizedDigitsKeyListener(inputTypes, decimalSeparator)); - } - - return cache[decimalSeparator]; - } - - protected LocalizedDigitsKeyListener(InputTypes inputTypes, char decimalSeparator) - { - _decimalSeparator = decimalSeparator; - InputType = inputTypes; - } - - public override InputTypes InputType { get; } - - char[] _acceptedChars; - - protected override char[] GetAcceptedChars() - { - if ((InputType & InputTypes.NumberFlagSigned) == 0) - { - return _acceptedChars ?? - (_acceptedChars = new[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', _decimalSeparator }); - } - - return _acceptedChars ?? - (_acceptedChars = new[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', SignCharacter, _decimalSeparator }); - } - - static bool IsSignChar(char c) - { - return c == SignCharacter; - } - - bool IsDecimalPointChar(char c) - { - return c == _decimalSeparator; - } - - public override ICharSequence FilterFormatted(ICharSequence source, int start, int end, ISpanned dest, int dstart, - int dend) - { - // Borrowed heavily from the Android source - ICharSequence filterFormatted = base.FilterFormatted(source, start, end, dest, dstart, dend); - - if (filterFormatted != null) - { - source = filterFormatted; - start = 0; - end = filterFormatted.Length(); - } - - int sign = -1; - int dec = -1; - int dlen = dest.Length(); - - // Find out if the existing text has a sign or decimal point characters. - for (var i = 0; i < dstart; i++) - { - char c = dest.CharAt(i); - if (IsSignChar(c)) - { - sign = i; - } - else if (IsDecimalPointChar(c)) - { - dec = i; - } - } - - for (int i = dend; i < dlen; i++) - { - char c = dest.CharAt(i); - if (IsSignChar(c)) - { - return new String(""); // Nothing can be inserted in front of a sign character. - } - - if (IsDecimalPointChar(c)) - { - dec = i; - } - } - - // If it does, we must strip them out from the source. - // In addition, a sign character must be the very first character, - // and nothing can be inserted before an existing sign character. - // Go in reverse order so the offsets are stable. - SpannableStringBuilder stripped = null; - for (int i = end - 1; i >= start; i--) - { - char c = source.CharAt(i); - var strip = false; - - if (IsSignChar(c)) - { - if (i != start || dstart != 0) - { - strip = true; - } - else if (sign >= 0) - { - strip = true; - } - else - { - sign = i; - } - } - else if (IsDecimalPointChar(c)) - { - if (dec >= 0) - { - strip = true; - } - else - { - dec = i; - } - } - - if (strip) - { - if (end == start + 1) - { - return new String(""); // Only one character, and it was stripped. - } - if (stripped == null) - { - stripped = new SpannableStringBuilder(source, start, end); - } - stripped.Delete(i - start, i + 1 - start); - } - } - - return stripped ?? filterFormatted; - } - } -} \ No newline at end of file diff --git a/src/Compatibility/Core/src/Android/Renderers/SearchBarRenderer.cs b/src/Compatibility/Core/src/Android/Renderers/SearchBarRenderer.cs index 32700076e4f4..76d0603e4f58 100644 --- a/src/Compatibility/Core/src/Android/Renderers/SearchBarRenderer.cs +++ b/src/Compatibility/Core/src/Android/Renderers/SearchBarRenderer.cs @@ -8,6 +8,7 @@ using Android.Util; using Android.Views; using Android.Widget; +using Microsoft.Maui.Platform.Android; namespace Microsoft.Maui.Controls.Compatibility.Platform.Android { diff --git a/src/Compatibility/Core/src/Android/Renderers/SearchHandlerAppearanceTracker.cs b/src/Compatibility/Core/src/Android/Renderers/SearchHandlerAppearanceTracker.cs index e756ef38b30b..adc963654211 100644 --- a/src/Compatibility/Core/src/Android/Renderers/SearchHandlerAppearanceTracker.cs +++ b/src/Compatibility/Core/src/Android/Renderers/SearchHandlerAppearanceTracker.cs @@ -12,6 +12,7 @@ using Android.Views; using Android.Widget; using Microsoft.Maui.Controls.Internals; +using Microsoft.Maui.Platform.Android; using AImageButton = Android.Widget.ImageButton; using AView = Android.Views.View; diff --git a/src/Core/src/Platform/Android/LocalizedDigitsKeyListener.cs b/src/Core/src/Platform/Android/LocalizedDigitsKeyListener.cs index c537fc3ac6b9..2df4be445614 100644 --- a/src/Core/src/Platform/Android/LocalizedDigitsKeyListener.cs +++ b/src/Core/src/Platform/Android/LocalizedDigitsKeyListener.cs @@ -6,7 +6,7 @@ namespace Microsoft.Maui.Platform.Android { - internal class LocalizedDigitsKeyListener : NumberKeyListener + public class LocalizedDigitsKeyListener : NumberKeyListener { readonly char _decimalSeparator; From a473775c616ee0b85046b142f379c7ece53fec2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Burak=20Kaan=20K=C3=B6se?= Date: Mon, 15 Mar 2021 11:44:02 +0100 Subject: [PATCH 17/48] Delete KeyboardExtensions in Android Compatibility. --- .../Android/Renderers/KeyboardExtensions.cs | 92 ------------------- 1 file changed, 92 deletions(-) delete mode 100644 src/Compatibility/Core/src/Android/Renderers/KeyboardExtensions.cs diff --git a/src/Compatibility/Core/src/Android/Renderers/KeyboardExtensions.cs b/src/Compatibility/Core/src/Android/Renderers/KeyboardExtensions.cs deleted file mode 100644 index cc5529f178fd..000000000000 --- a/src/Compatibility/Core/src/Android/Renderers/KeyboardExtensions.cs +++ /dev/null @@ -1,92 +0,0 @@ -using Android.Text; -using Microsoft.Maui.Controls.Internals; - -namespace Microsoft.Maui.Controls.Compatibility.Platform.Android -{ - public static class KeyboardExtensions - { - public static InputTypes ToInputType(this Keyboard self) - { - var result = new InputTypes(); - - // ClassText: !autocaps, spellcheck, suggestions - // TextFlagNoSuggestions: !autocaps, !spellcheck, !suggestions - // InputTypes.ClassText | InputTypes.TextFlagCapSentences autocaps, spellcheck, suggestions - // InputTypes.ClassText | InputTypes.TextFlagCapSentences | InputTypes.TextFlagNoSuggestions; autocaps, !spellcheck, !suggestions - - if (self == Keyboard.Default) - result = InputTypes.ClassText | InputTypes.TextVariationNormal; - else if (self == Keyboard.Chat) - result = InputTypes.ClassText | InputTypes.TextFlagCapSentences | InputTypes.TextFlagNoSuggestions; - else if (self == Keyboard.Email) - result = InputTypes.ClassText | InputTypes.TextVariationEmailAddress; - else if (self == Keyboard.Numeric) - result = InputTypes.ClassNumber | InputTypes.NumberFlagDecimal | InputTypes.NumberFlagSigned; - else if (self == Keyboard.Telephone) - result = InputTypes.ClassPhone; - else if (self == Keyboard.Text) - result = InputTypes.ClassText | InputTypes.TextFlagCapSentences; - else if (self == Keyboard.Url) - result = InputTypes.ClassText | InputTypes.TextVariationUri; - else if (self is CustomKeyboard) - { - var custom = (CustomKeyboard)self; - var capitalizedSentenceEnabled = (custom.Flags & KeyboardFlags.CapitalizeSentence) == KeyboardFlags.CapitalizeSentence; - var capitalizedWordsEnabled = (custom.Flags & KeyboardFlags.CapitalizeWord) == KeyboardFlags.CapitalizeWord; - var capitalizedCharacterEnabled = (custom.Flags & KeyboardFlags.CapitalizeCharacter) == KeyboardFlags.CapitalizeCharacter; - - var spellcheckEnabled = (custom.Flags & KeyboardFlags.Spellcheck) == KeyboardFlags.Spellcheck; - var suggestionsEnabled = (custom.Flags & KeyboardFlags.Suggestions) == KeyboardFlags.Suggestions; - - if (!capitalizedSentenceEnabled && !spellcheckEnabled && !suggestionsEnabled) - result = InputTypes.ClassText | InputTypes.TextFlagNoSuggestions; - - if (!capitalizedSentenceEnabled && !spellcheckEnabled && suggestionsEnabled) - { - // Due to the nature of android, TextFlagAutoCorrect includes Spellcheck - Log.Warning(null, "On Android, KeyboardFlags.Suggestions enables KeyboardFlags.Spellcheck as well due to a platform limitation."); - result = InputTypes.ClassText | InputTypes.TextFlagAutoCorrect; - } - - if (!capitalizedSentenceEnabled && spellcheckEnabled && !suggestionsEnabled) - result = InputTypes.ClassText | InputTypes.TextFlagAutoComplete; - - if (!capitalizedSentenceEnabled && spellcheckEnabled && suggestionsEnabled) - result = InputTypes.ClassText | InputTypes.TextFlagAutoCorrect; - - if (capitalizedSentenceEnabled && !spellcheckEnabled && !suggestionsEnabled) - result = InputTypes.ClassText | InputTypes.TextFlagCapSentences | InputTypes.TextFlagNoSuggestions; - - if (capitalizedSentenceEnabled && !spellcheckEnabled && suggestionsEnabled) - { - // Due to the nature of android, TextFlagAutoCorrect includes Spellcheck - Log.Warning(null, "On Android, KeyboardFlags.Suggestions enables KeyboardFlags.Spellcheck as well due to a platform limitation."); - result = InputTypes.ClassText | InputTypes.TextFlagCapSentences | InputTypes.TextFlagAutoCorrect; - } - - if (capitalizedSentenceEnabled && spellcheckEnabled && !suggestionsEnabled) - result = InputTypes.ClassText | InputTypes.TextFlagCapSentences | InputTypes.TextFlagAutoComplete; - - if (capitalizedSentenceEnabled && spellcheckEnabled && suggestionsEnabled) - result = InputTypes.ClassText | InputTypes.TextFlagCapSentences | InputTypes.TextFlagAutoCorrect; - - // All existed before these settings. This ensures these changes are backwards compatible - // without this check TextFlagCapCharacters would win - if (custom.Flags != KeyboardFlags.All) - { - if (capitalizedWordsEnabled) - result = result | InputTypes.TextFlagCapWords; - - if (capitalizedCharacterEnabled) - result = result | InputTypes.TextFlagCapCharacters; - } - } - else - { - // Should never happens - result = InputTypes.TextVariationNormal; - } - return result; - } - } -} \ No newline at end of file From a8e098335f375c585a6a536328e0ead663c723eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Burak=20Kaan=20K=C3=B6se?= Date: Mon, 15 Mar 2021 11:56:21 +0100 Subject: [PATCH 18/48] Possible iOS Compatibility for Extensions. --- .../Core/src/iOS/Extensions/Extensions.cs | 150 +----------------- .../src/iOS/Renderers/ButtonLayoutManager.cs | 1 + .../Core/src/iOS/Renderers/EntryRenderer.cs | 1 + .../SearchHandlerAppearanceTracker.cs | 1 + .../{KeyboardExtensions.cs => Extensions.cs} | 81 +++++++++- 5 files changed, 84 insertions(+), 150 deletions(-) rename src/Core/src/Platform/iOS/{KeyboardExtensions.cs => Extensions.cs} (56%) diff --git a/src/Compatibility/Core/src/iOS/Extensions/Extensions.cs b/src/Compatibility/Core/src/iOS/Extensions/Extensions.cs index e2d7ce489a45..7988b688e5b4 100644 --- a/src/Compatibility/Core/src/iOS/Extensions/Extensions.cs +++ b/src/Compatibility/Core/src/iOS/Extensions/Extensions.cs @@ -6,77 +6,9 @@ namespace Microsoft.Maui.Controls.Compatibility.Platform.iOS { + [PortHandler("Following methods still need to be ported.")] public static class Extensions { - public static void ApplyKeyboard(this IUITextInput textInput, Keyboard keyboard) - { - if(textInput is IUITextInputTraits traits) - ApplyKeyboard(traits, keyboard); - } - - public static void ApplyKeyboard(this IUITextInputTraits textInput, Keyboard keyboard) - { - textInput.AutocapitalizationType = UITextAutocapitalizationType.None; - textInput.AutocorrectionType = UITextAutocorrectionType.No; - textInput.SpellCheckingType = UITextSpellCheckingType.No; - textInput.KeyboardType = UIKeyboardType.Default; - - if (keyboard == Keyboard.Default) - { - textInput.AutocapitalizationType = UITextAutocapitalizationType.Sentences; - textInput.AutocorrectionType = UITextAutocorrectionType.Default; - textInput.SpellCheckingType = UITextSpellCheckingType.Default; - } - else if (keyboard == Keyboard.Chat) - { - textInput.AutocapitalizationType = UITextAutocapitalizationType.Sentences; - textInput.AutocorrectionType = UITextAutocorrectionType.Yes; - } - else if (keyboard == Keyboard.Email) - textInput.KeyboardType = UIKeyboardType.EmailAddress; - else if (keyboard == Keyboard.Numeric) - textInput.KeyboardType = UIKeyboardType.DecimalPad; - else if (keyboard == Keyboard.Telephone) - textInput.KeyboardType = UIKeyboardType.PhonePad; - else if (keyboard == Keyboard.Text) - { - textInput.AutocapitalizationType = UITextAutocapitalizationType.Sentences; - textInput.AutocorrectionType = UITextAutocorrectionType.Yes; - textInput.SpellCheckingType = UITextSpellCheckingType.Yes; - } - else if (keyboard == Keyboard.Url) - textInput.KeyboardType = UIKeyboardType.Url; - else if (keyboard is CustomKeyboard) - { - var custom = (CustomKeyboard)keyboard; - - var capitalizedSentenceEnabled = (custom.Flags & KeyboardFlags.CapitalizeSentence) == KeyboardFlags.CapitalizeSentence; - var capitalizedWordsEnabled = (custom.Flags & KeyboardFlags.CapitalizeWord) == KeyboardFlags.CapitalizeWord; - var capitalizedCharacterEnabled = (custom.Flags & KeyboardFlags.CapitalizeCharacter) == KeyboardFlags.CapitalizeCharacter; - var capitalizedNone = (custom.Flags & KeyboardFlags.None) == KeyboardFlags.None; - - var spellcheckEnabled = (custom.Flags & KeyboardFlags.Spellcheck) == KeyboardFlags.Spellcheck; - var suggestionsEnabled = (custom.Flags & KeyboardFlags.Suggestions) == KeyboardFlags.Suggestions; - - - UITextAutocapitalizationType capSettings = UITextAutocapitalizationType.None; - - // Sentence being first ensures that the behavior of ALL is backwards compatible - if (capitalizedSentenceEnabled) - capSettings = UITextAutocapitalizationType.Sentences; - else if (capitalizedWordsEnabled) - capSettings = UITextAutocapitalizationType.Words; - else if (capitalizedCharacterEnabled) - capSettings = UITextAutocapitalizationType.AllCharacters; - else if (capitalizedNone) - capSettings = UITextAutocapitalizationType.None; - - textInput.AutocapitalizationType = capSettings; - textInput.AutocorrectionType = suggestionsEnabled ? UITextAutocorrectionType.Yes : UITextAutocorrectionType.No; - textInput.SpellCheckingType = spellcheckEnabled ? UITextSpellCheckingType.Yes : UITextSpellCheckingType.No; - } - } - public static UIModalPresentationStyle ToNativeModalPresentationStyle(this PlatformConfiguration.iOSSpecific.UIModalPresentationStyle style) { switch (style) @@ -110,28 +42,6 @@ internal static UISearchBarStyle ToNativeSearchBarStyle(this PlatformConfigurati throw new ArgumentOutOfRangeException(nameof(style)); } } - - internal static UIReturnKeyType ToUIReturnKeyType(this ReturnType returnType) - { - switch (returnType) - { - case ReturnType.Go: - return UIReturnKeyType.Go; - case ReturnType.Next: - return UIReturnKeyType.Next; - case ReturnType.Send: - return UIReturnKeyType.Send; - case ReturnType.Search: - return UIReturnKeyType.Search; - case ReturnType.Done: - return UIReturnKeyType.Done; - case ReturnType.Default: - return UIReturnKeyType.Default; - default: - throw new System.NotImplementedException($"ReturnType {returnType} not supported"); - } - } - internal static DeviceOrientation ToDeviceOrientation(this UIDeviceOrientation orientation) { switch (orientation) @@ -149,64 +59,6 @@ internal static DeviceOrientation ToDeviceOrientation(this UIDeviceOrientation o } } - [PortHandler] - internal static NSMutableAttributedString AddCharacterSpacing(this NSAttributedString attributedString, string text, double characterSpacing) - { - if (attributedString == null && characterSpacing == 0) - return null; - - NSMutableAttributedString mutableAttributedString = attributedString as NSMutableAttributedString; - if (attributedString == null || attributedString.Length == 0) - { - mutableAttributedString = text == null ? new NSMutableAttributedString() : new NSMutableAttributedString(text); - } - else - { - mutableAttributedString = new NSMutableAttributedString(attributedString); - - if (!mutableAttributedString.MutableString.ToString().Equals(text)) - { - mutableAttributedString.MutableString.SetString(new NSString(text)); - } - } - - AddKerningAdjustment(mutableAttributedString, text, characterSpacing); - - return mutableAttributedString; - } - - [PortHandler] - internal static bool HasCharacterAdjustment(this NSMutableAttributedString mutableAttributedString) - { - if (mutableAttributedString == null) - return false; - - NSRange removalRange; - var attributes = mutableAttributedString.GetAttributes(0, out removalRange); - - for (uint i = 0; i < attributes.Count; i++) - if (attributes.Keys[i] is NSString nSString && nSString == UIStringAttributeKey.KerningAdjustment) - return true; - - return false; - } - - [PortHandler] - internal static void AddKerningAdjustment(NSMutableAttributedString mutableAttributedString, string text, double characterSpacing) - { - if (!string.IsNullOrEmpty(text)) - { - if (characterSpacing == 0 && !mutableAttributedString.HasCharacterAdjustment()) - return; - - mutableAttributedString.AddAttribute - ( - UIStringAttributeKey.KerningAdjustment, - NSObject.FromObject(characterSpacing), new NSRange(0, text.Length - 1) - ); - } - } - internal static bool IsHorizontal(this Button.ButtonContentLayout layout) => layout.Position == Button.ButtonContentLayout.ImagePosition.Left || layout.Position == Button.ButtonContentLayout.ImagePosition.Right; diff --git a/src/Compatibility/Core/src/iOS/Renderers/ButtonLayoutManager.cs b/src/Compatibility/Core/src/iOS/Renderers/ButtonLayoutManager.cs index c8eb4f6eb917..1544f21c1fd5 100644 --- a/src/Compatibility/Core/src/iOS/Renderers/ButtonLayoutManager.cs +++ b/src/Compatibility/Core/src/iOS/Renderers/ButtonLayoutManager.cs @@ -3,6 +3,7 @@ using System.Threading.Tasks; using CoreGraphics; using Foundation; +using Microsoft.Maui.Platform.iOS; using UIKit; namespace Microsoft.Maui.Controls.Compatibility.Platform.iOS diff --git a/src/Compatibility/Core/src/iOS/Renderers/EntryRenderer.cs b/src/Compatibility/Core/src/iOS/Renderers/EntryRenderer.cs index 12a87eb3bd7c..2774d7f272a3 100644 --- a/src/Compatibility/Core/src/iOS/Renderers/EntryRenderer.cs +++ b/src/Compatibility/Core/src/iOS/Renderers/EntryRenderer.cs @@ -7,6 +7,7 @@ using UIKit; using Microsoft.Maui.Controls.PlatformConfiguration.iOSSpecific; using Specifics = Microsoft.Maui.Controls.PlatformConfiguration.iOSSpecific.Entry; +using Microsoft.Maui.Platform.iOS; namespace Microsoft.Maui.Controls.Compatibility.Platform.iOS { diff --git a/src/Compatibility/Core/src/iOS/Renderers/SearchHandlerAppearanceTracker.cs b/src/Compatibility/Core/src/iOS/Renderers/SearchHandlerAppearanceTracker.cs index bdd4bd5945d4..a4e50b9223db 100644 --- a/src/Compatibility/Core/src/iOS/Renderers/SearchHandlerAppearanceTracker.cs +++ b/src/Compatibility/Core/src/iOS/Renderers/SearchHandlerAppearanceTracker.cs @@ -1,6 +1,7 @@ using System; using CoreGraphics; using Foundation; +using Microsoft.Maui.Platform.iOS; using UIKit; namespace Microsoft.Maui.Controls.Compatibility.Platform.iOS diff --git a/src/Core/src/Platform/iOS/KeyboardExtensions.cs b/src/Core/src/Platform/iOS/Extensions.cs similarity index 56% rename from src/Core/src/Platform/iOS/KeyboardExtensions.cs rename to src/Core/src/Platform/iOS/Extensions.cs index 53fa83450ceb..9de40f52b42c 100644 --- a/src/Core/src/Platform/iOS/KeyboardExtensions.cs +++ b/src/Core/src/Platform/iOS/Extensions.cs @@ -1,11 +1,12 @@ using System; using System.Collections.Generic; using System.Text; +using Foundation; using UIKit; namespace Microsoft.Maui.Platform.iOS { - public static class KeyboardExtensions + public static class Extensions { public static void ApplyKeyboard(this IUITextInput textInput, Keyboard keyboard) { @@ -75,5 +76,83 @@ public static void ApplyKeyboard(this IUITextInputTraits textInput, Keyboard key textInput.SpellCheckingType = spellcheckEnabled ? UITextSpellCheckingType.Yes : UITextSpellCheckingType.No; } } + + public static NSMutableAttributedString? AddCharacterSpacing(this NSAttributedString attributedString, string text, double characterSpacing) + { + if (attributedString == null && characterSpacing == 0) + return null; + + NSMutableAttributedString? mutableAttributedString = attributedString as NSMutableAttributedString; + if (attributedString == null || attributedString.Length == 0) + { + mutableAttributedString = text == null ? new NSMutableAttributedString() : new NSMutableAttributedString(text); + } + else + { + mutableAttributedString = new NSMutableAttributedString(attributedString); + + if (!mutableAttributedString.MutableString.ToString().Equals(text)) + { + mutableAttributedString.MutableString.SetString(new NSString(text)); + } + } + + AddKerningAdjustment(mutableAttributedString, text, characterSpacing); + + return mutableAttributedString; + } + + internal static bool HasCharacterAdjustment(this NSMutableAttributedString mutableAttributedString) + { + if (mutableAttributedString == null) + return false; + + NSRange removalRange; + var attributes = mutableAttributedString.GetAttributes(0, out removalRange); + + for (uint i = 0; i < attributes.Count; i++) + if (attributes.Keys[i] is NSString nSString && nSString == UIStringAttributeKey.KerningAdjustment) + return true; + + return false; + } + + internal static void AddKerningAdjustment(NSMutableAttributedString mutableAttributedString, string? text, double characterSpacing) + { + if (!string.IsNullOrEmpty(text)) + { + if (characterSpacing == 0 && !mutableAttributedString.HasCharacterAdjustment()) + return; + + mutableAttributedString.AddAttribute + ( + UIStringAttributeKey.KerningAdjustment, +#pragma warning disable CS8602 // Dereference of a possibly null reference. + NSObject.FromObject(characterSpacing), new NSRange(0, text.Length - 1) +#pragma warning restore CS8602 // Dereference of a possibly null reference. + ); + } + } + + public static UIReturnKeyType ToUIReturnKeyType(this ReturnType returnType) + { + switch (returnType) + { + case ReturnType.Go: + return UIReturnKeyType.Go; + case ReturnType.Next: + return UIReturnKeyType.Next; + case ReturnType.Send: + return UIReturnKeyType.Send; + case ReturnType.Search: + return UIReturnKeyType.Search; + case ReturnType.Done: + return UIReturnKeyType.Done; + case ReturnType.Default: + return UIReturnKeyType.Default; + default: + throw new System.NotImplementedException($"ReturnType {returnType} not supported"); + } + } } } From 42f0326f9ca8eff8e9480c40b83018e38c995704 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Burak=20Kaan=20K=C3=B6se?= Date: Mon, 15 Mar 2021 12:17:08 +0100 Subject: [PATCH 19/48] Missing SearchBarRenderer usings. --- src/Compatibility/Core/src/iOS/Renderers/SearchBarRenderer.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Compatibility/Core/src/iOS/Renderers/SearchBarRenderer.cs b/src/Compatibility/Core/src/iOS/Renderers/SearchBarRenderer.cs index e96ae87188c5..8a88b3289f89 100644 --- a/src/Compatibility/Core/src/iOS/Renderers/SearchBarRenderer.cs +++ b/src/Compatibility/Core/src/iOS/Renderers/SearchBarRenderer.cs @@ -5,6 +5,7 @@ using Foundation; using UIKit; using Microsoft.Maui.Controls.PlatformConfiguration.iOSSpecific; +using Microsoft.Maui.Platform.iOS; namespace Microsoft.Maui.Controls.Compatibility.Platform.iOS { From 05dad635ce669331a0443cb4d4f094649267472a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Burak=20Kaan=20K=C3=B6se?= Date: Mon, 15 Mar 2021 12:51:21 +0100 Subject: [PATCH 20/48] Added missing usings for iOS renderers. --- src/Compatibility/Core/src/iOS/Cells/EntryCellRenderer.cs | 1 + src/Compatibility/Core/src/iOS/Renderers/DatePickerRenderer.cs | 1 + src/Compatibility/Core/src/iOS/Renderers/EditorRenderer.cs | 1 + src/Compatibility/Core/src/iOS/Renderers/PickerRenderer.cs | 1 + 4 files changed, 4 insertions(+) diff --git a/src/Compatibility/Core/src/iOS/Cells/EntryCellRenderer.cs b/src/Compatibility/Core/src/iOS/Cells/EntryCellRenderer.cs index 2cae3320e78f..6d979e445ff8 100644 --- a/src/Compatibility/Core/src/iOS/Cells/EntryCellRenderer.cs +++ b/src/Compatibility/Core/src/iOS/Cells/EntryCellRenderer.cs @@ -1,6 +1,7 @@ using System; using System.ComponentModel; using Foundation; +using Microsoft.Maui.Platform.iOS; using UIKit; using RectangleF = CoreGraphics.CGRect; diff --git a/src/Compatibility/Core/src/iOS/Renderers/DatePickerRenderer.cs b/src/Compatibility/Core/src/iOS/Renderers/DatePickerRenderer.cs index 2bd7123922e2..50d6d4cff99e 100644 --- a/src/Compatibility/Core/src/iOS/Renderers/DatePickerRenderer.cs +++ b/src/Compatibility/Core/src/iOS/Renderers/DatePickerRenderer.cs @@ -4,6 +4,7 @@ using System.Linq; using Foundation; using Microsoft.Maui.Controls.PlatformConfiguration.iOSSpecific; +using Microsoft.Maui.Platform.iOS; using UIKit; using RectangleF = CoreGraphics.CGRect; diff --git a/src/Compatibility/Core/src/iOS/Renderers/EditorRenderer.cs b/src/Compatibility/Core/src/iOS/Renderers/EditorRenderer.cs index f7bc0ad41f0e..8744c1756ab8 100644 --- a/src/Compatibility/Core/src/iOS/Renderers/EditorRenderer.cs +++ b/src/Compatibility/Core/src/iOS/Renderers/EditorRenderer.cs @@ -2,6 +2,7 @@ using System.ComponentModel; using CoreGraphics; using Foundation; +using Microsoft.Maui.Platform.iOS; using UIKit; using RectangleF = CoreGraphics.CGRect; diff --git a/src/Compatibility/Core/src/iOS/Renderers/PickerRenderer.cs b/src/Compatibility/Core/src/iOS/Renderers/PickerRenderer.cs index cf16f9f2a0c7..44edb1196993 100644 --- a/src/Compatibility/Core/src/iOS/Renderers/PickerRenderer.cs +++ b/src/Compatibility/Core/src/iOS/Renderers/PickerRenderer.cs @@ -8,6 +8,7 @@ using UIKit; using Microsoft.Maui.Controls.PlatformConfiguration.iOSSpecific; using RectangleF = CoreGraphics.CGRect; +using Microsoft.Maui.Platform.iOS; namespace Microsoft.Maui.Controls.Compatibility.Platform.iOS { From 83183cad808fc00b8a1e9759e64d86d59ddde9f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Burak=20Kaan=20K=C3=B6se?= Date: Mon, 15 Mar 2021 13:04:38 +0100 Subject: [PATCH 21/48] more missing references in iOS renderers... --- src/Compatibility/Core/src/iOS/Platform.cs | 1 + src/Compatibility/Core/src/iOS/Renderers/LabelRenderer.cs | 1 + src/Compatibility/Core/src/iOS/Renderers/TimePickerRenderer.cs | 1 + 3 files changed, 3 insertions(+) diff --git a/src/Compatibility/Core/src/iOS/Platform.cs b/src/Compatibility/Core/src/iOS/Platform.cs index ed59a0a6e8c2..1962b88ec42e 100644 --- a/src/Compatibility/Core/src/iOS/Platform.cs +++ b/src/Compatibility/Core/src/iOS/Platform.cs @@ -9,6 +9,7 @@ using RectangleF = CoreGraphics.CGRect; using Microsoft.Maui.Controls.Internals; using Microsoft.Maui.Controls.PlatformConfiguration.iOSSpecific; +using Microsoft.Maui.Platform.iOS; namespace Microsoft.Maui.Controls.Compatibility.Platform.iOS { diff --git a/src/Compatibility/Core/src/iOS/Renderers/LabelRenderer.cs b/src/Compatibility/Core/src/iOS/Renderers/LabelRenderer.cs index 9f636ec1e570..a0218f0c0de8 100644 --- a/src/Compatibility/Core/src/iOS/Renderers/LabelRenderer.cs +++ b/src/Compatibility/Core/src/iOS/Renderers/LabelRenderer.cs @@ -5,6 +5,7 @@ using Foundation; using System.Collections.Generic; using System.Diagnostics; +using Microsoft.Maui.Platform.iOS; #if __MOBILE__ using UIKit; diff --git a/src/Compatibility/Core/src/iOS/Renderers/TimePickerRenderer.cs b/src/Compatibility/Core/src/iOS/Renderers/TimePickerRenderer.cs index 18608fab27e7..f14d08e018b2 100644 --- a/src/Compatibility/Core/src/iOS/Renderers/TimePickerRenderer.cs +++ b/src/Compatibility/Core/src/iOS/Renderers/TimePickerRenderer.cs @@ -6,6 +6,7 @@ using UIKit; using Microsoft.Maui.Controls.PlatformConfiguration.iOSSpecific; using RectangleF = CoreGraphics.CGRect; +using Microsoft.Maui.Platform.iOS; namespace Microsoft.Maui.Controls.Compatibility.Platform.iOS { From c4de5731136b16e1e5d4aaede6d25ca412570d81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Burak=20Kaan=20K=C3=B6se?= Date: Mon, 15 Mar 2021 14:09:50 +0100 Subject: [PATCH 22/48] Removed already ported extension methods in iOS and changed the usages in renderer. --- .../src/iOS/Renderers/ButtonLayoutManager.cs | 6 +- .../src/iOS/Renderers/DatePickerRenderer.cs | 2 +- .../Core/src/iOS/Renderers/EditorRenderer.cs | 6 +- .../Core/src/iOS/Renderers/EntryRenderer.cs | 6 +- .../Core/src/iOS/Renderers/LabelRenderer.cs | 2 +- .../Core/src/iOS/Renderers/PickerRenderer.cs | 6 +- .../src/iOS/Renderers/SearchBarRenderer.cs | 8 +-- .../src/iOS/Renderers/TimePickerRenderer.cs | 2 +- src/Core/src/Platform/iOS/Extensions.cs | 57 ------------------- 9 files changed, 19 insertions(+), 76 deletions(-) diff --git a/src/Compatibility/Core/src/iOS/Renderers/ButtonLayoutManager.cs b/src/Compatibility/Core/src/iOS/Renderers/ButtonLayoutManager.cs index 1544f21c1fd5..4eb18ccb359a 100644 --- a/src/Compatibility/Core/src/iOS/Renderers/ButtonLayoutManager.cs +++ b/src/Compatibility/Core/src/iOS/Renderers/ButtonLayoutManager.cs @@ -210,17 +210,17 @@ internal void UpdateText() var normal = control .GetAttributedTitle(UIControlState.Normal) - .AddCharacterSpacing(text, _element.CharacterSpacing); + .WithCharacterSpacing(_element.CharacterSpacing); var highlighted = control .GetAttributedTitle(UIControlState.Highlighted) - .AddCharacterSpacing(text, _element.CharacterSpacing); + .WithCharacterSpacing(_element.CharacterSpacing); var disabled = control .GetAttributedTitle(UIControlState.Disabled) - .AddCharacterSpacing(text, _element.CharacterSpacing); + .WithCharacterSpacing(_element.CharacterSpacing); normal.AddAttribute( UIStringAttributeKey.ForegroundColor, diff --git a/src/Compatibility/Core/src/iOS/Renderers/DatePickerRenderer.cs b/src/Compatibility/Core/src/iOS/Renderers/DatePickerRenderer.cs index 50d6d4cff99e..f93b8ed04947 100644 --- a/src/Compatibility/Core/src/iOS/Renderers/DatePickerRenderer.cs +++ b/src/Compatibility/Core/src/iOS/Renderers/DatePickerRenderer.cs @@ -215,7 +215,7 @@ protected internal virtual void UpdateFont() void UpdateCharacterSpacing() { - var textAttr = Control.AttributedText.AddCharacterSpacing(Control.Text, Element.CharacterSpacing); + var textAttr = Control.AttributedText.WithCharacterSpacing(Element.CharacterSpacing); if (textAttr != null) Control.AttributedText = textAttr; diff --git a/src/Compatibility/Core/src/iOS/Renderers/EditorRenderer.cs b/src/Compatibility/Core/src/iOS/Renderers/EditorRenderer.cs index 8744c1756ab8..bb8583f12e27 100644 --- a/src/Compatibility/Core/src/iOS/Renderers/EditorRenderer.cs +++ b/src/Compatibility/Core/src/iOS/Renderers/EditorRenderer.cs @@ -73,12 +73,12 @@ protected internal override void UpdatePlaceholderText() protected internal override void UpdateCharacterSpacing() { - var textAttr = TextView.AttributedText.AddCharacterSpacing(Element.Text, Element.CharacterSpacing); + var textAttr = TextView.AttributedText.WithCharacterSpacing(Element.CharacterSpacing); if(textAttr != null) TextView.AttributedText = textAttr; - var placeHolder = _placeholderLabel.AttributedText.AddCharacterSpacing(Element.Placeholder, Element.CharacterSpacing); + var placeHolder = _placeholderLabel.AttributedText.WithCharacterSpacing(Element.CharacterSpacing); if(placeHolder != null) _placeholderLabel.AttributedText = placeHolder; @@ -119,7 +119,7 @@ void CreatePlaceholderLabel() ); _placeholderLabel.TranslatesAutoresizingMaskIntoConstraints = false; - _placeholderLabel.AttributedText = _placeholderLabel.AttributedText.AddCharacterSpacing(Element.Placeholder, Element.CharacterSpacing); + _placeholderLabel.AttributedText = _placeholderLabel.AttributedText.WithCharacterSpacing(Element.CharacterSpacing); Control.AddConstraints(hConstraints); Control.AddConstraints(vConstraints); diff --git a/src/Compatibility/Core/src/iOS/Renderers/EntryRenderer.cs b/src/Compatibility/Core/src/iOS/Renderers/EntryRenderer.cs index 2774d7f272a3..8d4180f07c18 100644 --- a/src/Compatibility/Core/src/iOS/Renderers/EntryRenderer.cs +++ b/src/Compatibility/Core/src/iOS/Renderers/EntryRenderer.cs @@ -360,7 +360,7 @@ protected virtual void UpdatePlaceholder() UpdateAttributedPlaceholder(formatted.ToAttributed(Element, color)); } - UpdateAttributedPlaceholder(Control.AttributedPlaceholder.AddCharacterSpacing(Element.Placeholder, Element.CharacterSpacing)); + UpdateAttributedPlaceholder(Control.AttributedPlaceholder.WithCharacterSpacing(Element.CharacterSpacing)); } protected virtual void UpdateAttributedPlaceholder(NSAttributedString nsAttributedString) => @@ -377,12 +377,12 @@ void UpdateText() void UpdateCharacterSpacing() { - var textAttr = Control.AttributedText.AddCharacterSpacing(Element.Text, Element.CharacterSpacing); + var textAttr = Control.AttributedText.WithCharacterSpacing(Element.CharacterSpacing); if (textAttr != null) Control.AttributedText = textAttr; - var placeHolder = Control.AttributedPlaceholder.AddCharacterSpacing(Element.Placeholder, Element.CharacterSpacing); + var placeHolder = Control.AttributedPlaceholder.WithCharacterSpacing(Element.CharacterSpacing); if (placeHolder != null) UpdateAttributedPlaceholder(placeHolder); diff --git a/src/Compatibility/Core/src/iOS/Renderers/LabelRenderer.cs b/src/Compatibility/Core/src/iOS/Renderers/LabelRenderer.cs index a0218f0c0de8..aa0f24e511c3 100644 --- a/src/Compatibility/Core/src/iOS/Renderers/LabelRenderer.cs +++ b/src/Compatibility/Core/src/iOS/Renderers/LabelRenderer.cs @@ -418,7 +418,7 @@ void UpdateCharacterSpacing() if (string.IsNullOrEmpty(Element.Text)) return; #if __MOBILE__ - var textAttr = Control.AttributedText.AddCharacterSpacing(Element.Text, Element.CharacterSpacing); + var textAttr = Control.AttributedText.WithCharacterSpacing(Element.CharacterSpacing); if (textAttr != null) Control.AttributedText = textAttr; diff --git a/src/Compatibility/Core/src/iOS/Renderers/PickerRenderer.cs b/src/Compatibility/Core/src/iOS/Renderers/PickerRenderer.cs index 44edb1196993..9af263e092e5 100644 --- a/src/Compatibility/Core/src/iOS/Renderers/PickerRenderer.cs +++ b/src/Compatibility/Core/src/iOS/Renderers/PickerRenderer.cs @@ -188,12 +188,12 @@ protected void UpdateCharacterSpacing() if (Control == null) return; - var textAttr = Control.AttributedText.AddCharacterSpacing(Control.Text, Element.CharacterSpacing); + var textAttr = Control.AttributedText.WithCharacterSpacing(Element.CharacterSpacing); if (textAttr != null) Control.AttributedText = textAttr; - var placeHolder = Control.AttributedPlaceholder.AddCharacterSpacing(Element.Title, Element.CharacterSpacing); + var placeHolder = Control.AttributedPlaceholder.WithCharacterSpacing(Element.CharacterSpacing); if (placeHolder != null) UpdateAttributedPlaceholder(placeHolder); @@ -226,7 +226,7 @@ protected internal virtual void UpdatePlaceholder() UpdateAttributedPlaceholder(formatted.ToAttributed(Element, color)); } - UpdateAttributedPlaceholder(Control.AttributedPlaceholder.AddCharacterSpacing(Element.Title, Element.CharacterSpacing)); + UpdateAttributedPlaceholder(Control.AttributedPlaceholder.WithCharacterSpacing(Element.CharacterSpacing)); } protected virtual void UpdateAttributedPlaceholder(NSAttributedString nsAttributedString) => diff --git a/src/Compatibility/Core/src/iOS/Renderers/SearchBarRenderer.cs b/src/Compatibility/Core/src/iOS/Renderers/SearchBarRenderer.cs index 8a88b3289f89..678d29770bce 100644 --- a/src/Compatibility/Core/src/iOS/Renderers/SearchBarRenderer.cs +++ b/src/Compatibility/Core/src/iOS/Renderers/SearchBarRenderer.cs @@ -233,8 +233,8 @@ void UpdateCharacterSpacing() if (_textField == null) return; - _textField.AttributedText = _textField.AttributedText.AddCharacterSpacing(Element.Text, Element.CharacterSpacing); - _textField.AttributedPlaceholder = _textField.AttributedPlaceholder.AddCharacterSpacing(Element.Placeholder, Element.CharacterSpacing); + _textField.AttributedText = _textField.AttributedText.WithCharacterSpacing(Element.CharacterSpacing); + _textField.AttributedPlaceholder = _textField.AttributedPlaceholder.WithCharacterSpacing(Element.CharacterSpacing); } void UpdateHorizontalTextAlignment() @@ -323,14 +323,14 @@ void UpdatePlaceholder() ? targetColor : ColorExtensions.PlaceholderColor.ToColor(); _textField.AttributedPlaceholder = formatted.ToAttributed(Element, color); - _textField.AttributedPlaceholder.AddCharacterSpacing(Element.Placeholder, Element.CharacterSpacing); + _textField.AttributedPlaceholder.WithCharacterSpacing(Element.CharacterSpacing); } else { _textField.AttributedPlaceholder = formatted.ToAttributed(Element, targetColor.IsDefault ? ColorExtensions.PlaceholderColor.ToColor() : targetColor); - _textField.AttributedPlaceholder.AddCharacterSpacing(Element.Placeholder, Element.CharacterSpacing); + _textField.AttributedPlaceholder.WithCharacterSpacing(Element.CharacterSpacing); } } diff --git a/src/Compatibility/Core/src/iOS/Renderers/TimePickerRenderer.cs b/src/Compatibility/Core/src/iOS/Renderers/TimePickerRenderer.cs index f14d08e018b2..ac62039484ab 100644 --- a/src/Compatibility/Core/src/iOS/Renderers/TimePickerRenderer.cs +++ b/src/Compatibility/Core/src/iOS/Renderers/TimePickerRenderer.cs @@ -196,7 +196,7 @@ protected internal virtual void UpdateTextColor() void UpdateCharacterSpacing() { - var textAttr = Control.AttributedText.AddCharacterSpacing(Control.Text, Element.CharacterSpacing); + var textAttr = Control.AttributedText.WithCharacterSpacing(Element.CharacterSpacing); if (textAttr != null) Control.AttributedText = textAttr; diff --git a/src/Core/src/Platform/iOS/Extensions.cs b/src/Core/src/Platform/iOS/Extensions.cs index 9de40f52b42c..29cc2875d174 100644 --- a/src/Core/src/Platform/iOS/Extensions.cs +++ b/src/Core/src/Platform/iOS/Extensions.cs @@ -77,63 +77,6 @@ public static void ApplyKeyboard(this IUITextInputTraits textInput, Keyboard key } } - public static NSMutableAttributedString? AddCharacterSpacing(this NSAttributedString attributedString, string text, double characterSpacing) - { - if (attributedString == null && characterSpacing == 0) - return null; - - NSMutableAttributedString? mutableAttributedString = attributedString as NSMutableAttributedString; - if (attributedString == null || attributedString.Length == 0) - { - mutableAttributedString = text == null ? new NSMutableAttributedString() : new NSMutableAttributedString(text); - } - else - { - mutableAttributedString = new NSMutableAttributedString(attributedString); - - if (!mutableAttributedString.MutableString.ToString().Equals(text)) - { - mutableAttributedString.MutableString.SetString(new NSString(text)); - } - } - - AddKerningAdjustment(mutableAttributedString, text, characterSpacing); - - return mutableAttributedString; - } - - internal static bool HasCharacterAdjustment(this NSMutableAttributedString mutableAttributedString) - { - if (mutableAttributedString == null) - return false; - - NSRange removalRange; - var attributes = mutableAttributedString.GetAttributes(0, out removalRange); - - for (uint i = 0; i < attributes.Count; i++) - if (attributes.Keys[i] is NSString nSString && nSString == UIStringAttributeKey.KerningAdjustment) - return true; - - return false; - } - - internal static void AddKerningAdjustment(NSMutableAttributedString mutableAttributedString, string? text, double characterSpacing) - { - if (!string.IsNullOrEmpty(text)) - { - if (characterSpacing == 0 && !mutableAttributedString.HasCharacterAdjustment()) - return; - - mutableAttributedString.AddAttribute - ( - UIStringAttributeKey.KerningAdjustment, -#pragma warning disable CS8602 // Dereference of a possibly null reference. - NSObject.FromObject(characterSpacing), new NSRange(0, text.Length - 1) -#pragma warning restore CS8602 // Dereference of a possibly null reference. - ); - } - } - public static UIReturnKeyType ToUIReturnKeyType(this ReturnType returnType) { switch (returnType) From 7b57f0ae2cb28d761cde1e0994d495393ee12c66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Burak=20Kaan=20K=C3=B6se?= Date: Mon, 15 Mar 2021 14:13:30 +0100 Subject: [PATCH 23/48] Inverted LogaliczedDigitKeyListener return logic to better one. --- src/Core/src/Platform/Android/LocalizedDigitsKeyListener.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Core/src/Platform/Android/LocalizedDigitsKeyListener.cs b/src/Core/src/Platform/Android/LocalizedDigitsKeyListener.cs index 2df4be445614..b31c5ec78c5a 100644 --- a/src/Core/src/Platform/Android/LocalizedDigitsKeyListener.cs +++ b/src/Core/src/Platform/Android/LocalizedDigitsKeyListener.cs @@ -217,7 +217,7 @@ bool IsDecimalPointChar(char c) } } - return stripped == null ? (filterFormatted != null ? filterFormatted : new String("")) : stripped; + return stripped ?? filterFormatted ?? new String(""); } #pragma warning restore CS8602 // Dereference of a possibly null reference. } From 8b52d740a5d7db03091d51c4928962408ffcaed6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Burak=20Kaan=20K=C3=B6se?= Date: Fri, 19 Mar 2021 02:04:54 +0100 Subject: [PATCH 24/48] Merged main. --- .../Platform/Android/EditTextExtensions.cs | 46 +++++++++++++++---- .../src/Platform/iOS/TextFieldExtensions.cs | 11 ++++- src/Core/tests/DeviceTests/Stubs/EntryStub.cs | 2 - 3 files changed, 46 insertions(+), 13 deletions(-) diff --git a/src/Core/src/Platform/Android/EditTextExtensions.cs b/src/Core/src/Platform/Android/EditTextExtensions.cs index 923dc80950e4..72f47c35fd18 100644 --- a/src/Core/src/Platform/Android/EditTextExtensions.cs +++ b/src/Core/src/Platform/Android/EditTextExtensions.cs @@ -2,6 +2,7 @@ using Android.Text; using Android.Util; using AndroidX.AppCompat.Widget; +using Microsoft.Maui.Platform.Android; namespace Microsoft.Maui { @@ -99,6 +100,11 @@ public static void UpdateIsReadOnly(this AppCompatEditText editText, IEntry entr editText.Focusable = isEditable; } + public static void UpdateKeyboard(this AppCompatEditText editText, IEntry entry) + { + editText.SetInputType(entry); + } + public static void UpdateFont(this AppCompatEditText editText, IEntry entry, IFontManager fontManager) { var font = entry.Font; @@ -122,20 +128,40 @@ public static void UpdateCharacterSpacing(this AppCompatEditText editText, IEdit internal static void SetInputType(this AppCompatEditText editText, IEntry entry) { - editText.InputType = InputTypes.ClassText; - editText.InputType |= InputTypes.TextFlagMultiLine; + if (entry.IsReadOnly) + editText.InputType = InputTypes.Null; + else + { + var keyboard = entry.Keyboard; + var nativeInputTypeToUpdate = keyboard.ToInputType(); - if (entry.IsPassword && ((editText.InputType & InputTypes.ClassText) == InputTypes.ClassText)) - editText.InputType |= InputTypes.TextVariationPassword; + if (!(keyboard is CustomKeyboard)) + { + // TODO: IsSpellCheckEnabled handling must be here. - if (entry.IsPassword && ((editText.InputType & InputTypes.ClassNumber) == InputTypes.ClassNumber)) - editText.InputType |= InputTypes.NumberVariationPassword; + if ((nativeInputTypeToUpdate & InputTypes.TextFlagNoSuggestions) != InputTypes.TextFlagNoSuggestions) + { + if (!entry.IsTextPredictionEnabled) + nativeInputTypeToUpdate |= InputTypes.TextFlagNoSuggestions; + } + } - if (!entry.IsTextPredictionEnabled && ((editText.InputType & InputTypes.TextFlagNoSuggestions) != InputTypes.TextFlagNoSuggestions)) - editText.InputType |= InputTypes.TextFlagNoSuggestions; + if (keyboard == Keyboard.Numeric) + { + editText.KeyListener = LocalizedDigitsKeyListener.Create(editText.InputType); + } - if (entry.IsReadOnly) - editText.InputType = InputTypes.Null; + if (entry.IsPassword) + { + if (((nativeInputTypeToUpdate & InputTypes.ClassText) == InputTypes.ClassText)) + nativeInputTypeToUpdate |= InputTypes.TextVariationPassword; + + if (((nativeInputTypeToUpdate & InputTypes.ClassNumber) == InputTypes.ClassNumber)) + nativeInputTypeToUpdate |= InputTypes.NumberVariationPassword; + } + + editText.InputType = nativeInputTypeToUpdate; + } } } } diff --git a/src/Core/src/Platform/iOS/TextFieldExtensions.cs b/src/Core/src/Platform/iOS/TextFieldExtensions.cs index 3bf91dda39f8..97aedc6a4988 100644 --- a/src/Core/src/Platform/iOS/TextFieldExtensions.cs +++ b/src/Core/src/Platform/iOS/TextFieldExtensions.cs @@ -1,4 +1,5 @@ -using UIKit; +using Microsoft.Maui.Platform.iOS; +using UIKit; namespace Microsoft.Maui { @@ -83,6 +84,14 @@ public static void UpdateCharacterSpacing(this UITextField textField, IText text textField.AttributedText = textAttr; } + public static void UpdateKeyboard(this UITextField textField, IEntry entry) + { + var keyboard = entry.Keyboard; + + textField.ApplyKeyboard(keyboard); + textField.ReloadInputViews(); + } + public static void UpdateFont(this UITextField textField, IText textView, IFontManager fontManager) { var uiFont = fontManager.GetFont(textView.Font); diff --git a/src/Core/tests/DeviceTests/Stubs/EntryStub.cs b/src/Core/tests/DeviceTests/Stubs/EntryStub.cs index 3c71eb0d7bc1..fe720e1315df 100644 --- a/src/Core/tests/DeviceTests/Stubs/EntryStub.cs +++ b/src/Core/tests/DeviceTests/Stubs/EntryStub.cs @@ -35,8 +35,6 @@ public string Text void OnTextChanged(string oldValue, string newValue) => TextChanged?.Invoke(this, new StubPropertyChangedEventArgs(oldValue, newValue)); - public Font Font { get; set; } - public Keyboard Keyboard { get; set; } = Keyboard.Default; } } \ No newline at end of file From 5555ab75dbfd924fef0fe89ba2c6abd634be5423 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Sua=CC=81rez=20Ruiz?= Date: Tue, 6 Apr 2021 10:30:48 +0200 Subject: [PATCH 25/48] Fix build errors --- .../Platform/Android/EditTextExtensions.cs | 4 ---- .../Platform/Android/KeyboardExtensions.cs | 12 ++++------ .../Android/LocalizedDigitsKeyListener.cs | 24 +++++++++---------- .../{Extensions.cs => KeyboardExtensions.cs} | 12 ++++------ .../src/Platform/iOS/TextFieldExtensions.cs | 3 +-- .../Entry/EntryHandlerTests.Android.cs | 2 -- .../tests/DeviceTests/Stubs/EditorStub.cs | 3 ++- 7 files changed, 23 insertions(+), 37 deletions(-) rename src/Core/src/Platform/iOS/{Extensions.cs => KeyboardExtensions.cs} (95%) diff --git a/src/Core/src/Platform/Android/EditTextExtensions.cs b/src/Core/src/Platform/Android/EditTextExtensions.cs index fd32f0c65aae..68e9d41a6599 100644 --- a/src/Core/src/Platform/Android/EditTextExtensions.cs +++ b/src/Core/src/Platform/Android/EditTextExtensions.cs @@ -4,7 +4,6 @@ using Android.Text; using Android.Util; using AndroidX.AppCompat.Widget; -using Microsoft.Maui.Platform.Android; namespace Microsoft.Maui { @@ -140,9 +139,6 @@ public static void UpdateKeyboard(this AppCompatEditText editText, IEntry entry) editText.SetInputType(entry); } - public static void UpdateFont(this AppCompatEditText editText, IEntry entry, IFontManager fontManager) => - editText.UpdateFont(entry.Font, fontManager); - public static void UpdateIsReadOnly(this AppCompatEditText editText, IEditor editor) { bool isReadOnly = !editor.IsReadOnly; diff --git a/src/Core/src/Platform/Android/KeyboardExtensions.cs b/src/Core/src/Platform/Android/KeyboardExtensions.cs index 0acf3d56ede6..b1bda5deb64f 100644 --- a/src/Core/src/Platform/Android/KeyboardExtensions.cs +++ b/src/Core/src/Platform/Android/KeyboardExtensions.cs @@ -1,9 +1,6 @@ -using System; -using System.Collections.Generic; -using System.Text; -using Android.Text; +using Android.Text; -namespace Microsoft.Maui.Platform.Android +namespace Microsoft.Maui { public static class KeyboardExtensions { @@ -75,10 +72,10 @@ public static InputTypes ToInputType(this Keyboard self) if (custom.Flags != KeyboardFlags.All) { if (capitalizedWordsEnabled) - result = result | InputTypes.TextFlagCapWords; + result |= InputTypes.TextFlagCapWords; if (capitalizedCharacterEnabled) - result = result | InputTypes.TextFlagCapCharacters; + result |= InputTypes.TextFlagCapCharacters; } } else @@ -86,6 +83,7 @@ public static InputTypes ToInputType(this Keyboard self) // Should never happens result = InputTypes.TextVariationNormal; } + return result; } } diff --git a/src/Core/src/Platform/Android/LocalizedDigitsKeyListener.cs b/src/Core/src/Platform/Android/LocalizedDigitsKeyListener.cs index b31c5ec78c5a..72f77a54d0aa 100644 --- a/src/Core/src/Platform/Android/LocalizedDigitsKeyListener.cs +++ b/src/Core/src/Platform/Android/LocalizedDigitsKeyListener.cs @@ -4,7 +4,7 @@ using Java.Lang; using Java.Text; -namespace Microsoft.Maui.Platform.Android +namespace Microsoft.Maui { public class LocalizedDigitsKeyListener : NumberKeyListener { @@ -14,8 +14,8 @@ public class LocalizedDigitsKeyListener : NumberKeyListener // but we'll make it easy to localize the sign in the future just in case const char SignCharacter = '-'; - static Dictionary? s_unsignedCache; - static Dictionary? s_signedCache; + static Dictionary? UnsignedCache; + static Dictionary? SignedCache; static char GetDecimalSeparator() { @@ -57,18 +57,18 @@ public static NumberKeyListener Create(InputTypes inputTypes) public static LocalizedDigitsKeyListener GetInstance(InputTypes inputTypes, char decimalSeparator) { - if (s_signedCache == null) - s_signedCache = new Dictionary(); + if (SignedCache == null) + SignedCache = new Dictionary(); if ((inputTypes & InputTypes.NumberFlagSigned) != 0) { - return GetInstance(inputTypes, decimalSeparator, ref s_signedCache); + return GetInstance(inputTypes, decimalSeparator, ref SignedCache); } - if (s_unsignedCache == null) - s_unsignedCache = new Dictionary(); + if (UnsignedCache == null) + UnsignedCache = new Dictionary(); - return GetInstance(inputTypes, decimalSeparator, ref s_unsignedCache); + return GetInstance(inputTypes, decimalSeparator, ref UnsignedCache); } static LocalizedDigitsKeyListener GetInstance(InputTypes inputTypes, char decimalSeparator, ref Dictionary cache) @@ -101,12 +101,10 @@ protected override char[] GetAcceptedChars() { if ((InputType & InputTypes.NumberFlagSigned) == 0) { - return _acceptedChars ?? - (_acceptedChars = new[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', _decimalSeparator }); + return _acceptedChars ??= new[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', _decimalSeparator }; } - return _acceptedChars ?? - (_acceptedChars = new[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', SignCharacter, _decimalSeparator }); + return _acceptedChars ??= new[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', SignCharacter, _decimalSeparator }; } static bool IsSignChar(char c) diff --git a/src/Core/src/Platform/iOS/Extensions.cs b/src/Core/src/Platform/iOS/KeyboardExtensions.cs similarity index 95% rename from src/Core/src/Platform/iOS/Extensions.cs rename to src/Core/src/Platform/iOS/KeyboardExtensions.cs index 29cc2875d174..96ddb1866d28 100644 --- a/src/Core/src/Platform/iOS/Extensions.cs +++ b/src/Core/src/Platform/iOS/KeyboardExtensions.cs @@ -1,12 +1,8 @@ -using System; -using System.Collections.Generic; -using System.Text; -using Foundation; -using UIKit; +using UIKit; -namespace Microsoft.Maui.Platform.iOS +namespace Microsoft.Maui { - public static class Extensions + public static class KeyboardExtensions { public static void ApplyKeyboard(this IUITextInput textInput, Keyboard keyboard) { @@ -98,4 +94,4 @@ public static UIReturnKeyType ToUIReturnKeyType(this ReturnType returnType) } } } -} +} \ No newline at end of file diff --git a/src/Core/src/Platform/iOS/TextFieldExtensions.cs b/src/Core/src/Platform/iOS/TextFieldExtensions.cs index 896ea98f6498..b06285989510 100644 --- a/src/Core/src/Platform/iOS/TextFieldExtensions.cs +++ b/src/Core/src/Platform/iOS/TextFieldExtensions.cs @@ -1,5 +1,4 @@ -using Microsoft.Maui.Platform.iOS; -using UIKit; +using UIKit; namespace Microsoft.Maui { diff --git a/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.Android.cs b/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.Android.cs index 765ed3ed4ac4..2afc3dcf52a7 100644 --- a/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.Android.cs +++ b/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.Android.cs @@ -1,7 +1,5 @@ using System.Threading.Tasks; using System.Linq; -using System.Threading.Tasks; -using Android.Graphics.Drawables; using Android.Text; using Android.Text.Method; using Android.Views.InputMethods; diff --git a/src/Core/tests/DeviceTests/Stubs/EditorStub.cs b/src/Core/tests/DeviceTests/Stubs/EditorStub.cs index f9177e48e8be..49a1b5968f03 100644 --- a/src/Core/tests/DeviceTests/Stubs/EditorStub.cs +++ b/src/Core/tests/DeviceTests/Stubs/EditorStub.cs @@ -28,10 +28,11 @@ public string Text public bool IsTextPredictionEnabled { get; set; } + public Keyboard Keyboard { get; set; } + public event EventHandler> TextChanged; void OnTextChanged(string oldValue, string newValue) => TextChanged?.Invoke(this, new StubPropertyChangedEventArgs(oldValue, newValue)); - } } \ No newline at end of file From 85d6ee1941136a0c9083ca22802738b5e4190417 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Sua=CC=81rez=20Ruiz?= Date: Tue, 6 Apr 2021 10:32:55 +0200 Subject: [PATCH 26/48] Added TODO --- src/Core/src/Platform/Android/KeyboardExtensions.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Core/src/Platform/Android/KeyboardExtensions.cs b/src/Core/src/Platform/Android/KeyboardExtensions.cs index b1bda5deb64f..adbcce74e10b 100644 --- a/src/Core/src/Platform/Android/KeyboardExtensions.cs +++ b/src/Core/src/Platform/Android/KeyboardExtensions.cs @@ -42,6 +42,8 @@ public static InputTypes ToInputType(this Keyboard self) if (!capitalizedSentenceEnabled && !spellcheckEnabled && suggestionsEnabled) { // Due to the nature of android, TextFlagAutoCorrect includes Spellcheck + + // TODO: Port Logger // Log.Warning(null, "On Android, KeyboardFlags.Suggestions enables KeyboardFlags.Spellcheck as well due to a platform limitation."); result = InputTypes.ClassText | InputTypes.TextFlagAutoCorrect; } From fef77f611351b01dc3e5733c472fb312554d6943 Mon Sep 17 00:00:00 2001 From: Shane Neuville Date: Tue, 6 Apr 2021 17:31:38 -0500 Subject: [PATCH 27/48] - fix compile errors --- src/Compatibility/Core/src/Android/Cells/EntryCellRenderer.cs | 1 - src/Compatibility/Core/src/Android/PopupManager.cs | 1 - src/Compatibility/Core/src/Android/Renderers/EditorRenderer.cs | 1 - src/Compatibility/Core/src/Android/Renderers/EntryRenderer.cs | 1 - .../Core/src/Android/Renderers/SearchBarRenderer.cs | 1 - .../Core/src/Android/Renderers/SearchHandlerAppearanceTracker.cs | 1 - 6 files changed, 6 deletions(-) diff --git a/src/Compatibility/Core/src/Android/Cells/EntryCellRenderer.cs b/src/Compatibility/Core/src/Android/Cells/EntryCellRenderer.cs index 36d4d5bea45a..ba2ce1fb8376 100644 --- a/src/Compatibility/Core/src/Android/Cells/EntryCellRenderer.cs +++ b/src/Compatibility/Core/src/Android/Cells/EntryCellRenderer.cs @@ -3,7 +3,6 @@ using Android.Text; using Android.Text.Method; using Android.Views; -using Microsoft.Maui.Platform.Android; namespace Microsoft.Maui.Controls.Compatibility.Platform.Android { diff --git a/src/Compatibility/Core/src/Android/PopupManager.cs b/src/Compatibility/Core/src/Android/PopupManager.cs index d3885ea07172..7798f3d275cf 100644 --- a/src/Compatibility/Core/src/Android/PopupManager.cs +++ b/src/Compatibility/Core/src/Android/PopupManager.cs @@ -7,7 +7,6 @@ using Android.Views; using Android.Widget; using Microsoft.Maui.Controls.Internals; -using Microsoft.Maui.Platform.Android; using AppCompatActivity = AndroidX.AppCompat.App.AppCompatActivity; using AppCompatAlertDialog = AndroidX.AppCompat.App.AlertDialog; diff --git a/src/Compatibility/Core/src/Android/Renderers/EditorRenderer.cs b/src/Compatibility/Core/src/Android/Renderers/EditorRenderer.cs index 890ca740b802..b056b8895c86 100644 --- a/src/Compatibility/Core/src/Android/Renderers/EditorRenderer.cs +++ b/src/Compatibility/Core/src/Android/Renderers/EditorRenderer.cs @@ -9,7 +9,6 @@ using Android.Views.InputMethods; using Android.Widget; using Java.Lang; -using Microsoft.Maui.Platform.Android; namespace Microsoft.Maui.Controls.Compatibility.Platform.Android { diff --git a/src/Compatibility/Core/src/Android/Renderers/EntryRenderer.cs b/src/Compatibility/Core/src/Android/Renderers/EntryRenderer.cs index 68ef89718225..9231a6fee250 100644 --- a/src/Compatibility/Core/src/Android/Renderers/EntryRenderer.cs +++ b/src/Compatibility/Core/src/Android/Renderers/EntryRenderer.cs @@ -12,7 +12,6 @@ using AndroidX.Core.Content; using Java.Lang; using Microsoft.Maui.Controls.PlatformConfiguration.AndroidSpecific; -using Microsoft.Maui.Platform.Android; namespace Microsoft.Maui.Controls.Compatibility.Platform.Android { diff --git a/src/Compatibility/Core/src/Android/Renderers/SearchBarRenderer.cs b/src/Compatibility/Core/src/Android/Renderers/SearchBarRenderer.cs index 6c34385e19cd..bdf2336ffe7a 100644 --- a/src/Compatibility/Core/src/Android/Renderers/SearchBarRenderer.cs +++ b/src/Compatibility/Core/src/Android/Renderers/SearchBarRenderer.cs @@ -8,7 +8,6 @@ using Android.Util; using Android.Views; using Android.Widget; -using Microsoft.Maui.Platform.Android; namespace Microsoft.Maui.Controls.Compatibility.Platform.Android { diff --git a/src/Compatibility/Core/src/Android/Renderers/SearchHandlerAppearanceTracker.cs b/src/Compatibility/Core/src/Android/Renderers/SearchHandlerAppearanceTracker.cs index adc963654211..e756ef38b30b 100644 --- a/src/Compatibility/Core/src/Android/Renderers/SearchHandlerAppearanceTracker.cs +++ b/src/Compatibility/Core/src/Android/Renderers/SearchHandlerAppearanceTracker.cs @@ -12,7 +12,6 @@ using Android.Views; using Android.Widget; using Microsoft.Maui.Controls.Internals; -using Microsoft.Maui.Platform.Android; using AImageButton = Android.Widget.ImageButton; using AView = Android.Views.View; From 924092b68431598c04a4b7381fd70c8a9d2be975 Mon Sep 17 00:00:00 2001 From: Matthew Leibowitz Date: Wed, 7 Apr 2021 01:26:42 +0200 Subject: [PATCH 28/48] Seems CheckBox is also done on Windows --- src/Compatibility/Core/src/AppHostBuilderExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Compatibility/Core/src/AppHostBuilderExtensions.cs b/src/Compatibility/Core/src/AppHostBuilderExtensions.cs index c8cbd655e06f..eed04808eb89 100644 --- a/src/Compatibility/Core/src/AppHostBuilderExtensions.cs +++ b/src/Compatibility/Core/src/AppHostBuilderExtensions.cs @@ -13,9 +13,9 @@ public static class AppHostBuilderExtensions typeof(ContentPage), typeof(Page), typeof(Label), + typeof(CheckBox), #if !WINDOWS typeof(ActivityIndicator), - typeof(CheckBox), typeof(DatePicker), typeof(Editor), typeof(Entry), From ccb341a386e7a47c9c0b281e0d7e97a5034284e9 Mon Sep 17 00:00:00 2001 From: Matthew Leibowitz Date: Wed, 7 Apr 2021 01:27:26 +0200 Subject: [PATCH 29/48] Added a enw attribute for incomplete handlers --- .../src/Attributes/MissingMapperAttribute.cs | 20 +++++++++++++++++++ .../{ => Attributes}/PortHandlerAttribute.cs | 0 2 files changed, 20 insertions(+) create mode 100644 src/Core/src/Attributes/MissingMapperAttribute.cs rename src/Core/src/{ => Attributes}/PortHandlerAttribute.cs (100%) diff --git a/src/Core/src/Attributes/MissingMapperAttribute.cs b/src/Core/src/Attributes/MissingMapperAttribute.cs new file mode 100644 index 000000000000..d6102a77529d --- /dev/null +++ b/src/Core/src/Attributes/MissingMapperAttribute.cs @@ -0,0 +1,20 @@ +using System; + +namespace Microsoft.Maui +{ + [AttributeUsage(AttributeTargets.All, AllowMultiple = true)] + public class MissingMapperAttribute : Attribute + { + public MissingMapperAttribute() + { + + } + + public MissingMapperAttribute(string description) + { + Description = description; + } + + public string? Description { get; set; } + } +} \ No newline at end of file diff --git a/src/Core/src/PortHandlerAttribute.cs b/src/Core/src/Attributes/PortHandlerAttribute.cs similarity index 100% rename from src/Core/src/PortHandlerAttribute.cs rename to src/Core/src/Attributes/PortHandlerAttribute.cs From a6890b105b1592ddb8c2ece6acbf12dfe7bf69d7 Mon Sep 17 00:00:00 2001 From: Matthew Leibowitz Date: Wed, 7 Apr 2021 01:28:12 +0200 Subject: [PATCH 30/48] Clean up the handler code a tiny bit --- .../src/Core/HandlerImpl/Button.Impl.cs | 2 +- .../src/Core/HandlerImpl/DatePicker.Impl.cs | 2 +- .../src/Core/HandlerImpl/Editor.Impl.cs | 2 +- .../src/Core/HandlerImpl/Entry.Impl.cs | 2 +- .../src/Core/HandlerImpl/Label.Impl.cs | 13 +--------- .../src/Core/HandlerImpl/Picker.Impl.cs | 2 ++ .../src/Core/HandlerImpl/SearchBar.Impl.cs | 4 ++- .../src/Core/HandlerImpl/TimePicker.Impl.cs | 2 +- src/Controls/src/Core/Picker.cs | 13 +++++++--- src/Core/src/Core/IDatePicker.cs | 12 +-------- src/Core/src/Core/IEditor.cs | 5 ---- src/Core/src/Core/IEntry.cs | 7 +----- src/Core/src/Core/ILabel.cs | 1 + src/Core/src/Core/IPicker.cs | 7 +----- src/Core/src/Core/ISearchBar.cs | 2 +- src/Core/src/Core/IText.cs | 17 +------------ src/Core/src/Core/ITextInput.cs | 5 ++++ src/Core/src/Core/ITextStyle.cs | 23 +++++++++++++++++ src/Core/src/Core/ITimePicker.cs | 12 +-------- .../ActivityIndicatorHandler.Android.cs | 10 ++++++++ .../ActivityIndicatorHandler.Standard.cs | 3 +++ .../ActivityIndicatorHandler.Windows.cs | 6 +++++ .../ActivityIndicatorHandler.cs | 12 +-------- .../ActivityIndicatorHandler.iOS.cs | 10 ++++++++ .../Handlers/Button/ButtonHandler.Android.cs | 5 ---- .../Handlers/Button/ButtonHandler.Standard.cs | 1 - .../Handlers/Button/ButtonHandler.Windows.cs | 2 ++ src/Core/src/Handlers/Button/ButtonHandler.cs | 6 +++-- .../src/Handlers/Button/ButtonHandler.iOS.cs | 5 ---- .../CheckBox/CheckBoxHandler.Android.cs | 17 ++++++++----- .../CheckBox/CheckBoxHandler.Standard.cs | 2 ++ .../CheckBox/CheckBoxHandler.Windows.cs | 19 ++++++++++++++ .../src/Handlers/CheckBox/CheckBoxHandler.cs | 7 +----- .../Handlers/CheckBox/CheckBoxHandler.iOS.cs | 5 ++++ .../DatePicker/DatePickerHandler.Android.cs | 3 +++ .../DatePicker/DatePickerHandler.Standard.cs | 1 + .../DatePicker/DatePickerHandler.Windows.cs | 11 ++++++++ .../Handlers/DatePicker/DatePickerHandler.cs | 9 ++++--- .../DatePicker/DatePickerHandler.iOS.cs | 3 +++ .../Handlers/Editor/EditorHandler.Android.cs | 3 +++ .../Handlers/Editor/EditorHandler.Standard.cs | 1 + .../Handlers/Editor/EditorHandler.Windows.cs | 18 +++++++++++++ src/Core/src/Handlers/Editor/EditorHandler.cs | 13 +++++----- .../src/Handlers/Editor/EditorHandler.iOS.cs | 3 +++ .../Handlers/Entry/EntryHandler.Windows.cs | 23 +++++++++++++++++ src/Core/src/Handlers/Entry/EntryHandler.cs | 14 +++++------ .../Handlers/Label/LabelHandler.Windows.cs | 8 +++++- src/Core/src/Handlers/Label/LabelHandler.cs | 8 +++--- .../Handlers/Picker/PickerHandler.Android.cs | 6 +++++ .../Handlers/Picker/PickerHandler.Standard.cs | 2 ++ .../Handlers/Picker/PickerHandler.Windows.cs | 11 ++++++++ src/Core/src/Handlers/Picker/PickerHandler.cs | 6 +++-- .../src/Handlers/Picker/PickerHandler.iOS.cs | 6 +++++ .../ProgressBar/ProgressBarHandler.Android.cs | 5 ++++ .../ProgressBarHandler.Standard.cs | 2 ++ .../ProgressBar/ProgressBarHandler.Windows.cs | 3 +++ .../ProgressBar/ProgressBarHandler.cs | 5 ---- .../ProgressBar/ProgressBarHandler.iOS.cs | 5 ++++ .../SearchBar/SearchBarHandler.Android.cs | 12 +++++++++ .../SearchBar/SearchBarHandler.Standard.cs | 4 +++ .../SearchBar/SearchBarHandler.Windows.cs | 19 ++++++++++++++ .../Handlers/SearchBar/SearchBarHandler.cs | 10 +++++--- .../SearchBar/SearchBarHandler.iOS.cs | 12 +++++++++ .../Handlers/Slider/SliderHandler.Windows.cs | 11 ++++++++ src/Core/src/Handlers/Slider/SliderHandler.cs | 8 +++--- .../Stepper/StepperHandler.Windows.cs | 7 ++++++ .../src/Handlers/Stepper/StepperHandler.cs | 6 ++--- .../Handlers/Switch/SwitchHandler.Windows.cs | 5 ++++ src/Core/src/Handlers/Switch/SwitchHandler.cs | 2 +- .../TimePicker/TimePickerHandler.Android.cs | 3 +++ .../TimePicker/TimePickerHandler.Standard.cs | 1 + .../TimePicker/TimePickerHandler.Windows.cs | 10 ++++++++ .../Handlers/TimePicker/TimePickerHandler.cs | 5 ++-- .../TimePicker/TimePickerHandler.iOS.cs | 3 +++ .../src/Handlers/View/ViewHandler.Android.cs | 8 ++---- src/Core/src/Handlers/View/ViewHandler.cs | 25 ++++++------------- .../Standard/ActivityIndicatorExtensions.cs | 15 ----------- .../Platform/Standard/CheckBoxExtensions.cs | 15 ----------- .../src/Platform/Standard/PickerExtensions.cs | 15 ----------- .../Standard/ProgressBarExtensions.cs | 10 -------- .../src/Platform/Standard/ViewExtensions.cs | 4 +-- .../Windows/ActivityIndicatorExtensions.cs | 17 ------------- .../Platform/Windows/ProgressBarExtensions.cs | 15 ----------- .../src/Platform/Windows/ViewExtensions.cs | 2 +- 84 files changed, 388 insertions(+), 268 deletions(-) create mode 100644 src/Core/src/Core/ITextStyle.cs delete mode 100644 src/Core/src/Platform/Standard/ActivityIndicatorExtensions.cs delete mode 100644 src/Core/src/Platform/Standard/CheckBoxExtensions.cs delete mode 100644 src/Core/src/Platform/Standard/PickerExtensions.cs delete mode 100644 src/Core/src/Platform/Standard/ProgressBarExtensions.cs delete mode 100644 src/Core/src/Platform/Windows/ActivityIndicatorExtensions.cs delete mode 100644 src/Core/src/Platform/Windows/ProgressBarExtensions.cs diff --git a/src/Controls/src/Core/HandlerImpl/Button.Impl.cs b/src/Controls/src/Core/HandlerImpl/Button.Impl.cs index da7df1b858a4..260c2a611e77 100644 --- a/src/Controls/src/Core/HandlerImpl/Button.Impl.cs +++ b/src/Controls/src/Core/HandlerImpl/Button.Impl.cs @@ -17,6 +17,6 @@ void IButton.Released() (this as IButtonController).SendReleased(); } - Font IText.Font => Font; + Font ITextStyle.Font => Font; } } \ No newline at end of file diff --git a/src/Controls/src/Core/HandlerImpl/DatePicker.Impl.cs b/src/Controls/src/Core/HandlerImpl/DatePicker.Impl.cs index c5573bbe8bcf..9a0f0ce67f4f 100644 --- a/src/Controls/src/Core/HandlerImpl/DatePicker.Impl.cs +++ b/src/Controls/src/Core/HandlerImpl/DatePicker.Impl.cs @@ -4,6 +4,6 @@ public partial class DatePicker : IDatePicker { Font? _font; - Font IDatePicker.Font => _font ??= Font.OfSize(FontFamily, FontSize).WithAttributes(FontAttributes); + Font ITextStyle.Font => _font ??= Font.OfSize(FontFamily, FontSize).WithAttributes(FontAttributes); } } \ No newline at end of file diff --git a/src/Controls/src/Core/HandlerImpl/Editor.Impl.cs b/src/Controls/src/Core/HandlerImpl/Editor.Impl.cs index 62f659d845aa..d06b0ae9180d 100644 --- a/src/Controls/src/Core/HandlerImpl/Editor.Impl.cs +++ b/src/Controls/src/Core/HandlerImpl/Editor.Impl.cs @@ -4,6 +4,6 @@ public partial class Editor : IEditor { Font? _font; - Font IText.Font => _font ??= Font.OfSize(FontFamily, FontSize).WithAttributes(FontAttributes); + Font ITextStyle.Font => _font ??= Font.OfSize(FontFamily, FontSize).WithAttributes(FontAttributes); } } \ No newline at end of file diff --git a/src/Controls/src/Core/HandlerImpl/Entry.Impl.cs b/src/Controls/src/Core/HandlerImpl/Entry.Impl.cs index ca398b37d16d..23124142a31d 100644 --- a/src/Controls/src/Core/HandlerImpl/Entry.Impl.cs +++ b/src/Controls/src/Core/HandlerImpl/Entry.Impl.cs @@ -4,6 +4,6 @@ public partial class Entry : IEntry { Font? _font; - Font IText.Font => _font ??= Font.OfSize(FontFamily, FontSize).WithAttributes(FontAttributes); + Font ITextStyle.Font => _font ??= Font.OfSize(FontFamily, FontSize).WithAttributes(FontAttributes); } } \ No newline at end of file diff --git a/src/Controls/src/Core/HandlerImpl/Label.Impl.cs b/src/Controls/src/Core/HandlerImpl/Label.Impl.cs index 1ce5f752ec35..f51910de327c 100644 --- a/src/Controls/src/Core/HandlerImpl/Label.Impl.cs +++ b/src/Controls/src/Core/HandlerImpl/Label.Impl.cs @@ -4,17 +4,6 @@ public partial class Label : ILabel { Font? _font; - Font IText.Font - { - get - { - if (_font == null) - { - _font = Font.OfSize(FontFamily, FontSize).WithAttributes(FontAttributes); - } - - return _font.Value; - } - } + Font ITextStyle.Font => _font ??= Font.OfSize(FontFamily, FontSize).WithAttributes(FontAttributes); } } \ No newline at end of file diff --git a/src/Controls/src/Core/HandlerImpl/Picker.Impl.cs b/src/Controls/src/Core/HandlerImpl/Picker.Impl.cs index b98e185c368d..ebaacb0cd48a 100644 --- a/src/Controls/src/Core/HandlerImpl/Picker.Impl.cs +++ b/src/Controls/src/Core/HandlerImpl/Picker.Impl.cs @@ -2,6 +2,8 @@ { public partial class Picker : IPicker { + Font? _font; + Font ITextStyle.Font => _font ??= Font.OfSize(FontFamily, FontSize).WithAttributes(FontAttributes); } } \ No newline at end of file diff --git a/src/Controls/src/Core/HandlerImpl/SearchBar.Impl.cs b/src/Controls/src/Core/HandlerImpl/SearchBar.Impl.cs index 7ac8d035e229..bd383aebde42 100644 --- a/src/Controls/src/Core/HandlerImpl/SearchBar.Impl.cs +++ b/src/Controls/src/Core/HandlerImpl/SearchBar.Impl.cs @@ -4,6 +4,8 @@ public partial class SearchBar : ISearchBar { Font? _font; - Font IText.Font => _font ??= Font.OfSize(FontFamily, FontSize).WithAttributes(FontAttributes); + Font ITextStyle.Font => _font ??= Font.OfSize(FontFamily, FontSize).WithAttributes(FontAttributes); + + bool ITextInput.IsTextPredictionEnabled => true; } } \ No newline at end of file diff --git a/src/Controls/src/Core/HandlerImpl/TimePicker.Impl.cs b/src/Controls/src/Core/HandlerImpl/TimePicker.Impl.cs index c06ca3e21c38..9587c87dd18e 100644 --- a/src/Controls/src/Core/HandlerImpl/TimePicker.Impl.cs +++ b/src/Controls/src/Core/HandlerImpl/TimePicker.Impl.cs @@ -4,6 +4,6 @@ public partial class TimePicker : ITimePicker { Font? _font; - Font ITimePicker.Font => _font ??= Font.OfSize(FontFamily, FontSize).WithAttributes(FontAttributes); + Font ITextStyle.Font => _font ??= Font.OfSize(FontFamily, FontSize).WithAttributes(FontAttributes); } } \ No newline at end of file diff --git a/src/Controls/src/Core/Picker.cs b/src/Controls/src/Core/Picker.cs index c50dedbf1a2b..92c4434c48e3 100644 --- a/src/Controls/src/Core/Picker.cs +++ b/src/Controls/src/Core/Picker.cs @@ -81,19 +81,26 @@ public virtual string UpdateFormsText(string source, TextTransform textTransform => TextTransformUtilites.GetTransformedText(source, textTransform); void IFontElement.OnFontFamilyChanged(string oldValue, string newValue) => - InvalidateMeasureInternal(InvalidationTrigger.MeasureChanged); + HandleFontChanged(); void IFontElement.OnFontSizeChanged(double oldValue, double newValue) => - InvalidateMeasureInternal(InvalidationTrigger.MeasureChanged); + HandleFontChanged(); void IFontElement.OnFontChanged(Font oldValue, Font newValue) => - InvalidateMeasureInternal(InvalidationTrigger.MeasureChanged); + HandleFontChanged(); double IFontElement.FontSizeDefaultValueCreator() => Device.GetNamedSize(NamedSize.Default, (Picker)this); void IFontElement.OnFontAttributesChanged(FontAttributes oldValue, FontAttributes newValue) => + HandleFontChanged(); + + void HandleFontChanged() + { + // Null out the Maui font value so it will be recreated next time it's accessed + _font = null; InvalidateMeasureInternal(InvalidationTrigger.MeasureChanged); + } void ITextElement.OnTextTransformChanged(TextTransform oldValue, TextTransform newValue) => InvalidateMeasureInternal(InvalidationTrigger.MeasureChanged); diff --git a/src/Core/src/Core/IDatePicker.cs b/src/Core/src/Core/IDatePicker.cs index 35c0f61790d7..78c1efac26a2 100644 --- a/src/Core/src/Core/IDatePicker.cs +++ b/src/Core/src/Core/IDatePicker.cs @@ -5,7 +5,7 @@ namespace Microsoft.Maui /// /// Represents a View that allows the user to select a date. /// - public interface IDatePicker : IView + public interface IDatePicker : IView, ITextStyle { /// /// Gets the format of the date to display to the user. @@ -26,15 +26,5 @@ public interface IDatePicker : IView /// Gets the maximum DateTime selectable. /// DateTime MaximumDate { get; } - - /// - /// Gets the spacing between characters of the text. - /// - double CharacterSpacing { get; } - - /// - /// Gets the font family, style and size of the font. - /// - Font Font { get; } } } \ No newline at end of file diff --git a/src/Core/src/Core/IEditor.cs b/src/Core/src/Core/IEditor.cs index 14ea5067c40e..a696f16a29e1 100644 --- a/src/Core/src/Core/IEditor.cs +++ b/src/Core/src/Core/IEditor.cs @@ -9,10 +9,5 @@ public interface IEditor : IView, ITextInput /// Gets or sets the placeholder text color. /// Color PlaceholderColor { get; set; } - - /// - /// Gets a value that controls whether text prediction and automatic text correction is on or off. - /// - bool IsTextPredictionEnabled { get; } } } \ No newline at end of file diff --git a/src/Core/src/Core/IEntry.cs b/src/Core/src/Core/IEntry.cs index 9b4b1635ae07..7472ec4ba3e6 100644 --- a/src/Core/src/Core/IEntry.cs +++ b/src/Core/src/Core/IEntry.cs @@ -3,18 +3,13 @@ /// /// Represents a View that is used for single-line text input. /// - public interface IEntry : IView, IText, ITextInput, ITextAlignment + public interface IEntry : IView, ITextInput, ITextAlignment { /// /// Gets a value that indicates if the entry should visually obscure typed text. /// bool IsPassword { get; } - /// - /// Gets a value that controls whether text prediction and automatic text correction is on or off. - /// - bool IsTextPredictionEnabled { get; } - /// /// Gets an enumeration value that controls the appearance of the return button. /// diff --git a/src/Core/src/Core/ILabel.cs b/src/Core/src/Core/ILabel.cs index b38ef2149326..e2fc4084b1d0 100644 --- a/src/Core/src/Core/ILabel.cs +++ b/src/Core/src/Core/ILabel.cs @@ -20,6 +20,7 @@ public interface ILabel : IView, IText, ITextAlignment, IPadding /// Underline and strike-through text decorations can be applied. /// TextDecorations TextDecorations { get; } + /// /// Gets the line height applied to the Label. /// Underline and strike-through text decorations can be applied. diff --git a/src/Core/src/Core/IPicker.cs b/src/Core/src/Core/IPicker.cs index 6a542a2070ed..5936fae95ea6 100644 --- a/src/Core/src/Core/IPicker.cs +++ b/src/Core/src/Core/IPicker.cs @@ -6,7 +6,7 @@ namespace Microsoft.Maui /// /// Represents a View for selecting a text item from a list of data. /// - public interface IPicker : IView + public interface IPicker : IView, ITextStyle { /// /// Gets the title for the Picker. @@ -32,10 +32,5 @@ public interface IPicker : IView /// Gets the selected item. /// object? SelectedItem { get; set; } - - /// - /// Gets the character spacing. - /// - double CharacterSpacing { get; set; } } } \ No newline at end of file diff --git a/src/Core/src/Core/ISearchBar.cs b/src/Core/src/Core/ISearchBar.cs index 30e76d3b568b..b963442a1f4c 100644 --- a/src/Core/src/Core/ISearchBar.cs +++ b/src/Core/src/Core/ISearchBar.cs @@ -3,7 +3,7 @@ /// /// Represents a View used to initiating a search. /// - public interface ISearchBar : IView, IText, IPlaceholder, ITextAlignment + public interface ISearchBar : IView, ITextInput, ITextAlignment { } diff --git a/src/Core/src/Core/IText.cs b/src/Core/src/Core/IText.cs index 6b390f3800ff..194fe7003354 100644 --- a/src/Core/src/Core/IText.cs +++ b/src/Core/src/Core/IText.cs @@ -3,26 +3,11 @@ namespace Microsoft.Maui /// /// Provides functionality to be able to customize Text. /// - public interface IText + public interface IText : ITextStyle { /// /// Gets the text. /// string Text { get; } - - /// - /// Gets the text color. - /// - Color TextColor { get; } - - /// - /// Gets the font family, style and size of the font. - /// - Font Font { get; } - - /// - /// Gets the spacing between characters of the text. - /// - double CharacterSpacing { get; } } } \ No newline at end of file diff --git a/src/Core/src/Core/ITextInput.cs b/src/Core/src/Core/ITextInput.cs index 4dbe0ccf8aec..4cef3349d1e3 100644 --- a/src/Core/src/Core/ITextInput.cs +++ b/src/Core/src/Core/ITextInput.cs @@ -10,6 +10,11 @@ public interface ITextInput : IText, IPlaceholder /// new string Text { get; set; } + /// + /// Gets a value that controls whether text prediction and automatic text correction is on or off. + /// + bool IsTextPredictionEnabled { get; } + /// /// Gets a value indicating whether or not the view is read-only. /// diff --git a/src/Core/src/Core/ITextStyle.cs b/src/Core/src/Core/ITextStyle.cs new file mode 100644 index 000000000000..da5b8ff6cb45 --- /dev/null +++ b/src/Core/src/Core/ITextStyle.cs @@ -0,0 +1,23 @@ +namespace Microsoft.Maui +{ + /// + /// Provides functionality to be able to customize the appearance of text. + /// + public interface ITextStyle + { + /// + /// Gets the text color. + /// + Color TextColor { get; } + + /// + /// Gets the font family, style and size of the font. + /// + Font Font { get; } + + /// + /// Gets the spacing between characters of the text. + /// + double CharacterSpacing { get; } + } +} \ No newline at end of file diff --git a/src/Core/src/Core/ITimePicker.cs b/src/Core/src/Core/ITimePicker.cs index 94e376c78a72..7e4cdf81f4b2 100644 --- a/src/Core/src/Core/ITimePicker.cs +++ b/src/Core/src/Core/ITimePicker.cs @@ -5,7 +5,7 @@ namespace Microsoft.Maui /// /// Represents a View that allows the user to select a time. /// - public interface ITimePicker : IView + public interface ITimePicker : IView, ITextStyle { /// /// The format of the time to display to the user. @@ -16,15 +16,5 @@ public interface ITimePicker : IView /// Gets the displayed time. /// TimeSpan Time { get; set; } - - /// - /// Gets the spacing between characters of the text. - /// - double CharacterSpacing { get; } - - /// - /// Gets the font family, style and size of the font. - /// - Font Font { get; } } } \ No newline at end of file diff --git a/src/Core/src/Handlers/ActivityIndicator/ActivityIndicatorHandler.Android.cs b/src/Core/src/Handlers/ActivityIndicator/ActivityIndicatorHandler.Android.cs index c0b3847f3201..dc2d44855817 100644 --- a/src/Core/src/Handlers/ActivityIndicator/ActivityIndicatorHandler.Android.cs +++ b/src/Core/src/Handlers/ActivityIndicator/ActivityIndicatorHandler.Android.cs @@ -5,5 +5,15 @@ namespace Microsoft.Maui.Handlers public partial class ActivityIndicatorHandler : ViewHandler { protected override ProgressBar CreateNativeView() => new ProgressBar(Context) { Indeterminate = true }; + + public static void MapIsRunning(ActivityIndicatorHandler handler, IActivityIndicator activityIndicator) + { + handler.NativeView?.UpdateIsRunning(activityIndicator); + } + + public static void MapColor(ActivityIndicatorHandler handler, IActivityIndicator activityIndicator) + { + handler.NativeView?.UpdateColor(activityIndicator); + } } } \ No newline at end of file diff --git a/src/Core/src/Handlers/ActivityIndicator/ActivityIndicatorHandler.Standard.cs b/src/Core/src/Handlers/ActivityIndicator/ActivityIndicatorHandler.Standard.cs index e00e45cb89c5..1988a49b2be8 100644 --- a/src/Core/src/Handlers/ActivityIndicator/ActivityIndicatorHandler.Standard.cs +++ b/src/Core/src/Handlers/ActivityIndicator/ActivityIndicatorHandler.Standard.cs @@ -5,5 +5,8 @@ namespace Microsoft.Maui.Handlers public partial class ActivityIndicatorHandler : ViewHandler { protected override object CreateNativeView() => throw new NotImplementedException(); + + public static void MapIsRunning(ActivityIndicatorHandler handler, IActivityIndicator activityIndicator) { } + public static void MapColor(ActivityIndicatorHandler handler, IActivityIndicator activityIndicator) { } } } \ No newline at end of file diff --git a/src/Core/src/Handlers/ActivityIndicator/ActivityIndicatorHandler.Windows.cs b/src/Core/src/Handlers/ActivityIndicator/ActivityIndicatorHandler.Windows.cs index 31ab56044ced..52a60b508a22 100644 --- a/src/Core/src/Handlers/ActivityIndicator/ActivityIndicatorHandler.Windows.cs +++ b/src/Core/src/Handlers/ActivityIndicator/ActivityIndicatorHandler.Windows.cs @@ -6,5 +6,11 @@ namespace Microsoft.Maui.Handlers public partial class ActivityIndicatorHandler : ViewHandler { protected override ProgressBar CreateNativeView() => new ProgressBar(); + + [MissingMapper] + public static void MapIsRunning(ActivityIndicatorHandler handler, IActivityIndicator activityIndicator) { } + + [MissingMapper] + public static void MapColor(ActivityIndicatorHandler handler, IActivityIndicator activityIndicator) { } } } \ No newline at end of file diff --git a/src/Core/src/Handlers/ActivityIndicator/ActivityIndicatorHandler.cs b/src/Core/src/Handlers/ActivityIndicator/ActivityIndicatorHandler.cs index 5c5d93255a82..116f332ad723 100644 --- a/src/Core/src/Handlers/ActivityIndicator/ActivityIndicatorHandler.cs +++ b/src/Core/src/Handlers/ActivityIndicator/ActivityIndicatorHandler.cs @@ -4,20 +4,10 @@ public partial class ActivityIndicatorHandler { public static PropertyMapper ActivityIndicatorMapper = new PropertyMapper(ViewHandler.ViewMapper) { + [nameof(IActivityIndicator.Color)] = MapColor, [nameof(IActivityIndicator.IsRunning)] = MapIsRunning, - [nameof(IActivityIndicator.Color)] = MapColor }; - public static void MapIsRunning(ActivityIndicatorHandler handler, IActivityIndicator activityIndicator) - { - handler.NativeView?.UpdateIsRunning(activityIndicator); - } - - public static void MapColor(ActivityIndicatorHandler handler, IActivityIndicator activityIndicator) - { - handler.NativeView?.UpdateColor(activityIndicator); - } - public ActivityIndicatorHandler() : base(ActivityIndicatorMapper) { diff --git a/src/Core/src/Handlers/ActivityIndicator/ActivityIndicatorHandler.iOS.cs b/src/Core/src/Handlers/ActivityIndicator/ActivityIndicatorHandler.iOS.cs index 2f90abc60bcf..9fea110f7151 100644 --- a/src/Core/src/Handlers/ActivityIndicator/ActivityIndicatorHandler.iOS.cs +++ b/src/Core/src/Handlers/ActivityIndicator/ActivityIndicatorHandler.iOS.cs @@ -9,5 +9,15 @@ public partial class ActivityIndicatorHandler : ViewHandler { protected override object CreateNativeView() => throw new NotImplementedException(); - public static void MapBackgroundColor(ButtonHandler handler, IButton button) { } public static void MapText(ButtonHandler handler, IButton button) { } public static void MapTextColor(ButtonHandler handler, IButton button) { } public static void MapCharacterSpacing(ButtonHandler handler, IButton button) { } diff --git a/src/Core/src/Handlers/Button/ButtonHandler.Windows.cs b/src/Core/src/Handlers/Button/ButtonHandler.Windows.cs index 19663248ac4d..86c604ddf6de 100644 --- a/src/Core/src/Handlers/Button/ButtonHandler.Windows.cs +++ b/src/Core/src/Handlers/Button/ButtonHandler.Windows.cs @@ -44,6 +44,7 @@ protected override void DisconnectHandler(Button nativeView) base.DisconnectHandler(nativeView); } + // This is a Windows-specific mapping public static void MapBackgroundColor(ButtonHandler handler, IButton button) { handler.NativeView?.UpdateBackgroundColor(button, DefaultBackground); @@ -59,6 +60,7 @@ public static void MapTextColor(ButtonHandler handler, IButton button) handler.NativeView?.UpdateTextColor(button, DefaultForeground); } + [MissingMapper] public static void MapCharacterSpacing(ButtonHandler handler, IButton button) { } public static void MapFont(ButtonHandler handler, IButton button) diff --git a/src/Core/src/Handlers/Button/ButtonHandler.cs b/src/Core/src/Handlers/Button/ButtonHandler.cs index 53ed2ed61713..ceb36c7ee218 100644 --- a/src/Core/src/Handlers/Button/ButtonHandler.cs +++ b/src/Core/src/Handlers/Button/ButtonHandler.cs @@ -4,12 +4,14 @@ public partial class ButtonHandler { public static PropertyMapper ButtonMapper = new PropertyMapper(ViewHandler.ViewMapper) { +#if WINDOWS [nameof(IButton.BackgroundColor)] = MapBackgroundColor, - [nameof(IButton.Text)] = MapText, - [nameof(IButton.TextColor)] = MapTextColor, +#endif [nameof(IButton.CharacterSpacing)] = MapCharacterSpacing, [nameof(IButton.Font)] = MapFont, [nameof(IButton.Padding)] = MapPadding, + [nameof(IButton.Text)] = MapText, + [nameof(IButton.TextColor)] = MapTextColor, }; public ButtonHandler() : base(ButtonMapper) diff --git a/src/Core/src/Handlers/Button/ButtonHandler.iOS.cs b/src/Core/src/Handlers/Button/ButtonHandler.iOS.cs index e24d11182756..8f273c0f7553 100644 --- a/src/Core/src/Handlers/Button/ButtonHandler.iOS.cs +++ b/src/Core/src/Handlers/Button/ButtonHandler.iOS.cs @@ -45,11 +45,6 @@ protected override void SetupDefaults(UIButton nativeView) base.SetupDefaults(nativeView); } - public static void MapBackgroundColor(ButtonHandler handler, IButton button) - { - handler.NativeView?.UpdateBackgroundColor(button); - } - public static void MapText(ButtonHandler handler, IButton button) { handler.NativeView?.UpdateText(button); diff --git a/src/Core/src/Handlers/CheckBox/CheckBoxHandler.Android.cs b/src/Core/src/Handlers/CheckBox/CheckBoxHandler.Android.cs index 61d400f6506f..4673cb234a53 100644 --- a/src/Core/src/Handlers/CheckBox/CheckBoxHandler.Android.cs +++ b/src/Core/src/Handlers/CheckBox/CheckBoxHandler.Android.cs @@ -7,12 +7,6 @@ public partial class CheckBoxHandler : ViewHandler { CheckedChangeListener ChangeListener { get; } = new CheckedChangeListener(); - // This is an Android-specific mapping - public static void MapBackgroundColor(CheckBoxHandler handler, ICheckBox check) - { - handler.NativeView?.UpdateBackgroundColor(check); - } - protected override AppCompatCheckBox CreateNativeView() { var nativeCheckBox = new AppCompatCheckBox(Context) @@ -37,6 +31,17 @@ protected override void DisconnectHandler(AppCompatCheckBox nativeView) nativeView.SetOnCheckedChangeListener(null); } + // This is an Android-specific mapping + public static void MapBackgroundColor(CheckBoxHandler handler, ICheckBox check) + { + handler.NativeView?.UpdateBackgroundColor(check); + } + + public static void MapIsChecked(CheckBoxHandler handler, ICheckBox check) + { + handler.NativeView?.UpdateIsChecked(check); + } + void OnCheckedChanged(bool isChecked) { if (VirtualView != null) diff --git a/src/Core/src/Handlers/CheckBox/CheckBoxHandler.Standard.cs b/src/Core/src/Handlers/CheckBox/CheckBoxHandler.Standard.cs index 740f8679bb40..2daaaaa4fa4e 100644 --- a/src/Core/src/Handlers/CheckBox/CheckBoxHandler.Standard.cs +++ b/src/Core/src/Handlers/CheckBox/CheckBoxHandler.Standard.cs @@ -5,5 +5,7 @@ namespace Microsoft.Maui.Handlers public partial class CheckBoxHandler : ViewHandler { protected override object CreateNativeView() => throw new NotImplementedException(); + + public static void MapIsChecked(CheckBoxHandler handler, ICheckBox check) { } } } \ No newline at end of file diff --git a/src/Core/src/Handlers/CheckBox/CheckBoxHandler.Windows.cs b/src/Core/src/Handlers/CheckBox/CheckBoxHandler.Windows.cs index a1bd40349d9f..2b00a50035eb 100644 --- a/src/Core/src/Handlers/CheckBox/CheckBoxHandler.Windows.cs +++ b/src/Core/src/Handlers/CheckBox/CheckBoxHandler.Windows.cs @@ -6,5 +6,24 @@ namespace Microsoft.Maui.Handlers public partial class CheckBoxHandler : ViewHandler { protected override CheckBox CreateNativeView() => new CheckBox(); + + protected override void ConnectHandler(CheckBox nativeView) + { + base.ConnectHandler(nativeView); + + nativeView.CheckedChanged += OnCheckedChanged; + } + + protected override void DisconnectHandler(CheckBox nativeView) + { + base.DisconnectHandler(nativeView); + + nativeView.CheckedChanged -= OnCheckedChanged; + } + + public static void MapIsChecked(CheckBoxHandler handler, ICheckBox check) + { + handler.NativeView?.UpdateIsChecked(check); + } } } \ No newline at end of file diff --git a/src/Core/src/Handlers/CheckBox/CheckBoxHandler.cs b/src/Core/src/Handlers/CheckBox/CheckBoxHandler.cs index cf5b7ec12fa5..e4f25fd1dab7 100644 --- a/src/Core/src/Handlers/CheckBox/CheckBoxHandler.cs +++ b/src/Core/src/Handlers/CheckBox/CheckBoxHandler.cs @@ -4,10 +4,10 @@ public partial class CheckBoxHandler { public static PropertyMapper CheckBoxMapper = new PropertyMapper(ViewHandler.ViewMapper) { - [nameof(ICheckBox.IsChecked)] = MapIsChecked, #if MONOANDROID [nameof(ICheckBox.BackgroundColor)] = MapBackgroundColor, #endif + [nameof(ICheckBox.IsChecked)] = MapIsChecked, }; public CheckBoxHandler() : base(CheckBoxMapper) @@ -19,10 +19,5 @@ public CheckBoxHandler(PropertyMapper mapper) : base(mapper ?? CheckBoxMapper) { } - - public static void MapIsChecked(CheckBoxHandler handler, ICheckBox check) - { - handler.NativeView?.UpdateIsChecked(check); - } } } \ No newline at end of file diff --git a/src/Core/src/Handlers/CheckBox/CheckBoxHandler.iOS.cs b/src/Core/src/Handlers/CheckBox/CheckBoxHandler.iOS.cs index fa54e8ac39a1..3e09105c6206 100644 --- a/src/Core/src/Handlers/CheckBox/CheckBoxHandler.iOS.cs +++ b/src/Core/src/Handlers/CheckBox/CheckBoxHandler.iOS.cs @@ -28,6 +28,11 @@ protected override void DisconnectHandler(MauiCheckBox nativeView) nativeView.CheckedChanged -= OnCheckedChanged; } + public static void MapIsChecked(CheckBoxHandler handler, ICheckBox check) + { + handler.NativeView?.UpdateIsChecked(check); + } + public override Size GetDesiredSize(double widthConstraint, double heightConstraint) { var size = base.GetDesiredSize(widthConstraint, heightConstraint); diff --git a/src/Core/src/Handlers/DatePicker/DatePickerHandler.Android.cs b/src/Core/src/Handlers/DatePicker/DatePickerHandler.Android.cs index 9a3b0b28b01e..2c60d3e93bc5 100644 --- a/src/Core/src/Handlers/DatePicker/DatePickerHandler.Android.cs +++ b/src/Core/src/Handlers/DatePicker/DatePickerHandler.Android.cs @@ -83,6 +83,9 @@ public static void MapFont(DatePickerHandler handler, IDatePicker datePicker) handler.NativeView?.UpdateFont(datePicker, fontManager); } + [MissingMapper] + public static void MapTextColor(DatePickerHandler handler, IDatePicker datePicker) { } + void ShowPickerDialog() { if (VirtualView == null) diff --git a/src/Core/src/Handlers/DatePicker/DatePickerHandler.Standard.cs b/src/Core/src/Handlers/DatePicker/DatePickerHandler.Standard.cs index 7c4ecf810ce4..75335ccc621e 100644 --- a/src/Core/src/Handlers/DatePicker/DatePickerHandler.Standard.cs +++ b/src/Core/src/Handlers/DatePicker/DatePickerHandler.Standard.cs @@ -12,5 +12,6 @@ public static void MapMinimumDate(DatePickerHandler handler, IDatePicker datePic public static void MapMaximumDate(DatePickerHandler handler, IDatePicker datePicker) { } public static void MapCharacterSpacing(DatePickerHandler handler, IDatePicker datePicker) { } public static void MapFont(DatePickerHandler handler, IDatePicker datePicker) { } + public static void MapTextColor(DatePickerHandler handler, IDatePicker datePicker) { } } } \ No newline at end of file diff --git a/src/Core/src/Handlers/DatePicker/DatePickerHandler.Windows.cs b/src/Core/src/Handlers/DatePicker/DatePickerHandler.Windows.cs index 10321ae37d96..451dbe0dcbfc 100644 --- a/src/Core/src/Handlers/DatePicker/DatePickerHandler.Windows.cs +++ b/src/Core/src/Handlers/DatePicker/DatePickerHandler.Windows.cs @@ -7,11 +7,22 @@ public partial class DatePickerHandler : ViewHandler { protected override DatePicker CreateNativeView() => new DatePicker(); + [MissingMapper] public static void MapFormat(DatePickerHandler handler, IDatePicker datePicker) { } + + [MissingMapper] public static void MapDate(DatePickerHandler handler, IDatePicker datePicker) { } + + [MissingMapper] public static void MapMinimumDate(DatePickerHandler handler, IDatePicker datePicker) { } + + [MissingMapper] public static void MapMaximumDate(DatePickerHandler handler, IDatePicker datePicker) { } + + [MissingMapper] public static void MapCharacterSpacing(DatePickerHandler handler, IDatePicker datePicker) { } + + [MissingMapper] public static void MapFont(DatePickerHandler handler, IDatePicker datePicker) { } } } \ No newline at end of file diff --git a/src/Core/src/Handlers/DatePicker/DatePickerHandler.cs b/src/Core/src/Handlers/DatePicker/DatePickerHandler.cs index 38beca0c2c89..d218cdb38ef3 100644 --- a/src/Core/src/Handlers/DatePicker/DatePickerHandler.cs +++ b/src/Core/src/Handlers/DatePicker/DatePickerHandler.cs @@ -4,12 +4,13 @@ public partial class DatePickerHandler { public static PropertyMapper DatePickerMapper = new PropertyMapper(ViewHandler.ViewMapper) { - [nameof(IDatePicker.Format)] = MapFormat, + [nameof(IDatePicker.CharacterSpacing)] = MapCharacterSpacing, [nameof(IDatePicker.Date)] = MapDate, - [nameof(IDatePicker.MinimumDate)] = MapMinimumDate, + [nameof(IDatePicker.Font)] = MapFont, + [nameof(IDatePicker.Format)] = MapFormat, [nameof(IDatePicker.MaximumDate)] = MapMaximumDate, - [nameof(IDatePicker.CharacterSpacing)] = MapCharacterSpacing, - [nameof(IDatePicker.Font)] = MapFont + [nameof(IDatePicker.MinimumDate)] = MapMinimumDate, + [nameof(IDatePicker.TextColor)] = MapTextColor, }; public DatePickerHandler() : base(DatePickerMapper) diff --git a/src/Core/src/Handlers/DatePicker/DatePickerHandler.iOS.cs b/src/Core/src/Handlers/DatePicker/DatePickerHandler.iOS.cs index a0247dea77d7..b7a21765c109 100644 --- a/src/Core/src/Handlers/DatePicker/DatePickerHandler.iOS.cs +++ b/src/Core/src/Handlers/DatePicker/DatePickerHandler.iOS.cs @@ -98,6 +98,9 @@ public static void MapFont(DatePickerHandler handler, IDatePicker datePicker) handler.NativeView?.UpdateFont(datePicker, fontManager); } + [MissingMapper] + public static void MapTextColor(DatePickerHandler handler, IDatePicker datePicker) { } + void OnValueChanged(object? sender, EventArgs? e) { SetVirtualViewDate(); diff --git a/src/Core/src/Handlers/Editor/EditorHandler.Android.cs b/src/Core/src/Handlers/Editor/EditorHandler.Android.cs index 4d9e1e549de3..9d755e0097dc 100644 --- a/src/Core/src/Handlers/Editor/EditorHandler.Android.cs +++ b/src/Core/src/Handlers/Editor/EditorHandler.Android.cs @@ -75,5 +75,8 @@ public static void MapFont(EditorHandler handler, IEditor editor) handler.NativeView?.UpdateFont(editor, fontManager); } + + [MissingMapper] + public static void MapTextColor(EditorHandler handler, IEditor editor) { } } } \ No newline at end of file diff --git a/src/Core/src/Handlers/Editor/EditorHandler.Standard.cs b/src/Core/src/Handlers/Editor/EditorHandler.Standard.cs index 67a6fbce3f80..1766b7bba0af 100644 --- a/src/Core/src/Handlers/Editor/EditorHandler.Standard.cs +++ b/src/Core/src/Handlers/Editor/EditorHandler.Standard.cs @@ -14,5 +14,6 @@ public static void MapMaxLength(IViewHandler handler, IEditor editor) { } public static void MapIsTextPredictionEnabled(EditorHandler handler, IEditor editor) { } public static void MapFont(IViewHandler handler, IEditor editor) { } public static void MapIsReadOnly(IViewHandler handler, IEditor editor) { } + public static void MapTextColor(EditorHandler handler, IEditor editor) { } } } \ No newline at end of file diff --git a/src/Core/src/Handlers/Editor/EditorHandler.Windows.cs b/src/Core/src/Handlers/Editor/EditorHandler.Windows.cs index 1f64f3c294ce..60af8598643c 100644 --- a/src/Core/src/Handlers/Editor/EditorHandler.Windows.cs +++ b/src/Core/src/Handlers/Editor/EditorHandler.Windows.cs @@ -7,13 +7,31 @@ public partial class EditorHandler : ViewHandler { protected override TextBox CreateNativeView() => new TextBox(); + [MissingMapper] public static void MapText(IViewHandler handler, IEditor editor) { } + + [MissingMapper] public static void MapPlaceholder(IViewHandler handler, IEditor editor) { } + + [MissingMapper] public static void MapPlaceholderColor(IViewHandler handler, IEditor editor) { } + + [MissingMapper] public static void MapCharacterSpacing(IViewHandler handler, IEditor editor) { } + + [MissingMapper] public static void MapMaxLength(IViewHandler handler, IEditor editor) { } + + [MissingMapper] public static void MapIsTextPredictionEnabled(EditorHandler handler, IEditor editor) { } + + [MissingMapper] public static void MapFont(IViewHandler handler, IEditor editor) { } + + [MissingMapper] public static void MapIsReadOnly(IViewHandler handler, IEditor editor) { } + + [MissingMapper] + public static void MapTextColor(EditorHandler handler, IEditor editor) { } } } \ No newline at end of file diff --git a/src/Core/src/Handlers/Editor/EditorHandler.cs b/src/Core/src/Handlers/Editor/EditorHandler.cs index edb8aafc14ad..28b8a0fceacb 100644 --- a/src/Core/src/Handlers/Editor/EditorHandler.cs +++ b/src/Core/src/Handlers/Editor/EditorHandler.cs @@ -4,14 +4,15 @@ public partial class EditorHandler { public static PropertyMapper EditorMapper = new PropertyMapper(ViewHandler.ViewMapper) { - [nameof(IEditor.Text)] = MapText, - [nameof(IEditor.Placeholder)] = MapPlaceholder, - [nameof(IEditor.PlaceholderColor)] = MapPlaceholderColor, [nameof(IEditor.CharacterSpacing)] = MapCharacterSpacing, - [nameof(IEditor.MaxLength)] = MapMaxLength, - [nameof(IEditor.IsTextPredictionEnabled)] = MapIsTextPredictionEnabled, [nameof(IEditor.Font)] = MapFont, - [nameof(IEditor.IsReadOnly)] = MapIsReadOnly + [nameof(IEditor.IsReadOnly)] = MapIsReadOnly, + [nameof(IEditor.IsTextPredictionEnabled)] = MapIsTextPredictionEnabled, + [nameof(IEditor.MaxLength)] = MapMaxLength, + [nameof(IEditor.Placeholder)] = MapPlaceholder, + [nameof(IEditor.PlaceholderColor)] = MapPlaceholderColor, + [nameof(IEditor.Text)] = MapText, + [nameof(IEditor.TextColor)] = MapTextColor, }; public EditorHandler() : base(EditorMapper) diff --git a/src/Core/src/Handlers/Editor/EditorHandler.iOS.cs b/src/Core/src/Handlers/Editor/EditorHandler.iOS.cs index 901d72d7b888..0680a52c67c8 100644 --- a/src/Core/src/Handlers/Editor/EditorHandler.iOS.cs +++ b/src/Core/src/Handlers/Editor/EditorHandler.iOS.cs @@ -116,5 +116,8 @@ public static void MapFont(EditorHandler handler, IEditor editor) handler.NativeView?.UpdateFont(editor, fontManager); } + + [MissingMapper] + public static void MapTextColor(EditorHandler handler, IEditor editor) { } } } \ No newline at end of file diff --git a/src/Core/src/Handlers/Entry/EntryHandler.Windows.cs b/src/Core/src/Handlers/Entry/EntryHandler.Windows.cs index 91bc64be5412..0e27062358ed 100644 --- a/src/Core/src/Handlers/Entry/EntryHandler.Windows.cs +++ b/src/Core/src/Handlers/Entry/EntryHandler.Windows.cs @@ -7,17 +7,40 @@ public partial class EntryHandler : ViewHandler { protected override TextBox CreateNativeView() => new TextBox(); + [MissingMapper] public static void MapText(IViewHandler handler, IEntry entry) { } + + [MissingMapper] public static void MapTextColor(IViewHandler handler, IEntry entry) { } + + [MissingMapper] public static void MapIsPassword(IViewHandler handler, IEntry entry) { } + + [MissingMapper] public static void MapHorizontalTextAlignment(IViewHandler handler, IEntry entry) { } + + [MissingMapper] public static void MapIsTextPredictionEnabled(IViewHandler handler, IEntry entry) { } + + [MissingMapper] public static void MapMaxLength(IViewHandler handler, IEntry entry) { } + + [MissingMapper] public static void MapPlaceholder(IViewHandler handler, IEntry entry) { } + + [MissingMapper] public static void MapIsReadOnly(IViewHandler handler, IEntry entry) { } + + [MissingMapper] public static void MapFont(IViewHandler handler, IEntry entry) { } + + [MissingMapper] public static void MapReturnType(IViewHandler handler, IEntry entry) { } + + [MissingMapper] public static void MapClearButtonVisibility(IViewHandler handler, IEntry entry) { } + + [MissingMapper] public static void MapCharacterSpacing(IViewHandler handler, IEntry entry) { } } } \ No newline at end of file diff --git a/src/Core/src/Handlers/Entry/EntryHandler.cs b/src/Core/src/Handlers/Entry/EntryHandler.cs index 9337ac3c3895..c26c3b2afe81 100644 --- a/src/Core/src/Handlers/Entry/EntryHandler.cs +++ b/src/Core/src/Handlers/Entry/EntryHandler.cs @@ -4,18 +4,18 @@ public partial class EntryHandler { public static PropertyMapper EntryMapper = new PropertyMapper(ViewHandler.ViewMapper) { - [nameof(IEntry.Text)] = MapText, - [nameof(IEntry.TextColor)] = MapTextColor, - [nameof(IEntry.IsPassword)] = MapIsPassword, + [nameof(IEntry.CharacterSpacing)] = MapCharacterSpacing, + [nameof(IEntry.ClearButtonVisibility)] = MapClearButtonVisibility, + [nameof(IEntry.Font)] = MapFont, [nameof(IEntry.HorizontalTextAlignment)] = MapHorizontalTextAlignment, + [nameof(IEntry.IsPassword)] = MapIsPassword, + [nameof(IEntry.IsReadOnly)] = MapIsReadOnly, [nameof(IEntry.IsTextPredictionEnabled)] = MapIsTextPredictionEnabled, [nameof(IEntry.MaxLength)] = MapMaxLength, [nameof(IEntry.Placeholder)] = MapPlaceholder, - [nameof(IEntry.IsReadOnly)] = MapIsReadOnly, - [nameof(IEntry.Font)] = MapFont, [nameof(IEntry.ReturnType)] = MapReturnType, - [nameof(IEntry.ClearButtonVisibility)] = MapClearButtonVisibility, - [nameof(IEntry.CharacterSpacing)] = MapCharacterSpacing + [nameof(IEntry.Text)] = MapText, + [nameof(IEntry.TextColor)] = MapTextColor, }; public EntryHandler() : base(EntryMapper) diff --git a/src/Core/src/Handlers/Label/LabelHandler.Windows.cs b/src/Core/src/Handlers/Label/LabelHandler.Windows.cs index 39c870713df4..2d89d9b00c3b 100644 --- a/src/Core/src/Handlers/Label/LabelHandler.Windows.cs +++ b/src/Core/src/Handlers/Label/LabelHandler.Windows.cs @@ -21,6 +21,7 @@ public static void MapText(LabelHandler handler, ILabel label) => public static void MapTextColor(LabelHandler handler, ILabel label) => handler.TextBlock?.UpdateTextColor(label); + [MissingMapper] public static void MapCharacterSpacing(LabelHandler handler, ILabel label) { } public static void MapFont(LabelHandler handler, ILabel label) @@ -31,18 +32,23 @@ public static void MapFont(LabelHandler handler, ILabel label) handler.TextBlock?.UpdateFont(label, fontManager); } - + + [MissingMapper] public static void MapHorizontalTextAlignment(LabelHandler handler, ILabel label) { } + [MissingMapper] public static void MapLineBreakMode(LabelHandler handler, ILabel label) { } + [MissingMapper] public static void MapTextDecorations(LabelHandler handler, ILabel label) { } + [MissingMapper] public static void MapMaxLines(LabelHandler handler, ILabel label) { } public static void MapPadding(LabelHandler handler, ILabel label) => handler.TextBlock?.UpdatePadding(label); + [MissingMapper] public static void MapLineHeight(LabelHandler handler, ILabel label) { } } } \ No newline at end of file diff --git a/src/Core/src/Handlers/Label/LabelHandler.cs b/src/Core/src/Handlers/Label/LabelHandler.cs index 820346779a2a..4915ed20de60 100644 --- a/src/Core/src/Handlers/Label/LabelHandler.cs +++ b/src/Core/src/Handlers/Label/LabelHandler.cs @@ -4,16 +4,16 @@ public partial class LabelHandler { public static PropertyMapper LabelMapper = new PropertyMapper(ViewHandler.ViewMapper) { - [nameof(ILabel.TextColor)] = MapTextColor, - [nameof(ILabel.Text)] = MapText, [nameof(ILabel.CharacterSpacing)] = MapCharacterSpacing, - [nameof(ILabel.MaxLines)] = MapMaxLines, [nameof(ILabel.Font)] = MapFont, [nameof(ILabel.HorizontalTextAlignment)] = MapHorizontalTextAlignment, [nameof(ILabel.LineBreakMode)] = MapLineBreakMode, + [nameof(ILabel.LineHeight)] = MapLineHeight, + [nameof(ILabel.MaxLines)] = MapMaxLines, [nameof(ILabel.Padding)] = MapPadding, + [nameof(ILabel.Text)] = MapText, + [nameof(ILabel.TextColor)] = MapTextColor, [nameof(ILabel.TextDecorations)] = MapTextDecorations, - [nameof(ILabel.LineHeight)] = MapLineHeight }; public LabelHandler() : base(LabelMapper) diff --git a/src/Core/src/Handlers/Picker/PickerHandler.Android.cs b/src/Core/src/Handlers/Picker/PickerHandler.Android.cs index 84dd09449336..6414ead522f3 100644 --- a/src/Core/src/Handlers/Picker/PickerHandler.Android.cs +++ b/src/Core/src/Handlers/Picker/PickerHandler.Android.cs @@ -49,6 +49,12 @@ public static void MapCharacterSpacing(PickerHandler handler, IPicker picker) handler.NativeView?.UpdateCharacterSpacing(picker); } + [MissingMapper] + public static void MapFont(PickerHandler handler, IPicker view) { } + + [MissingMapper] + public static void MapTextColor(PickerHandler handler, IPicker view) { } + void OnFocusChange(object? sender, global::Android.Views.View.FocusChangeEventArgs e) { if (NativeView == null) diff --git a/src/Core/src/Handlers/Picker/PickerHandler.Standard.cs b/src/Core/src/Handlers/Picker/PickerHandler.Standard.cs index b8d3cc2f4e51..a6437e0e4ae0 100644 --- a/src/Core/src/Handlers/Picker/PickerHandler.Standard.cs +++ b/src/Core/src/Handlers/Picker/PickerHandler.Standard.cs @@ -9,5 +9,7 @@ public partial class PickerHandler : ViewHandler public static void MapTitle(PickerHandler handler, IPicker view) { } public static void MapSelectedIndex(PickerHandler handler, IPicker view) { } public static void MapCharacterSpacing(PickerHandler handler, IPicker view) { } + public static void MapFont(PickerHandler handler, IPicker view) { } + public static void MapTextColor(PickerHandler handler, IPicker view) { } } } \ No newline at end of file diff --git a/src/Core/src/Handlers/Picker/PickerHandler.Windows.cs b/src/Core/src/Handlers/Picker/PickerHandler.Windows.cs index f33388bf7e61..53b43f8dd590 100644 --- a/src/Core/src/Handlers/Picker/PickerHandler.Windows.cs +++ b/src/Core/src/Handlers/Picker/PickerHandler.Windows.cs @@ -7,8 +7,19 @@ public partial class PickerHandler : ViewHandler { protected override ComboBox CreateNativeView() => new ComboBox(); + [MissingMapper] public static void MapTitle(PickerHandler handler, IPicker view) { } + + [MissingMapper] public static void MapSelectedIndex(PickerHandler handler, IPicker view) { } + + [MissingMapper] public static void MapCharacterSpacing(PickerHandler handler, IPicker view) { } + + [MissingMapper] + public static void MapFont(PickerHandler handler, IPicker view) { } + + [MissingMapper] + public static void MapTextColor(PickerHandler handler, IPicker view) { } } } \ No newline at end of file diff --git a/src/Core/src/Handlers/Picker/PickerHandler.cs b/src/Core/src/Handlers/Picker/PickerHandler.cs index 48a271b81d5d..9a940a0664dd 100644 --- a/src/Core/src/Handlers/Picker/PickerHandler.cs +++ b/src/Core/src/Handlers/Picker/PickerHandler.cs @@ -4,9 +4,11 @@ public partial class PickerHandler { public static PropertyMapper PickerMapper = new PropertyMapper(ViewHandler.ViewMapper) { - [nameof(IPicker.Title)] = MapTitle, + [nameof(IPicker.CharacterSpacing)] = MapCharacterSpacing, + [nameof(IPicker.Font)] = MapFont, [nameof(IPicker.SelectedIndex)] = MapSelectedIndex, - [nameof(IPicker.CharacterSpacing)] = MapCharacterSpacing + [nameof(IPicker.TextColor)] = MapTextColor, + [nameof(IPicker.Title)] = MapTitle, }; public PickerHandler() : base(PickerMapper) diff --git a/src/Core/src/Handlers/Picker/PickerHandler.iOS.cs b/src/Core/src/Handlers/Picker/PickerHandler.iOS.cs index 38a52ac6048b..a7914b9e8099 100644 --- a/src/Core/src/Handlers/Picker/PickerHandler.iOS.cs +++ b/src/Core/src/Handlers/Picker/PickerHandler.iOS.cs @@ -106,6 +106,12 @@ public static void MapCharacterSpacing(PickerHandler handler, IPicker picker) handler.NativeView?.UpdateCharacterSpacing(picker); } + [MissingMapper] + public static void MapFont(PickerHandler handler, IPicker view) { } + + [MissingMapper] + public static void MapTextColor(PickerHandler handler, IPicker view) { } + void OnCollectionChanged(object? sender, EventArgs e) { if (VirtualView == null || NativeView == null) diff --git a/src/Core/src/Handlers/ProgressBar/ProgressBarHandler.Android.cs b/src/Core/src/Handlers/ProgressBar/ProgressBarHandler.Android.cs index 9fe82180a5d6..370c5bdc4fa8 100644 --- a/src/Core/src/Handlers/ProgressBar/ProgressBarHandler.Android.cs +++ b/src/Core/src/Handlers/ProgressBar/ProgressBarHandler.Android.cs @@ -13,5 +13,10 @@ protected override AndroidProgressBar CreateNativeView() Max = ProgressBarExtensions.Maximum }; } + + public static void MapProgress(ProgressBarHandler handler, IProgress progress) + { + handler.NativeView?.UpdateProgress(progress); + } } } \ No newline at end of file diff --git a/src/Core/src/Handlers/ProgressBar/ProgressBarHandler.Standard.cs b/src/Core/src/Handlers/ProgressBar/ProgressBarHandler.Standard.cs index 559e797ff167..28659787d4bd 100644 --- a/src/Core/src/Handlers/ProgressBar/ProgressBarHandler.Standard.cs +++ b/src/Core/src/Handlers/ProgressBar/ProgressBarHandler.Standard.cs @@ -5,5 +5,7 @@ namespace Microsoft.Maui.Handlers public partial class ProgressBarHandler : ViewHandler { protected override object CreateNativeView() => throw new NotImplementedException(); + + public static void MapProgress(ProgressBarHandler handler, IProgress progress) { } } } \ No newline at end of file diff --git a/src/Core/src/Handlers/ProgressBar/ProgressBarHandler.Windows.cs b/src/Core/src/Handlers/ProgressBar/ProgressBarHandler.Windows.cs index 9906d4603065..9fed669b54f9 100644 --- a/src/Core/src/Handlers/ProgressBar/ProgressBarHandler.Windows.cs +++ b/src/Core/src/Handlers/ProgressBar/ProgressBarHandler.Windows.cs @@ -6,5 +6,8 @@ namespace Microsoft.Maui.Handlers public partial class ProgressBarHandler : ViewHandler { protected override ProgressBar CreateNativeView() => new ProgressBar(); + + [MissingMapper] + public static void MapProgress(ProgressBarHandler handler, IProgress progress) { } } } \ No newline at end of file diff --git a/src/Core/src/Handlers/ProgressBar/ProgressBarHandler.cs b/src/Core/src/Handlers/ProgressBar/ProgressBarHandler.cs index 6aed448c4eb4..1760062666b5 100644 --- a/src/Core/src/Handlers/ProgressBar/ProgressBarHandler.cs +++ b/src/Core/src/Handlers/ProgressBar/ProgressBarHandler.cs @@ -7,11 +7,6 @@ public partial class ProgressBarHandler [nameof(IProgress.Progress)] = MapProgress, }; - public static void MapProgress(ProgressBarHandler handler, IProgress progress) - { - handler.NativeView?.UpdateProgress(progress); - } - public ProgressBarHandler() : base(ProgressMapper) { diff --git a/src/Core/src/Handlers/ProgressBar/ProgressBarHandler.iOS.cs b/src/Core/src/Handlers/ProgressBar/ProgressBarHandler.iOS.cs index 29a7bb48c26c..fd78a75e92ad 100644 --- a/src/Core/src/Handlers/ProgressBar/ProgressBarHandler.iOS.cs +++ b/src/Core/src/Handlers/ProgressBar/ProgressBarHandler.iOS.cs @@ -8,5 +8,10 @@ protected override UIProgressView CreateNativeView() { return new UIProgressView(UIProgressViewStyle.Default); } + + public static void MapProgress(ProgressBarHandler handler, IProgress progress) + { + handler.NativeView?.UpdateProgress(progress); + } } } \ No newline at end of file diff --git a/src/Core/src/Handlers/SearchBar/SearchBarHandler.Android.cs b/src/Core/src/Handlers/SearchBar/SearchBarHandler.Android.cs index 593e52211c52..21d58891c9f6 100644 --- a/src/Core/src/Handlers/SearchBar/SearchBarHandler.Android.cs +++ b/src/Core/src/Handlers/SearchBar/SearchBarHandler.Android.cs @@ -48,5 +48,17 @@ public static void MapCharacterSpacing(SearchBarHandler handler, ISearchBar sear { handler.QueryEditor?.UpdateCharacterSpacing(searchBar); } + + [MissingMapper] + public static void MapTextColor(IViewHandler handler, ISearchBar searchBar) { } + + [MissingMapper] + public static void MapIsTextPredictionEnabled(IViewHandler handler, ISearchBar searchBar) { } + + [MissingMapper] + public static void MapMaxLength(IViewHandler handler, ISearchBar searchBar) { } + + [MissingMapper] + public static void MapIsReadOnly(IViewHandler handler, ISearchBar searchBar) { } } } \ No newline at end of file diff --git a/src/Core/src/Handlers/SearchBar/SearchBarHandler.Standard.cs b/src/Core/src/Handlers/SearchBar/SearchBarHandler.Standard.cs index 3dc72af6b520..7f705d63f27a 100644 --- a/src/Core/src/Handlers/SearchBar/SearchBarHandler.Standard.cs +++ b/src/Core/src/Handlers/SearchBar/SearchBarHandler.Standard.cs @@ -11,5 +11,9 @@ public static void MapPlaceholder(IViewHandler handler, ISearchBar searchBar) { public static void MapFont(IViewHandler handler, ISearchBar searchBar) { } public static void MapHorizontalTextAlignment(IViewHandler handler, ISearchBar searchBar) { } public static void MapCharacterSpacing(IViewHandler handler, ISearchBar searchBar) { } + public static void MapTextColor(IViewHandler handler, ISearchBar searchBar) { } + public static void MapIsTextPredictionEnabled(IViewHandler handler, ISearchBar searchBar) { } + public static void MapMaxLength(IViewHandler handler, ISearchBar searchBar) { } + public static void MapIsReadOnly(IViewHandler handler, ISearchBar searchBar) { } } } \ No newline at end of file diff --git a/src/Core/src/Handlers/SearchBar/SearchBarHandler.Windows.cs b/src/Core/src/Handlers/SearchBar/SearchBarHandler.Windows.cs index 0ec00c092618..7222e3c27f81 100644 --- a/src/Core/src/Handlers/SearchBar/SearchBarHandler.Windows.cs +++ b/src/Core/src/Handlers/SearchBar/SearchBarHandler.Windows.cs @@ -7,12 +7,31 @@ public partial class SearchBarHandler : ViewHandler { protected override AutoSuggestBox CreateNativeView() => new AutoSuggestBox(); + [MissingMapper] public static void MapText(IViewHandler handler, ISearchBar searchBar) { } + + [MissingMapper] public static void MapPlaceholder(IViewHandler handler, ISearchBar searchBar) { } + + [MissingMapper] public static void MapHorizontalTextAlignment(IViewHandler handler, ISearchBar searchBar) { } + [MissingMapper] public static void MapFont(IViewHandler handler, ISearchBar searchBar) { } + + [MissingMapper] public static void MapCharacterSpacing(IViewHandler handler, ISearchBar searchBar) { } + [MissingMapper] + public static void MapTextColor(IViewHandler handler, ISearchBar searchBar) { } + + [MissingMapper] + public static void MapIsTextPredictionEnabled(IViewHandler handler, ISearchBar searchBar) { } + + [MissingMapper] + public static void MapMaxLength(IViewHandler handler, ISearchBar searchBar) { } + + [MissingMapper] + public static void MapIsReadOnly(IViewHandler handler, ISearchBar searchBar) { } } } \ No newline at end of file diff --git a/src/Core/src/Handlers/SearchBar/SearchBarHandler.cs b/src/Core/src/Handlers/SearchBar/SearchBarHandler.cs index d56db9e51087..13d172a3a4b8 100644 --- a/src/Core/src/Handlers/SearchBar/SearchBarHandler.cs +++ b/src/Core/src/Handlers/SearchBar/SearchBarHandler.cs @@ -4,11 +4,15 @@ public partial class SearchBarHandler { public static PropertyMapper SearchBarMapper = new PropertyMapper(ViewHandler.ViewMapper) { - [nameof(ISearchBar.Text)] = MapText, - [nameof(ISearchBar.Placeholder)] = MapPlaceholder, + [nameof(ISearchBar.CharacterSpacing)] = MapCharacterSpacing, [nameof(ISearchBar.Font)] = MapFont, [nameof(ISearchBar.HorizontalTextAlignment)] = MapHorizontalTextAlignment, - [nameof(ISearchBar.CharacterSpacing)] = MapCharacterSpacing + [nameof(ISearchBar.IsReadOnly)] = MapIsReadOnly, + [nameof(ISearchBar.IsTextPredictionEnabled)] = MapIsTextPredictionEnabled, + [nameof(ISearchBar.MaxLength)] = MapMaxLength, + [nameof(ISearchBar.Placeholder)] = MapPlaceholder, + [nameof(ISearchBar.Text)] = MapText, + [nameof(ISearchBar.TextColor)] = MapTextColor, }; public SearchBarHandler() : base(SearchBarMapper) diff --git a/src/Core/src/Handlers/SearchBar/SearchBarHandler.iOS.cs b/src/Core/src/Handlers/SearchBar/SearchBarHandler.iOS.cs index 92a6c4081eec..d25359c225bb 100644 --- a/src/Core/src/Handlers/SearchBar/SearchBarHandler.iOS.cs +++ b/src/Core/src/Handlers/SearchBar/SearchBarHandler.iOS.cs @@ -47,5 +47,17 @@ public static void MapCharacterSpacing(SearchBarHandler handler, ISearchBar sear { handler.QueryEditor?.UpdateCharacterSpacing(searchBar); } + + [MissingMapper] + public static void MapTextColor(IViewHandler handler, ISearchBar searchBar) { } + + [MissingMapper] + public static void MapIsTextPredictionEnabled(IViewHandler handler, ISearchBar searchBar) { } + + [MissingMapper] + public static void MapMaxLength(IViewHandler handler, ISearchBar searchBar) { } + + [MissingMapper] + public static void MapIsReadOnly(IViewHandler handler, ISearchBar searchBar) { } } } \ No newline at end of file diff --git a/src/Core/src/Handlers/Slider/SliderHandler.Windows.cs b/src/Core/src/Handlers/Slider/SliderHandler.Windows.cs index e86f6f4c7226..d019fe8606c3 100644 --- a/src/Core/src/Handlers/Slider/SliderHandler.Windows.cs +++ b/src/Core/src/Handlers/Slider/SliderHandler.Windows.cs @@ -7,11 +7,22 @@ public partial class SliderHandler : ViewHandler { protected override Slider CreateNativeView() => new Slider(); + [MissingMapper] public static void MapMinimum(IViewHandler handler, ISlider slider) { } + + [MissingMapper] public static void MapMaximum(IViewHandler handler, ISlider slider) { } + + [MissingMapper] public static void MapValue(IViewHandler handler, ISlider slider) { } + + [MissingMapper] public static void MapMinimumTrackColor(IViewHandler handler, ISlider slider) { } + + [MissingMapper] public static void MapMaximumTrackColor(IViewHandler handler, ISlider slider) { } + + [MissingMapper] public static void MapThumbColor(IViewHandler handler, ISlider slider) { } } } \ No newline at end of file diff --git a/src/Core/src/Handlers/Slider/SliderHandler.cs b/src/Core/src/Handlers/Slider/SliderHandler.cs index b535a9e2699f..9d9fd6ae3788 100644 --- a/src/Core/src/Handlers/Slider/SliderHandler.cs +++ b/src/Core/src/Handlers/Slider/SliderHandler.cs @@ -4,12 +4,12 @@ public partial class SliderHandler { public static PropertyMapper SliderMapper = new PropertyMapper(ViewHandler.ViewMapper) { - [nameof(ISlider.Minimum)] = MapMinimum, [nameof(ISlider.Maximum)] = MapMaximum, - [nameof(ISlider.Value)] = MapValue, - [nameof(ISlider.MinimumTrackColor)] = MapMinimumTrackColor, [nameof(ISlider.MaximumTrackColor)] = MapMaximumTrackColor, - [nameof(ISlider.ThumbColor)] = MapThumbColor + [nameof(ISlider.Minimum)] = MapMinimum, + [nameof(ISlider.MinimumTrackColor)] = MapMinimumTrackColor, + [nameof(ISlider.ThumbColor)] = MapThumbColor, + [nameof(ISlider.Value)] = MapValue, }; public SliderHandler() : base(SliderMapper) diff --git a/src/Core/src/Handlers/Stepper/StepperHandler.Windows.cs b/src/Core/src/Handlers/Stepper/StepperHandler.Windows.cs index 0e168fb96115..607c50635eae 100644 --- a/src/Core/src/Handlers/Stepper/StepperHandler.Windows.cs +++ b/src/Core/src/Handlers/Stepper/StepperHandler.Windows.cs @@ -7,9 +7,16 @@ public partial class StepperHandler : ViewHandler { protected override Button CreateNativeView() => new Button(); + [MissingMapper] public static void MapMinimum(IViewHandler handler, IStepper stepper) { } + + [MissingMapper] public static void MapMaximum(IViewHandler handler, IStepper stepper) { } + + [MissingMapper] public static void MapIncrement(IViewHandler handler, IStepper stepper) { } + + [MissingMapper] public static void MapValue(IViewHandler handler, IStepper stepper) { } } } \ No newline at end of file diff --git a/src/Core/src/Handlers/Stepper/StepperHandler.cs b/src/Core/src/Handlers/Stepper/StepperHandler.cs index 40f05225bd3a..71ff22533d1e 100644 --- a/src/Core/src/Handlers/Stepper/StepperHandler.cs +++ b/src/Core/src/Handlers/Stepper/StepperHandler.cs @@ -4,10 +4,10 @@ public partial class StepperHandler { public static PropertyMapper StepperMapper = new PropertyMapper(ViewHandler.ViewMapper) { - [nameof(IStepper.Minimum)] = MapMinimum, - [nameof(IStepper.Maximum)] = MapMaximum, [nameof(IStepper.Interval)] = MapIncrement, - [nameof(IStepper.Value)] = MapValue + [nameof(IStepper.Maximum)] = MapMaximum, + [nameof(IStepper.Minimum)] = MapMinimum, + [nameof(IStepper.Value)] = MapValue, }; public StepperHandler() : base(StepperMapper) diff --git a/src/Core/src/Handlers/Switch/SwitchHandler.Windows.cs b/src/Core/src/Handlers/Switch/SwitchHandler.Windows.cs index 1ce64ccb57c5..fb64eca34f6c 100644 --- a/src/Core/src/Handlers/Switch/SwitchHandler.Windows.cs +++ b/src/Core/src/Handlers/Switch/SwitchHandler.Windows.cs @@ -7,8 +7,13 @@ public partial class SwitchHandler : ViewHandler { protected override ToggleSwitch CreateNativeView() => new ToggleSwitch(); + [MissingMapper] public static void MapIsToggled(SwitchHandler handler, ISwitch view) { } + + [MissingMapper] public static void MapTrackColor(SwitchHandler handler, ISwitch view) { } + + [MissingMapper] public static void MapThumbColor(SwitchHandler handler, ISwitch view) { } } } \ No newline at end of file diff --git a/src/Core/src/Handlers/Switch/SwitchHandler.cs b/src/Core/src/Handlers/Switch/SwitchHandler.cs index 3c4947b6c30a..b404c8b0642b 100644 --- a/src/Core/src/Handlers/Switch/SwitchHandler.cs +++ b/src/Core/src/Handlers/Switch/SwitchHandler.cs @@ -5,8 +5,8 @@ public partial class SwitchHandler public static PropertyMapper SwitchMapper = new PropertyMapper(ViewHandler.ViewMapper) { [nameof(ISwitch.IsToggled)] = MapIsToggled, + [nameof(ISwitch.ThumbColor)] = MapThumbColor, [nameof(ISwitch.TrackColor)] = MapTrackColor, - [nameof(ISwitch.ThumbColor)] = MapThumbColor }; public SwitchHandler() : base(SwitchMapper) diff --git a/src/Core/src/Handlers/TimePicker/TimePickerHandler.Android.cs b/src/Core/src/Handlers/TimePicker/TimePickerHandler.Android.cs index b873c5d67120..3eb69a7a3cc1 100644 --- a/src/Core/src/Handlers/TimePicker/TimePickerHandler.Android.cs +++ b/src/Core/src/Handlers/TimePicker/TimePickerHandler.Android.cs @@ -69,6 +69,9 @@ public static void MapFont(TimePickerHandler handler, ITimePicker timePicker) handler.NativeView?.UpdateFont(timePicker, fontManager); } + [MissingMapper] + public static void MapTextColor(TimePickerHandler handler, ITimePicker timePicker) { } + void ShowPickerDialog() { if (VirtualView == null) diff --git a/src/Core/src/Handlers/TimePicker/TimePickerHandler.Standard.cs b/src/Core/src/Handlers/TimePicker/TimePickerHandler.Standard.cs index 5a825d08527b..eed60e1a8101 100644 --- a/src/Core/src/Handlers/TimePicker/TimePickerHandler.Standard.cs +++ b/src/Core/src/Handlers/TimePicker/TimePickerHandler.Standard.cs @@ -10,5 +10,6 @@ public static void MapFormat(TimePickerHandler handler, ITimePicker view) { } public static void MapTime(TimePickerHandler handler, ITimePicker view) { } public static void MapCharacterSpacing(TimePickerHandler handler, ITimePicker view) { } public static void MapFont(TimePickerHandler handler, ITimePicker view) { } + public static void MapTextColor(TimePickerHandler handler, ITimePicker timePicker) { } } } \ No newline at end of file diff --git a/src/Core/src/Handlers/TimePicker/TimePickerHandler.Windows.cs b/src/Core/src/Handlers/TimePicker/TimePickerHandler.Windows.cs index 4dad5c2dff1a..d735209657d8 100644 --- a/src/Core/src/Handlers/TimePicker/TimePickerHandler.Windows.cs +++ b/src/Core/src/Handlers/TimePicker/TimePickerHandler.Windows.cs @@ -6,9 +6,19 @@ public partial class TimePickerHandler : ViewHandler new Microsoft.UI.Xaml.Controls.TimePicker(); + [MissingMapper] public static void MapFormat(TimePickerHandler handler, ITimePicker view) { } + + [MissingMapper] public static void MapTime(TimePickerHandler handler, ITimePicker view) { } + + [MissingMapper] public static void MapCharacterSpacing(TimePickerHandler handler, ITimePicker view) { } + + [MissingMapper] public static void MapFont(TimePickerHandler handler, ITimePicker view) { } + + [MissingMapper] + public static void MapTextColor(TimePickerHandler handler, ITimePicker timePicker) { } } } \ No newline at end of file diff --git a/src/Core/src/Handlers/TimePicker/TimePickerHandler.cs b/src/Core/src/Handlers/TimePicker/TimePickerHandler.cs index ad30b9887cc7..9e2ac6dd6ae3 100644 --- a/src/Core/src/Handlers/TimePicker/TimePickerHandler.cs +++ b/src/Core/src/Handlers/TimePicker/TimePickerHandler.cs @@ -4,10 +4,11 @@ public partial class TimePickerHandler { public static PropertyMapper TimePickerMapper = new PropertyMapper(ViewHandler.ViewMapper) { + [nameof(ITimePicker.CharacterSpacing)] = MapCharacterSpacing, + [nameof(ITimePicker.Font)] = MapFont, [nameof(ITimePicker.Format)] = MapFormat, + [nameof(ITimePicker.TextColor)] = MapTextColor, [nameof(ITimePicker.Time)] = MapTime, - [nameof(ITimePicker.CharacterSpacing)] = MapCharacterSpacing, - [nameof(ITimePicker.Font)] = MapFont }; public TimePickerHandler() : base(TimePickerMapper) diff --git a/src/Core/src/Handlers/TimePicker/TimePickerHandler.iOS.cs b/src/Core/src/Handlers/TimePicker/TimePickerHandler.iOS.cs index f7f342638aa4..256ba28695a0 100644 --- a/src/Core/src/Handlers/TimePicker/TimePickerHandler.iOS.cs +++ b/src/Core/src/Handlers/TimePicker/TimePickerHandler.iOS.cs @@ -54,6 +54,9 @@ public static void MapFont(TimePickerHandler handler, ITimePicker timePicker) handler.NativeView?.UpdateFont(timePicker, fontManager); } + [MissingMapper] + public static void MapTextColor(TimePickerHandler handler, ITimePicker timePicker) { } + void OnValueChanged(object? sender, EventArgs e) { SetVirtualViewTime(); diff --git a/src/Core/src/Handlers/View/ViewHandler.Android.cs b/src/Core/src/Handlers/View/ViewHandler.Android.cs index f8e3df85864c..ce817d98485b 100644 --- a/src/Core/src/Handlers/View/ViewHandler.Android.cs +++ b/src/Core/src/Handlers/View/ViewHandler.Android.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Text; -using Android.Widget; +using Android.Widget; using AndroidX.Core.View; using AndroidX.Core.View.Accessibility; using NativeView = Android.Views.View; @@ -35,7 +32,6 @@ handler is ViewHandler viewHandler && ViewCompat.SetAccessibilityDelegate(handler.NativeView as NativeView, viewHandler.AccessibilityDelegate); } } - } public void OnInitializeAccessibilityNodeInfo(NativeView? host, AccessibilityNodeInfoCompat? info) @@ -71,4 +67,4 @@ public override void OnInitializeAccessibilityNodeInfo(NativeView? host, Accessi } } } -} +} \ No newline at end of file diff --git a/src/Core/src/Handlers/View/ViewHandler.cs b/src/Core/src/Handlers/View/ViewHandler.cs index 1bd7d7500ba0..98c279043993 100644 --- a/src/Core/src/Handlers/View/ViewHandler.cs +++ b/src/Core/src/Handlers/View/ViewHandler.cs @@ -1,6 +1,3 @@ -using System; -using System.Drawing; -using System.Runtime.CompilerServices; #if __IOS__ using NativeView = UIKit.UIView; #elif __MACOS__ @@ -19,14 +16,16 @@ public abstract partial class ViewHandler : IViewHandler { public static PropertyMapper ViewMapper = new PropertyMapper { + [nameof(IView.AutomationId)] = MapAutomationId, [nameof(IView.BackgroundColor)] = MapBackgroundColor, [nameof(IView.Frame)] = MapFrame, [nameof(IView.IsEnabled)] = MapIsEnabled, - [nameof(IView.AutomationId)] = MapAutomationId, - [nameof(IView.Semantics)] = MapSemantics + [nameof(IView.Semantics)] = MapSemantics, }; - internal ViewHandler() {} + internal ViewHandler() + { + } bool _hasContainer; @@ -53,17 +52,9 @@ public bool HasContainer public IMauiContext? MauiContext { get; private set; } - public object? NativeView - { - get; - private protected set; - } + public object? NativeView { get; private protected set; } - public IView? VirtualView - { - get; - private protected set; - } + public IView? VirtualView { get; private protected set; } public void SetMauiContext(IMauiContext mauiContext) => MauiContext = mauiContext; @@ -82,6 +73,7 @@ private protected void ConnectHandler(NativeView? nativeView) } partial void DisconnectingHandler(NativeView? nativeView); + private protected void DisconnectHandler(NativeView? nativeView) { DisconnectingHandler(nativeView); @@ -112,7 +104,6 @@ public static void MapAutomationId(IViewHandler handler, IView view) ((NativeView?)handler.NativeView)?.UpdateAutomationId(view); } - static partial void MappingSemantics(IViewHandler handler, IView view); public static void MapSemantics(IViewHandler handler, IView view) diff --git a/src/Core/src/Platform/Standard/ActivityIndicatorExtensions.cs b/src/Core/src/Platform/Standard/ActivityIndicatorExtensions.cs deleted file mode 100644 index 89c86ca030b2..000000000000 --- a/src/Core/src/Platform/Standard/ActivityIndicatorExtensions.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace Microsoft.Maui -{ - public static class ActivityIndicatorExtensions - { - public static void UpdateIsRunning(this object nothing, IActivityIndicator activityIndicator) - { - - } - - public static void UpdateColor(this object nothing, IActivityIndicator activityIndicator) - { - - } - } -} diff --git a/src/Core/src/Platform/Standard/CheckBoxExtensions.cs b/src/Core/src/Platform/Standard/CheckBoxExtensions.cs deleted file mode 100644 index af0aaf63ca3a..000000000000 --- a/src/Core/src/Platform/Standard/CheckBoxExtensions.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace Microsoft.Maui -{ - public static class CheckBoxExtensions - { - public static void UpdateIsChecked(this object nothing, ICheckBox check) - { - - } - - public static void UpdateColor(this object nothing, ICheckBox check) - { - - } - } -} \ No newline at end of file diff --git a/src/Core/src/Platform/Standard/PickerExtensions.cs b/src/Core/src/Platform/Standard/PickerExtensions.cs deleted file mode 100644 index 753779c1a179..000000000000 --- a/src/Core/src/Platform/Standard/PickerExtensions.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace Microsoft.Maui -{ - public static class PickerExtensions - { - public static void UpdateTitle(this object nothing, IPicker picker) - { - - } - - public static void UpdateSelectedIndex(this object nothing, IPicker picker) - { - - } - } -} \ No newline at end of file diff --git a/src/Core/src/Platform/Standard/ProgressBarExtensions.cs b/src/Core/src/Platform/Standard/ProgressBarExtensions.cs deleted file mode 100644 index 65492e719ac6..000000000000 --- a/src/Core/src/Platform/Standard/ProgressBarExtensions.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Microsoft.Maui -{ - public static class ProgressBarExtensions - { - public static void UpdateProgress(this object nothing, IProgress progress) - { - - } - } -} \ No newline at end of file diff --git a/src/Core/src/Platform/Standard/ViewExtensions.cs b/src/Core/src/Platform/Standard/ViewExtensions.cs index 0f0e87803245..1d42c3ed45bf 100644 --- a/src/Core/src/Platform/Standard/ViewExtensions.cs +++ b/src/Core/src/Platform/Standard/ViewExtensions.cs @@ -1,6 +1,6 @@ namespace Microsoft.Maui { - public static class ViewExtensions + static class ViewExtensions { public static void UpdateIsEnabled(this object nativeView, IView view) { } @@ -10,4 +10,4 @@ public static void UpdateAutomationId(this object nativeView, IView view) { } public static void UpdateSemantics(this object nativeView, IView view) { } } -} +} \ No newline at end of file diff --git a/src/Core/src/Platform/Windows/ActivityIndicatorExtensions.cs b/src/Core/src/Platform/Windows/ActivityIndicatorExtensions.cs deleted file mode 100644 index 54d96fd9f05c..000000000000 --- a/src/Core/src/Platform/Windows/ActivityIndicatorExtensions.cs +++ /dev/null @@ -1,17 +0,0 @@ -using Microsoft.UI.Xaml.Controls; - -namespace Microsoft.Maui -{ - public static class ActivityIndicatorExtensions - { - public static void UpdateIsRunning(this ProgressBar progressBar, IActivityIndicator activityIndicator) - { - // TODO - } - - public static void UpdateColor(this ProgressBar progressBar, IActivityIndicator activityIndicator) - { - // TODO - } - } -} \ No newline at end of file diff --git a/src/Core/src/Platform/Windows/ProgressBarExtensions.cs b/src/Core/src/Platform/Windows/ProgressBarExtensions.cs deleted file mode 100644 index 9e4cd534866c..000000000000 --- a/src/Core/src/Platform/Windows/ProgressBarExtensions.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using Microsoft.UI.Xaml.Controls; - -namespace Microsoft.Maui -{ - public static class ProgressBarExtensions - { - public const int Maximum = 10000; - - public static void UpdateProgress(this ProgressBar nativeProgressBar, IProgress progress) - { - throw new NotImplementedException(); - } - } -} \ No newline at end of file diff --git a/src/Core/src/Platform/Windows/ViewExtensions.cs b/src/Core/src/Platform/Windows/ViewExtensions.cs index 407903a286a7..6bfae6980e34 100644 --- a/src/Core/src/Platform/Windows/ViewExtensions.cs +++ b/src/Core/src/Platform/Windows/ViewExtensions.cs @@ -41,7 +41,7 @@ public static void UpdateSemantics(this FrameworkElement nativeView, IView view) AutomationProperties.SetHelpText(nativeView, semantics.Hint); AutomationProperties.SetHeadingLevel(nativeView, (UI.Xaml.Automation.Peers.AutomationHeadingLevel)((int)semantics.HeadingLevel)); } - + internal static void UpdateProperty(this FrameworkElement nativeControl, DependencyProperty property, Color color) { if (color.IsDefault) From 6e1c6b0def4c3384d3b54875b7f399d414310146 Mon Sep 17 00:00:00 2001 From: Matthew Leibowitz Date: Wed, 7 Apr 2021 02:11:42 +0200 Subject: [PATCH 31/48] Use the new ITextStyle --- .../src/Platform/Android/ButtonExtensions.cs | 35 +-------------- .../Platform/Android/DatePickerExtensions.cs | 17 -------- .../Platform/Android/EditTextExtensions.cs | 28 +----------- .../src/Platform/Android/PickerExtensions.cs | 5 --- .../Platform/Android/SearchViewExtensions.cs | 19 ++------ .../Platform/Android/TextViewExtensions.cs | 43 ++++++++----------- .../Platform/Android/TimePickerExtensions.cs | 8 ---- src/Core/src/Platform/iOS/ButtonExtensions.cs | 17 +++----- .../src/Platform/iOS/DatePickerExtensions.cs | 14 ------ src/Core/src/Platform/iOS/LabelExtensions.cs | 28 ++++-------- src/Core/src/Platform/iOS/PickerExtensions.cs | 8 ---- .../src/Platform/iOS/SearchBarExtensions.cs | 10 ++--- .../src/Platform/iOS/TextFieldExtensions.cs | 39 ++++------------- .../src/Platform/iOS/TextViewExtensions.cs | 9 ++-- .../src/Platform/iOS/TimePickerExtensions.cs | 14 ------ 15 files changed, 54 insertions(+), 240 deletions(-) diff --git a/src/Core/src/Platform/Android/ButtonExtensions.cs b/src/Core/src/Platform/Android/ButtonExtensions.cs index 25de30555cec..c910809033d7 100644 --- a/src/Core/src/Platform/Android/ButtonExtensions.cs +++ b/src/Core/src/Platform/Android/ButtonExtensions.cs @@ -1,7 +1,4 @@ -using Android.Content.Res; -using Android.Util; using AndroidX.AppCompat.Widget; -using XColor = Microsoft.Maui.Color; namespace Microsoft.Maui { @@ -10,34 +7,6 @@ public static class ButtonExtensions public static void UpdateText(this AppCompatButton appCompatButton, IButton button) => appCompatButton.Text = button.Text; - public static void UpdateTextColor(this AppCompatButton appCompatButton, IButton button) => - appCompatButton.UpdateTextColor(button.TextColor, appCompatButton.TextColors); - - public static void UpdateTextColor(this AppCompatButton button, XColor color, ColorStateList? defaultColor) - { - if (color.IsDefault) - button.SetTextColor(defaultColor); - else - button.SetTextColor(color.ToNative()); - } - - public static void UpdateTextColor(this AppCompatButton appCompatButton, IButton button, XColor defaultColor) => - appCompatButton.SetTextColor(button.TextColor.Cleanse(defaultColor).ToNative()); - - public static void UpdateCharacterSpacing(this AppCompatButton appCompatButton, IButton button) => - appCompatButton.LetterSpacing = button.CharacterSpacing.ToEm(); - - public static void UpdateFont(this AppCompatButton appCompatButton, IButton button, IFontManager fontManager) - { - var font = button.Font; - - var tf = fontManager.GetTypeface(font); - appCompatButton.Typeface = tf; - - var sp = fontManager.GetScaledPixel(font); - appCompatButton.SetTextSize(ComplexUnitType.Sp, sp); - } - public static void UpdatePadding(this AppCompatButton appCompatButton, IButton button, Thickness? defaultPadding = null) { var context = appCompatButton.Context; @@ -59,7 +28,5 @@ public static void UpdatePadding(this AppCompatButton appCompatButton, IButton b (int)padding.Right, (int)padding.Bottom); } - - static XColor Cleanse(this XColor color, XColor defaultColor) => color.IsDefault ? defaultColor : color; } -} +} \ No newline at end of file diff --git a/src/Core/src/Platform/Android/DatePickerExtensions.cs b/src/Core/src/Platform/Android/DatePickerExtensions.cs index 87ea83ec1cbd..25a0c49fa486 100644 --- a/src/Core/src/Platform/Android/DatePickerExtensions.cs +++ b/src/Core/src/Platform/Android/DatePickerExtensions.cs @@ -1,6 +1,5 @@ using System; using Android.App; -using Android.Util; namespace Microsoft.Maui { @@ -42,22 +41,6 @@ public static void UpdateMaximumDate(this MauiDatePicker nativeDatePicker, IDate } } - public static void UpdateCharacterSpacing(this MauiDatePicker nativeDatePicker, IDatePicker datePicker) - { - nativeDatePicker.LetterSpacing = datePicker.CharacterSpacing.ToEm(); - } - - public static void UpdateFont(this MauiDatePicker nativeDatePicker, IDatePicker datePicker, IFontManager fontManager) - { - var font = datePicker.Font; - - var tf = fontManager.GetTypeface(font); - nativeDatePicker.Typeface = tf; - - var sp = fontManager.GetScaledPixel(font); - nativeDatePicker.SetTextSize(ComplexUnitType.Sp, sp); - } - internal static void SetText(this MauiDatePicker nativeDatePicker, IDatePicker datePicker) { nativeDatePicker.Text = datePicker.Date.ToString(datePicker.Format); diff --git a/src/Core/src/Platform/Android/EditTextExtensions.cs b/src/Core/src/Platform/Android/EditTextExtensions.cs index 509a82e85dea..6ca4eb1ba74c 100644 --- a/src/Core/src/Platform/Android/EditTextExtensions.cs +++ b/src/Core/src/Platform/Android/EditTextExtensions.cs @@ -2,7 +2,6 @@ using Android.Content.Res; using Android.Graphics.Drawables; using Android.Text; -using Android.Util; using AndroidX.AppCompat.Widget; namespace Microsoft.Maui @@ -29,7 +28,7 @@ public static void UpdateText(this AppCompatEditText editText, IEditor editor) editText.SetSelection(editText.Text?.Length ?? 0); } - public static void UpdateTextColor(this AppCompatEditText editText, IEntry entry, ColorStateList? defaultColor) + public static void UpdateTextColor(this AppCompatEditText editText, ITextStyle entry, ColorStateList? defaultColor) { var textColor = entry.TextColor; if (textColor.IsDefault) @@ -143,17 +142,6 @@ public static void UpdateIsReadOnly(this AppCompatEditText editText, IEditor edi editText.SetCursorVisible(isReadOnly); } - public static void UpdateFont(this AppCompatEditText editText, IEntry entry, IFontManager fontManager) - { - var font = entry.Font; - - var tf = fontManager.GetTypeface(font); - editText.Typeface = tf; - - var sp = fontManager.GetScaledPixel(font); - editText.SetTextSize(ComplexUnitType.Sp, sp); - } - public static void UpdateClearButtonVisibility(this AppCompatEditText editText, IEntry entry, Drawable? ClearButtonDrawable) { // Places clear button drawable at the end or start of the EditText based on FlowDirection. @@ -192,23 +180,11 @@ void HideClearButton() } } - public static void UpdateReturnType(this AppCompatEditText editText, IEntry entry) { editText.ImeOptions = entry.ReturnType.ToNative(); } - public static void UpdateFont(this AppCompatEditText editText, IEditor editor, IFontManager fontManager) - { - var font = editor.Font; - - var tf = fontManager.GetTypeface(font); - editText.Typeface = tf; - - var sp = fontManager.GetScaledPixel(font); - editText.SetTextSize(Android.Util.ComplexUnitType.Sp, sp); - } - internal static void SetInputType(this AppCompatEditText editText, IEntry entry) { editText.InputType = InputTypes.ClassText; @@ -232,4 +208,4 @@ internal static void SetInputType(this AppCompatEditText editText, IEntry entry) ? currentText.Substring(0, maxLength) : currentText; } -} +} \ No newline at end of file diff --git a/src/Core/src/Platform/Android/PickerExtensions.cs b/src/Core/src/Platform/Android/PickerExtensions.cs index e5639156a938..2c09a1e9ff4d 100644 --- a/src/Core/src/Platform/Android/PickerExtensions.cs +++ b/src/Core/src/Platform/Android/PickerExtensions.cs @@ -8,11 +8,6 @@ public static void UpdateTitle(this MauiPicker nativePicker, IPicker picker) => public static void UpdateSelectedIndex(this MauiPicker nativePicker, IPicker picker) => UpdatePicker(nativePicker, picker); - public static void UpdateCharacterSpacing(this MauiPicker nativePicker, IPicker picker) - { - nativePicker.LetterSpacing = picker.CharacterSpacing.ToEm(); - } - internal static void UpdatePicker(this MauiPicker nativePicker, IPicker picker) { nativePicker.Hint = picker.Title; diff --git a/src/Core/src/Platform/Android/SearchViewExtensions.cs b/src/Core/src/Platform/Android/SearchViewExtensions.cs index 6083a352b998..772ac001e68d 100644 --- a/src/Core/src/Platform/Android/SearchViewExtensions.cs +++ b/src/Core/src/Platform/Android/SearchViewExtensions.cs @@ -1,5 +1,4 @@ using System.Linq; -using Android.Util; using Android.Widget; using SearchView = AndroidX.AppCompat.Widget.SearchView; @@ -17,25 +16,13 @@ public static void UpdatePlaceholder(this SearchView searchView, ISearchBar sear searchView.QueryHint = searchBar.Placeholder; } - public static void UpdateFont(this SearchView searchView, ISearchBar searchBar, IFontManager fontManager) - { - searchView.UpdateFont(searchBar, fontManager, null); - } - - public static void UpdateFont(this SearchView searchView, ISearchBar searchBar, IFontManager fontManager, EditText? editText) + public static void UpdateFont(this SearchView searchView, ISearchBar searchBar, IFontManager fontManager, EditText? editText = null) { editText ??= searchView.GetChildrenOfType().FirstOrDefault(); - if (editText == null) return; - var font = searchBar.Font; - - var tf = fontManager.GetTypeface(font); - editText.Typeface = tf; - - var sp = fontManager.GetScaledPixel(font); - editText.SetTextSize(ComplexUnitType.Sp, sp); + editText.UpdateFont(searchBar, fontManager); } } -} +} \ No newline at end of file diff --git a/src/Core/src/Platform/Android/TextViewExtensions.cs b/src/Core/src/Platform/Android/TextViewExtensions.cs index a5cef9ec9708..46c9b5230cc4 100644 --- a/src/Core/src/Platform/Android/TextViewExtensions.cs +++ b/src/Core/src/Platform/Android/TextViewExtensions.cs @@ -1,3 +1,4 @@ +using Android.Content.Res; using Android.Graphics; using Android.Text; using Android.Util; @@ -19,40 +20,31 @@ public static void UpdateText(this TextView textView, string newText) textView.Text = newText; } - public static void UpdateTextColor(this TextView textView, ILabel label, Color defaultColor) + public static void UpdateTextColor(this TextView textView, ITextStyle textStyle, Color defaultColor) { - Color textColor = label.TextColor; - + var textColor = textStyle.TextColor; if (textColor.IsDefault) - { textView.SetTextColor(defaultColor.ToNative()); - } else - { textView.SetTextColor(textColor.ToNative()); - } } - public static void UpdateCharacterSpacing(this TextView textView, IEntry entry) => - UpdateCharacterSpacing(textView, entry.CharacterSpacing); - - public static void UpdateCharacterSpacing(this TextView textView, IEditor editor) => - UpdateCharacterSpacing(textView, editor.CharacterSpacing); - - public static void UpdateCharacterSpacing(this TextView textView, ILabel label) => - UpdateCharacterSpacing(textView, label.CharacterSpacing); - - public static void UpdateCharacterSpacing(this TextView textView, ISearchBar searchBar) => - UpdateCharacterSpacing(textView, searchBar.CharacterSpacing); + public static void UpdateTextColor(this TextView textView, ITextStyle textStyle) => + textView.UpdateTextColor(textStyle, textView.TextColors); - public static void UpdateCharacterSpacing(this TextView textView, double characterSpacing) => - textView.LetterSpacing = characterSpacing.ToEm(); - - public static void UpdateFont(this TextView textView, ILabel label, IFontManager fontManager) => - UpdateFont(textView, label.Font, fontManager); + public static void UpdateTextColor(this TextView textView, ITextStyle textStyle, ColorStateList? defaultColor) + { + var textColor = textStyle.TextColor; + if (textColor.IsDefault) + textView.SetTextColor(defaultColor); + else + textView.SetTextColor(textColor.ToNative()); + } - public static void UpdateFont(this TextView textView, Font font, IFontManager fontManager) + public static void UpdateFont(this TextView textView, ITextStyle textStyle, IFontManager fontManager) { + var font = textStyle.Font; + var tf = fontManager.GetTypeface(font); textView.Typeface = tf; @@ -60,6 +52,9 @@ public static void UpdateFont(this TextView textView, Font font, IFontManager fo textView.SetTextSize(ComplexUnitType.Sp, sp); } + public static void UpdateCharacterSpacing(this TextView textView, ITextStyle textStyle) => + textView.LetterSpacing = textStyle.CharacterSpacing.ToEm(); + public static void UpdateHorizontalTextAlignment(this TextView textView, ITextAlignment text) { if (textView.Context!.HasRtlSupport()) diff --git a/src/Core/src/Platform/Android/TimePickerExtensions.cs b/src/Core/src/Platform/Android/TimePickerExtensions.cs index 6f366e1cfb4b..aa3b84779632 100644 --- a/src/Core/src/Platform/Android/TimePickerExtensions.cs +++ b/src/Core/src/Platform/Android/TimePickerExtensions.cs @@ -12,14 +12,6 @@ public static void UpdateTime(this MauiTimePicker mauiTimePicker, ITimePicker ti mauiTimePicker.SetTime(timePicker); } - public static void UpdateCharacterSpacing(this MauiTimePicker mauiTimePicker, ITimePicker timePicker) - { - mauiTimePicker.LetterSpacing = timePicker.CharacterSpacing.ToEm(); - } - - public static void UpdateFont(this MauiTimePicker mauiTimePicker, ITimePicker timePicker, IFontManager fontManager) => - mauiTimePicker.UpdateFont(timePicker.Font, fontManager); - internal static void SetTime(this MauiTimePicker mauiTimePicker, ITimePicker timePicker) { var time = timePicker.Time; diff --git a/src/Core/src/Platform/iOS/ButtonExtensions.cs b/src/Core/src/Platform/iOS/ButtonExtensions.cs index 71582482f8f0..d87b4e4047ae 100644 --- a/src/Core/src/Platform/iOS/ButtonExtensions.cs +++ b/src/Core/src/Platform/iOS/ButtonExtensions.cs @@ -30,21 +30,14 @@ public static void UpdateTextColor(this UIButton nativeButton, IButton button, U } } - public static void UpdateCharacterSpacing(this UIButton nativeButton, IButton button) + public static void UpdateCharacterSpacing(this UIButton nativeButton, ITextStyle textStyle) { - if (string.IsNullOrEmpty(button.Text)) - return; - - var textAttr = nativeButton.TitleLabel.AttributedText?.WithCharacterSpacing(button.CharacterSpacing); - - if (textAttr != null) - nativeButton.TitleLabel.AttributedText = textAttr; + nativeButton.TitleLabel.UpdateCharacterSpacing(textStyle); } - public static void UpdateFont(this UIButton nativeButton, IButton button, IFontManager fontManager) + public static void UpdateFont(this UIButton nativeButton, ITextStyle textStyle, IFontManager fontManager) { - var uiFont = fontManager.GetFont(button.Font); - nativeButton.TitleLabel.Font = uiFont; + nativeButton.TitleLabel.UpdateFont(textStyle, fontManager); } public static void UpdatePadding(this UIButton nativeButton, IButton button) @@ -56,4 +49,4 @@ public static void UpdatePadding(this UIButton nativeButton, IButton button) (float)button.Padding.Right); } } -} +} \ No newline at end of file diff --git a/src/Core/src/Platform/iOS/DatePickerExtensions.cs b/src/Core/src/Platform/iOS/DatePickerExtensions.cs index 18233cb95782..27996d70a138 100644 --- a/src/Core/src/Platform/iOS/DatePickerExtensions.cs +++ b/src/Core/src/Platform/iOS/DatePickerExtensions.cs @@ -52,19 +52,5 @@ public static void UpdateMaximumDate(this MauiDatePicker nativeDatePicker, IDate picker.MaximumDate = datePicker.MaximumDate.ToNSDate(); } } - - public static void UpdateCharacterSpacing(this MauiDatePicker nativeDatePicker, IDatePicker datePicker) - { - var textAttr = nativeDatePicker.AttributedText?.WithCharacterSpacing(datePicker.CharacterSpacing); - - if (textAttr != null) - nativeDatePicker.AttributedText = textAttr; - } - - public static void UpdateFont(this MauiDatePicker nativeDatePicker, IDatePicker datePicker, IFontManager fontManager) - { - var uiFont = fontManager.GetFont(datePicker.Font); - nativeDatePicker.Font = uiFont; - } } } \ No newline at end of file diff --git a/src/Core/src/Platform/iOS/LabelExtensions.cs b/src/Core/src/Platform/iOS/LabelExtensions.cs index 0b37daf1054b..11938016f0f5 100644 --- a/src/Core/src/Platform/iOS/LabelExtensions.cs +++ b/src/Core/src/Platform/iOS/LabelExtensions.cs @@ -10,35 +10,23 @@ public static void UpdateText(this UILabel nativeLabel, ILabel label) nativeLabel.Text = label.Text; } - public static void UpdateTextColor(this UILabel nativeLabel, ILabel label) + public static void UpdateTextColor(this UILabel nativeLabel, ITextStyle textStyle, UIColor? defaultColor = null) { - var textColor = label.TextColor; - - if (textColor.IsDefault) - { - // Default value of color documented to be black in iOS docs - nativeLabel.TextColor = textColor.ToNative(ColorExtensions.LabelColor); - } - else - { - nativeLabel.TextColor = textColor.ToNative(textColor); - } + // Default value of color documented to be black in iOS docs + var textColor = textStyle.TextColor; + nativeLabel.TextColor = textColor.ToNative(defaultColor ?? ColorExtensions.LabelColor); } - public static void UpdateCharacterSpacing(this UILabel nativeLabel, ILabel label) + public static void UpdateCharacterSpacing(this UILabel nativeLabel, ITextStyle textStyle) { - if (string.IsNullOrEmpty(label.Text)) - return; - - var textAttr = nativeLabel.AttributedText?.WithCharacterSpacing(label.CharacterSpacing); - + var textAttr = nativeLabel.AttributedText?.WithCharacterSpacing(textStyle.CharacterSpacing); if (textAttr != null) nativeLabel.AttributedText = textAttr; } - public static void UpdateFont(this UILabel nativeLabel, ILabel label, IFontManager fontManager) + public static void UpdateFont(this UILabel nativeLabel, ITextStyle textStyle, IFontManager fontManager) { - var uiFont = fontManager.GetFont(label.Font); + var uiFont = fontManager.GetFont(textStyle.Font); nativeLabel.Font = uiFont; } diff --git a/src/Core/src/Platform/iOS/PickerExtensions.cs b/src/Core/src/Platform/iOS/PickerExtensions.cs index 2fe4fcb88b84..dfc05168be48 100644 --- a/src/Core/src/Platform/iOS/PickerExtensions.cs +++ b/src/Core/src/Platform/iOS/PickerExtensions.cs @@ -30,14 +30,6 @@ internal static void UpdatePicker(this MauiPicker nativePicker, IPicker picker) nativePicker.SetSelectedItem(picker); } - public static void UpdateCharacterSpacing(this MauiPicker nativePicker, IPicker picker) - { - var textAttr = nativePicker.AttributedText?.WithCharacterSpacing(picker.CharacterSpacing); - - if (textAttr != null) - nativePicker.AttributedText = textAttr; - } - internal static void SetSelectedIndex(this MauiPicker nativePicker, IPicker picker, int selectedIndex = 0) { picker.SelectedIndex = selectedIndex; diff --git a/src/Core/src/Platform/iOS/SearchBarExtensions.cs b/src/Core/src/Platform/iOS/SearchBarExtensions.cs index bad5763992ba..356b0d3cf9eb 100644 --- a/src/Core/src/Platform/iOS/SearchBarExtensions.cs +++ b/src/Core/src/Platform/iOS/SearchBarExtensions.cs @@ -14,20 +14,18 @@ public static void UpdatePlaceholder(this UISearchBar uiSearchBar, ISearchBar se uiSearchBar.Placeholder = searchBar.Placeholder; } - public static void UpdateFont(this UISearchBar uiSearchBar, ISearchBar searchBar, IFontManager fontManager) + public static void UpdateFont(this UISearchBar uiSearchBar, ITextStyle textStyle, IFontManager fontManager) { - uiSearchBar.UpdateFont(searchBar, fontManager, null); + uiSearchBar.UpdateFont(textStyle, fontManager, null); } - public static void UpdateFont(this UISearchBar uiSearchBar, ISearchBar searchBar, IFontManager fontManager, UITextField? textField) + public static void UpdateFont(this UISearchBar uiSearchBar, ITextStyle textStyle, IFontManager fontManager, UITextField? textField) { textField ??= uiSearchBar.FindDescendantView(); - if (textField == null) return; - var uiFont = fontManager.GetFont(searchBar.Font); - textField.Font = uiFont; + textField.UpdateFont(textStyle, fontManager); } } } \ No newline at end of file diff --git a/src/Core/src/Platform/iOS/TextFieldExtensions.cs b/src/Core/src/Platform/iOS/TextFieldExtensions.cs index 9d31b7301ed5..34c107a672c5 100644 --- a/src/Core/src/Platform/iOS/TextFieldExtensions.cs +++ b/src/Core/src/Platform/iOS/TextFieldExtensions.cs @@ -9,20 +9,12 @@ public static void UpdateText(this UITextField textField, IEntry entry) textField.Text = entry.Text; } - public static void UpdateTextColor(this UITextField textField, IEntry entry) + public static void UpdateTextColor(this UITextField textField, ITextStyle textStyle, UIColor? defaultTextColor = null) { - textField.UpdateTextColor(entry, null); - } + // Default value of color documented to be black in iOS docs - public static void UpdateTextColor(this UITextField textField, IEntry entry, UIColor? defaultTextColor) - { - if (entry.TextColor == Color.Default) - { - if (defaultTextColor != null) - textField.TextColor = defaultTextColor; - } - else - textField.TextColor = entry.TextColor.ToNative(); + var textColor = textStyle.TextColor; + textField.TextColor = textColor.ToNative(defaultTextColor ?? ColorExtensions.LabelColor); } public static void UpdateIsPassword(this UITextField textField, IEntry entry) @@ -72,9 +64,9 @@ public static void UpdateIsReadOnly(this UITextField textField, IEntry entry) textField.UserInteractionEnabled = !entry.IsReadOnly; } - public static void UpdateFont(this UITextField textField, IEntry entry, IFontManager fontManager) + public static void UpdateFont(this UITextField textField, ITextStyle textStyle, IFontManager fontManager) { - var uiFont = fontManager.GetFont(entry.Font); + var uiFont = fontManager.GetFont(textStyle.Font); textField.Font = uiFont; } @@ -83,28 +75,13 @@ public static void UpdateReturnType(this UITextField textField, IEntry entry) textField.ReturnKeyType = entry.ReturnType.ToNative(); } - public static void UpdateCharacterSpacing(this UITextField textField, IText textView) - { - var textAttr = textField.AttributedText?.WithCharacterSpacing(textView.CharacterSpacing); - - if (textAttr != null) - textField.AttributedText = textAttr; - } - - public static void UpdateCharacterSpacing(this UITextField textField, IEntry textView) + public static void UpdateCharacterSpacing(this UITextField textField, ITextStyle textStyle) { - var textAttr = textField.AttributedText?.WithCharacterSpacing(textView.CharacterSpacing); - + var textAttr = textField.AttributedText?.WithCharacterSpacing(textStyle.CharacterSpacing); if (textAttr != null) textField.AttributedText = textAttr; } - public static void UpdateFont(this UITextField textField, IText textView, IFontManager fontManager) - { - var uiFont = fontManager.GetFont(textView.Font); - textField.Font = uiFont; - } - public static void UpdateClearButtonVisibility(this UITextField textField, IEntry entry) { textField.ClearButtonMode = entry.ClearButtonVisibility == ClearButtonVisibility.WhileEditing ? UITextFieldViewMode.WhileEditing : UITextFieldViewMode.Never; diff --git a/src/Core/src/Platform/iOS/TextViewExtensions.cs b/src/Core/src/Platform/iOS/TextViewExtensions.cs index 03c3a4eb4501..9621b2698f0e 100644 --- a/src/Core/src/Platform/iOS/TextViewExtensions.cs +++ b/src/Core/src/Platform/iOS/TextViewExtensions.cs @@ -14,10 +14,9 @@ public static void UpdateText(this UITextView textView, IEditor editor) } } - public static void UpdateCharacterSpacing(this UITextView textView, IEditor editor) + public static void UpdateCharacterSpacing(this UITextView textView, ITextStyle textStyle) { - var textAttr = textView.AttributedText?.WithCharacterSpacing(editor.CharacterSpacing); - + var textAttr = textView.AttributedText?.WithCharacterSpacing(textStyle.CharacterSpacing); if (textAttr != null) textView.AttributedText = textAttr; @@ -38,9 +37,9 @@ public static void UpdatePredictiveText(this UITextView textView, IEditor editor ? UITextAutocorrectionType.Yes : UITextAutocorrectionType.No; } - public static void UpdateFont(this UITextView textView, IEditor editor, IFontManager fontManager) + public static void UpdateFont(this UITextView textView, ITextStyle textStyle, IFontManager fontManager) { - var uiFont = fontManager.GetFont(editor.Font); + var uiFont = fontManager.GetFont(textStyle.Font); textView.Font = uiFont; } diff --git a/src/Core/src/Platform/iOS/TimePickerExtensions.cs b/src/Core/src/Platform/iOS/TimePickerExtensions.cs index 3e377041ad76..3b3a03830f1f 100644 --- a/src/Core/src/Platform/iOS/TimePickerExtensions.cs +++ b/src/Core/src/Platform/iOS/TimePickerExtensions.cs @@ -61,19 +61,5 @@ public static void UpdateTime(this MauiTimePicker mauiTimePicker, ITimePicker ti mauiTimePicker.UpdateCharacterSpacing(timePicker); } - - public static void UpdateCharacterSpacing(this MauiTimePicker mauiTimePicker, ITimePicker timePicker) - { - var textAttr = mauiTimePicker.AttributedText?.WithCharacterSpacing(timePicker.CharacterSpacing); - - if (textAttr != null) - mauiTimePicker.AttributedText = textAttr; - } - - public static void UpdateFont(this MauiTimePicker mauiTimePicker, ITimePicker timePicker, IFontManager fontManager) - { - var uiFont = fontManager.GetFont(timePicker.Font); - mauiTimePicker.Font = uiFont; - } } } \ No newline at end of file From 06f8e4fcb0bb631a619ea47ad651e879f2e6cc8d Mon Sep 17 00:00:00 2001 From: Matthew Leibowitz Date: Wed, 7 Apr 2021 02:15:51 +0200 Subject: [PATCH 32/48] Fix tests --- src/Core/tests/DeviceTests/Stubs/DatePickerStub.cs | 2 ++ src/Core/tests/DeviceTests/Stubs/PickerStub.cs | 4 ++++ src/Core/tests/DeviceTests/Stubs/SearchBarStub.cs | 6 ++++++ src/Core/tests/DeviceTests/Stubs/TimePickerStub.cs | 2 ++ 4 files changed, 14 insertions(+) diff --git a/src/Core/tests/DeviceTests/Stubs/DatePickerStub.cs b/src/Core/tests/DeviceTests/Stubs/DatePickerStub.cs index 939e1d23b853..28868a0fc68a 100644 --- a/src/Core/tests/DeviceTests/Stubs/DatePickerStub.cs +++ b/src/Core/tests/DeviceTests/Stubs/DatePickerStub.cs @@ -15,5 +15,7 @@ public partial class DatePickerStub : StubBase, IDatePicker public double CharacterSpacing { get; set; } public Font Font { get; set; } + + public Color TextColor { get; set; } } } \ No newline at end of file diff --git a/src/Core/tests/DeviceTests/Stubs/PickerStub.cs b/src/Core/tests/DeviceTests/Stubs/PickerStub.cs index 66681f5755df..3fde154c187d 100644 --- a/src/Core/tests/DeviceTests/Stubs/PickerStub.cs +++ b/src/Core/tests/DeviceTests/Stubs/PickerStub.cs @@ -16,5 +16,9 @@ public partial class PickerStub : StubBase, IPicker public object SelectedItem { get; set; } public double CharacterSpacing { get; set; } + + public Color TextColor { get; set; } + + public Font Font { get; set; } } } \ No newline at end of file diff --git a/src/Core/tests/DeviceTests/Stubs/SearchBarStub.cs b/src/Core/tests/DeviceTests/Stubs/SearchBarStub.cs index 8991b64b45d9..aaa6462a31ef 100644 --- a/src/Core/tests/DeviceTests/Stubs/SearchBarStub.cs +++ b/src/Core/tests/DeviceTests/Stubs/SearchBarStub.cs @@ -15,5 +15,11 @@ public partial class SearchBarStub : StubBase, ISearchBar public Font Font { get; set; } public TextAlignment HorizontalTextAlignment { get; set; } + + public bool IsTextPredictionEnabled { get; set; } + + public bool IsReadOnly { get; set; } + + public int MaxLength { get; set; } } } \ No newline at end of file diff --git a/src/Core/tests/DeviceTests/Stubs/TimePickerStub.cs b/src/Core/tests/DeviceTests/Stubs/TimePickerStub.cs index 608c889b5554..22a092133379 100644 --- a/src/Core/tests/DeviceTests/Stubs/TimePickerStub.cs +++ b/src/Core/tests/DeviceTests/Stubs/TimePickerStub.cs @@ -17,5 +17,7 @@ public TimeSpan Time public double CharacterSpacing { get; set; } public Font Font { get; set; } + + public Color TextColor { get; set; } } } \ No newline at end of file From dff6f23cbbaa2c779e213c2fd5a79a0939a627bd Mon Sep 17 00:00:00 2001 From: Matthew Leibowitz Date: Wed, 7 Apr 2021 03:53:50 +0200 Subject: [PATCH 33/48] Do not fire text changed if nothing changed --- src/Core/src/Handlers/Entry/EntryHandler.Android.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Core/src/Handlers/Entry/EntryHandler.Android.cs b/src/Core/src/Handlers/Entry/EntryHandler.Android.cs index 0c03eee0e9a6..9a203366451d 100644 --- a/src/Core/src/Handlers/Entry/EntryHandler.Android.cs +++ b/src/Core/src/Handlers/Entry/EntryHandler.Android.cs @@ -209,6 +209,10 @@ void ITextWatcher.BeforeTextChanged(Java.Lang.ICharSequence? s, int start, int c void ITextWatcher.OnTextChanged(Java.Lang.ICharSequence? s, int start, int before, int count) { + // we are replacing 0 characters with 0 characters, so skip + if (before == 0 && count == 0) + return; + Handler?.OnTextChanged(s?.ToString()); } } From 01ba0045a261831f80323c51bd10e30c7d626462 Mon Sep 17 00:00:00 2001 From: Matthew Leibowitz Date: Wed, 7 Apr 2021 04:54:40 +0200 Subject: [PATCH 34/48] MaxLength == -1 crashes --- .../src/Platform/Android/EditTextExtensions.cs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/Core/src/Platform/Android/EditTextExtensions.cs b/src/Core/src/Platform/Android/EditTextExtensions.cs index 6ca4eb1ba74c..fed1ac028b24 100644 --- a/src/Core/src/Platform/Android/EditTextExtensions.cs +++ b/src/Core/src/Platform/Android/EditTextExtensions.cs @@ -79,21 +79,30 @@ public static void UpdateMaxLength(this AppCompatEditText editText, IEditor edit public static void UpdateMaxLength(this AppCompatEditText editText, int maxLength) { var currentFilters = new List(editText.GetFilters() ?? new IInputFilter[0]); + var changed = false; for (var i = 0; i < currentFilters.Count; i++) { if (currentFilters[i] is InputFilterLengthFilter) { currentFilters.RemoveAt(i); + changed = true; break; } } - currentFilters.Add(new InputFilterLengthFilter(maxLength)); + if (maxLength > 0) + { + currentFilters.Add(new InputFilterLengthFilter(maxLength)); + changed = true; + } - editText.SetFilters(currentFilters.ToArray()); + if (changed) + editText.SetFilters(currentFilters.ToArray()); - editText.Text = TrimToMaxLength(editText.Text, maxLength); + var newText = TrimToMaxLength(editText.Text, maxLength); + if (editText.Text != newText) + editText.Text = newText; } public static void UpdatePlaceholder(this AppCompatEditText editText, IPlaceholder textInput) @@ -204,7 +213,7 @@ internal static void SetInputType(this AppCompatEditText editText, IEntry entry) } internal static string? TrimToMaxLength(string? currentText, int maxLength) => - currentText?.Length > maxLength + maxLength >= 0 && currentText?.Length > maxLength ? currentText.Substring(0, maxLength) : currentText; } From 103d029ff2a2ba80b7a4ecd8d5a8e605991ee465 Mon Sep 17 00:00:00 2001 From: Matthew Leibowitz Date: Wed, 7 Apr 2021 04:55:16 +0200 Subject: [PATCH 35/48] MaxLines < 0 == everything --- src/Core/src/Platform/Android/TextViewExtensions.cs | 4 +--- src/Core/src/Platform/iOS/LabelExtensions.cs | 9 ++------- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/src/Core/src/Platform/Android/TextViewExtensions.cs b/src/Core/src/Platform/Android/TextViewExtensions.cs index 46c9b5230cc4..ea37a972fb54 100644 --- a/src/Core/src/Platform/Android/TextViewExtensions.cs +++ b/src/Core/src/Platform/Android/TextViewExtensions.cs @@ -78,9 +78,7 @@ public static void UpdateLineBreakMode(this TextView textView, ILabel label) public static void UpdateMaxLines(this TextView textView, ILabel label) { - int maxLinex = label.MaxLines; - - textView.SetMaxLines(maxLinex); + textView.SetLineBreakMode(label); } public static void UpdatePadding(this TextView textView, ILabel label) diff --git a/src/Core/src/Platform/iOS/LabelExtensions.cs b/src/Core/src/Platform/iOS/LabelExtensions.cs index 11938016f0f5..01a34d4f2e6f 100644 --- a/src/Core/src/Platform/iOS/LabelExtensions.cs +++ b/src/Core/src/Platform/iOS/LabelExtensions.cs @@ -40,17 +40,12 @@ public static void UpdateHorizontalTextAlignment(this UILabel nativeLabel, ILabe public static void UpdateLineBreakMode(this UILabel nativeLabel, ILabel label) { - SetLineBreakMode(nativeLabel, label); + nativeLabel.SetLineBreakMode(label); } public static void UpdateMaxLines(this UILabel nativeLabel, ILabel label) { - int maxLines = label.MaxLines; - - if (maxLines >= 0) - { - nativeLabel.Lines = maxLines; - } + nativeLabel.SetLineBreakMode(label); } public static void UpdatePadding(this MauiLabel nativeLabel, ILabel label) From c8c6e72981c17aa29f3d5886872d15d3f9b5575d Mon Sep 17 00:00:00 2001 From: Matthew Leibowitz Date: Wed, 7 Apr 2021 04:55:27 +0200 Subject: [PATCH 36/48] Added a test --- .../Handlers/Entry/EntryHandlerTests.cs | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.cs b/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.cs index 2bbc7c02889b..a2adf7b560a5 100644 --- a/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.cs +++ b/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.cs @@ -274,6 +274,27 @@ public async Task MaxLengthInitializesCorrectly(int maxLength) Assert.Equal(expectedText, entry.Text); } + [Fact(DisplayName = "Negative MaxLength Does Not Clip")] + public async Task NegativeMaxLengthDoesNotClip() + { + const string text = "Lorem ipsum dolor sit amet"; + + var entry = new EntryStub() + { + MaxLength = -1, + }; + + var nativeText = await GetValueAsync(entry, handler => + { + entry.Text = text; + + return GetNativeText(handler); + }); + + Assert.Equal(text, nativeText); + Assert.Equal(text, entry.Text); + } + [Theory(DisplayName = "MaxLength Clips Native Text Correctly")] [InlineData(2)] [InlineData(5)] From 6915a2afe1d514bdc1246251517239e90d3fe89f Mon Sep 17 00:00:00 2001 From: Matthew Leibowitz Date: Wed, 7 Apr 2021 05:09:55 +0200 Subject: [PATCH 37/48] Attach that event! --- .../src/Handlers/CheckBox/CheckBoxHandler.Windows.cs | 12 +++++++++--- .../Handlers/DatePicker/DatePickerHandler.Windows.cs | 3 +++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/Core/src/Handlers/CheckBox/CheckBoxHandler.Windows.cs b/src/Core/src/Handlers/CheckBox/CheckBoxHandler.Windows.cs index 2b00a50035eb..f9df7a724df4 100644 --- a/src/Core/src/Handlers/CheckBox/CheckBoxHandler.Windows.cs +++ b/src/Core/src/Handlers/CheckBox/CheckBoxHandler.Windows.cs @@ -1,4 +1,4 @@ -using System; +using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; namespace Microsoft.Maui.Handlers @@ -11,19 +11,25 @@ protected override void ConnectHandler(CheckBox nativeView) { base.ConnectHandler(nativeView); - nativeView.CheckedChanged += OnCheckedChanged; + nativeView.Checked += OnChecked; } protected override void DisconnectHandler(CheckBox nativeView) { base.DisconnectHandler(nativeView); - nativeView.CheckedChanged -= OnCheckedChanged; + nativeView.Checked -= OnChecked; } public static void MapIsChecked(CheckBoxHandler handler, ICheckBox check) { handler.NativeView?.UpdateIsChecked(check); } + + void OnChecked(object sender, RoutedEventArgs e) + { + if (sender is CheckBox nativeView && VirtualView != null) + VirtualView.IsChecked = nativeView.IsChecked == true; + } } } \ No newline at end of file diff --git a/src/Core/src/Handlers/DatePicker/DatePickerHandler.Windows.cs b/src/Core/src/Handlers/DatePicker/DatePickerHandler.Windows.cs index 451dbe0dcbfc..a249127704c6 100644 --- a/src/Core/src/Handlers/DatePicker/DatePickerHandler.Windows.cs +++ b/src/Core/src/Handlers/DatePicker/DatePickerHandler.Windows.cs @@ -24,5 +24,8 @@ public static void MapCharacterSpacing(DatePickerHandler handler, IDatePicker da [MissingMapper] public static void MapFont(DatePickerHandler handler, IDatePicker datePicker) { } + + [MissingMapper] + public static void MapTextColor(DatePickerHandler handler, IDatePicker datePicker) { } } } \ No newline at end of file From ebfda45f84c57fc07c1534a9f6d2e34fa099add8 Mon Sep 17 00:00:00 2001 From: Matthew Leibowitz Date: Wed, 7 Apr 2021 05:14:16 +0200 Subject: [PATCH 38/48] That is correct, 2 events --- src/Controls/samples/Controls.Sample/Pages/MainPage.cs | 7 ++++++- src/Core/src/Handlers/CheckBox/CheckBoxHandler.Windows.cs | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Controls/samples/Controls.Sample/Pages/MainPage.cs b/src/Controls/samples/Controls.Sample/Pages/MainPage.cs index 5fd6bdef68ad..c264481317c4 100644 --- a/src/Controls/samples/Controls.Sample/Pages/MainPage.cs +++ b/src/Controls/samples/Controls.Sample/Pages/MainPage.cs @@ -114,7 +114,12 @@ void SetupMauiLayout() verticalStack.Add(new Button { Text = "CharacterSpacing" }); verticalStack.Add(new Button { CharacterSpacing = 8, Text = "CharacterSpacing" }); - verticalStack.Add(new CheckBox()); + var checkbox = new CheckBox(); + checkbox.CheckedChanged += (sender, e) => + { + Debug.WriteLine($"Checked Changed to '{e.Value}'"); + }; + verticalStack.Add(checkbox); verticalStack.Add(new CheckBox { BackgroundColor = Color.LightPink }); verticalStack.Add(new CheckBox { IsChecked = true, Color = Color.Aquamarine }); diff --git a/src/Core/src/Handlers/CheckBox/CheckBoxHandler.Windows.cs b/src/Core/src/Handlers/CheckBox/CheckBoxHandler.Windows.cs index f9df7a724df4..8d6fad76e265 100644 --- a/src/Core/src/Handlers/CheckBox/CheckBoxHandler.Windows.cs +++ b/src/Core/src/Handlers/CheckBox/CheckBoxHandler.Windows.cs @@ -12,6 +12,7 @@ protected override void ConnectHandler(CheckBox nativeView) base.ConnectHandler(nativeView); nativeView.Checked += OnChecked; + nativeView.Unchecked += OnChecked; } protected override void DisconnectHandler(CheckBox nativeView) @@ -19,6 +20,7 @@ protected override void DisconnectHandler(CheckBox nativeView) base.DisconnectHandler(nativeView); nativeView.Checked -= OnChecked; + nativeView.Unchecked -= OnChecked; } public static void MapIsChecked(CheckBoxHandler handler, ICheckBox check) From e367844ee0e981e83526fa1d117c3138070633f8 Mon Sep 17 00:00:00 2001 From: Matthew Leibowitz Date: Wed, 7 Apr 2021 05:16:30 +0200 Subject: [PATCH 39/48] Fix null ref --- src/Core/src/Platform/iOS/ViewExtensions.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Core/src/Platform/iOS/ViewExtensions.cs b/src/Core/src/Platform/iOS/ViewExtensions.cs index 0943f31ad036..a29192ca6cb9 100644 --- a/src/Core/src/Platform/iOS/ViewExtensions.cs +++ b/src/Core/src/Platform/iOS/ViewExtensions.cs @@ -32,10 +32,14 @@ public static void UpdateAutomationId(this UIView nativeView, IView view) => public static void UpdateSemantics(this UIView nativeView, IView view) { - nativeView.AccessibilityLabel = view.Semantics.Description; - nativeView.AccessibilityHint = view.Semantics.Hint; + var semantics = view.Semantics; + if (semantics == null) + return; + + nativeView.AccessibilityLabel = semantics.Description; + nativeView.AccessibilityHint = semantics.Hint; - if (view.Semantics.IsHeading) + if (semantics.IsHeading) nativeView.AccessibilityTraits |= UIAccessibilityTrait.Header; else nativeView.AccessibilityTraits |= ~UIAccessibilityTrait.Header; From 7c858536b474f78c70eb91a960e62edcd850a776 Mon Sep 17 00:00:00 2001 From: Matthew Leibowitz Date: Wed, 7 Apr 2021 05:29:14 +0200 Subject: [PATCH 40/48] Don't crash on -1 max length --- src/Core/src/Platform/Android/EditTextExtensions.cs | 7 +------ src/Core/src/Platform/StringExtensions.cs | 10 ++++++++++ .../src/Platform/iOS/AttributedStringExtensions.cs | 5 +++++ src/Core/src/Platform/iOS/TextFieldExtensions.cs | 7 +++---- src/Core/src/Platform/iOS/TextViewExtensions.cs | 7 +++---- 5 files changed, 22 insertions(+), 14 deletions(-) create mode 100644 src/Core/src/Platform/StringExtensions.cs diff --git a/src/Core/src/Platform/Android/EditTextExtensions.cs b/src/Core/src/Platform/Android/EditTextExtensions.cs index fed1ac028b24..e371b158595b 100644 --- a/src/Core/src/Platform/Android/EditTextExtensions.cs +++ b/src/Core/src/Platform/Android/EditTextExtensions.cs @@ -100,7 +100,7 @@ public static void UpdateMaxLength(this AppCompatEditText editText, int maxLengt if (changed) editText.SetFilters(currentFilters.ToArray()); - var newText = TrimToMaxLength(editText.Text, maxLength); + var newText = editText.Text.TrimToMaxLength(maxLength); if (editText.Text != newText) editText.Text = newText; } @@ -211,10 +211,5 @@ internal static void SetInputType(this AppCompatEditText editText, IEntry entry) if (entry.IsReadOnly) editText.InputType = InputTypes.Null; } - - internal static string? TrimToMaxLength(string? currentText, int maxLength) => - maxLength >= 0 && currentText?.Length > maxLength - ? currentText.Substring(0, maxLength) - : currentText; } } \ No newline at end of file diff --git a/src/Core/src/Platform/StringExtensions.cs b/src/Core/src/Platform/StringExtensions.cs new file mode 100644 index 000000000000..691754b0735c --- /dev/null +++ b/src/Core/src/Platform/StringExtensions.cs @@ -0,0 +1,10 @@ +namespace Microsoft.Maui +{ + internal static class StringExtensions + { + public static string? TrimToMaxLength(this string? currentText, int maxLength) => + maxLength >= 0 && currentText?.Length > maxLength + ? currentText.Substring(0, maxLength) + : currentText; + } +} \ No newline at end of file diff --git a/src/Core/src/Platform/iOS/AttributedStringExtensions.cs b/src/Core/src/Platform/iOS/AttributedStringExtensions.cs index c7d1a7fed7fb..525654757070 100644 --- a/src/Core/src/Platform/iOS/AttributedStringExtensions.cs +++ b/src/Core/src/Platform/iOS/AttributedStringExtensions.cs @@ -70,6 +70,11 @@ public static class AttributedStringExtensions return mutable; } + public static NSAttributedString? TrimToMaxLength(this NSAttributedString? attributedString, int maxLength) => + maxLength >= 0 && attributedString?.Length > maxLength + ? attributedString.Substring(0, maxLength) + : attributedString; + static void UpdateDecoration(NSMutableAttributedString attributedString, NSString key, NSRange range, TextDecorations decorations) { diff --git a/src/Core/src/Platform/iOS/TextFieldExtensions.cs b/src/Core/src/Platform/iOS/TextFieldExtensions.cs index 34c107a672c5..c4ae91a373df 100644 --- a/src/Core/src/Platform/iOS/TextFieldExtensions.cs +++ b/src/Core/src/Platform/iOS/TextFieldExtensions.cs @@ -48,10 +48,9 @@ public static void UpdateIsTextPredictionEnabled(this UITextField textField, IEn public static void UpdateMaxLength(this UITextField textField, IEntry entry) { - var currentControlText = textField.Text; - - if (currentControlText?.Length > entry.MaxLength) - textField.Text = currentControlText.Substring(0, entry.MaxLength); + var newText = textField.AttributedText.TrimToMaxLength(entry.MaxLength); + if (textField.AttributedText != newText) + textField.AttributedText = newText; } public static void UpdatePlaceholder(this UITextField textField, IEntry entry) diff --git a/src/Core/src/Platform/iOS/TextViewExtensions.cs b/src/Core/src/Platform/iOS/TextViewExtensions.cs index 9621b2698f0e..952d56b14e10 100644 --- a/src/Core/src/Platform/iOS/TextViewExtensions.cs +++ b/src/Core/src/Platform/iOS/TextViewExtensions.cs @@ -25,10 +25,9 @@ public static void UpdateCharacterSpacing(this UITextView textView, ITextStyle t public static void UpdateMaxLength(this UITextView textView, IEditor editor) { - var currentControlText = textView.Text; - - if (currentControlText?.Length > editor.MaxLength) - textView.Text = currentControlText.Substring(0, editor.MaxLength); + var newText = textView.AttributedText.TrimToMaxLength(editor.MaxLength); + if (textView.AttributedText != newText) + textView.AttributedText = newText; } public static void UpdatePredictiveText(this UITextView textView, IEditor editor) From eb28089bbef33f53fa1cb44fa1c675d82064d86d Mon Sep 17 00:00:00 2001 From: Matthew Leibowitz Date: Wed, 7 Apr 2021 05:45:50 +0200 Subject: [PATCH 41/48] nulls are uncool here --- src/Core/src/Platform/iOS/TextFieldExtensions.cs | 2 +- src/Core/src/Platform/iOS/TextViewExtensions.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Core/src/Platform/iOS/TextFieldExtensions.cs b/src/Core/src/Platform/iOS/TextFieldExtensions.cs index c4ae91a373df..5969e2b252ff 100644 --- a/src/Core/src/Platform/iOS/TextFieldExtensions.cs +++ b/src/Core/src/Platform/iOS/TextFieldExtensions.cs @@ -49,7 +49,7 @@ public static void UpdateIsTextPredictionEnabled(this UITextField textField, IEn public static void UpdateMaxLength(this UITextField textField, IEntry entry) { var newText = textField.AttributedText.TrimToMaxLength(entry.MaxLength); - if (textField.AttributedText != newText) + if (newText != null && textField.AttributedText != newText) textField.AttributedText = newText; } diff --git a/src/Core/src/Platform/iOS/TextViewExtensions.cs b/src/Core/src/Platform/iOS/TextViewExtensions.cs index 952d56b14e10..9ed0b0f65926 100644 --- a/src/Core/src/Platform/iOS/TextViewExtensions.cs +++ b/src/Core/src/Platform/iOS/TextViewExtensions.cs @@ -26,7 +26,7 @@ public static void UpdateCharacterSpacing(this UITextView textView, ITextStyle t public static void UpdateMaxLength(this UITextView textView, IEditor editor) { var newText = textView.AttributedText.TrimToMaxLength(editor.MaxLength); - if (textView.AttributedText != newText) + if (newText != null && textView.AttributedText != newText) textView.AttributedText = newText; } From aadd73c986df442378fff1a14332e1148a02edcc Mon Sep 17 00:00:00 2001 From: Matthew Leibowitz Date: Wed, 7 Apr 2021 05:53:20 +0200 Subject: [PATCH 42/48] Re-apply the formatting --- src/Core/src/Platform/iOS/DatePickerExtensions.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Core/src/Platform/iOS/DatePickerExtensions.cs b/src/Core/src/Platform/iOS/DatePickerExtensions.cs index 27996d70a138..a2067821525d 100644 --- a/src/Core/src/Platform/iOS/DatePickerExtensions.cs +++ b/src/Core/src/Platform/iOS/DatePickerExtensions.cs @@ -25,6 +25,8 @@ public static void UpdateDate(this MauiDatePicker nativeDatePicker, IDatePicker picker.SetDate(datePicker.Date.ToNSDate(), false); nativeDatePicker.Text = datePicker.Date.ToString(datePicker.Format); + + nativeDatePicker.UpdateCharacterSpacing(datePicker); } public static void UpdateMinimumDate(this MauiDatePicker nativeDatePicker, IDatePicker datePicker) From c09e85ad0ecd88b4b5e5030cfedceec62a4fedff Mon Sep 17 00:00:00 2001 From: Matthew Leibowitz Date: Wed, 7 Apr 2021 05:54:48 +0200 Subject: [PATCH 43/48] Test the crashes --- src/Controls/samples/Controls.Sample/Pages/MainPage.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Controls/samples/Controls.Sample/Pages/MainPage.cs b/src/Controls/samples/Controls.Sample/Pages/MainPage.cs index c264481317c4..986126b0803f 100644 --- a/src/Controls/samples/Controls.Sample/Pages/MainPage.cs +++ b/src/Controls/samples/Controls.Sample/Pages/MainPage.cs @@ -138,7 +138,7 @@ void SetupMauiLayout() }; verticalStack.Add(entry); - verticalStack.Add(new Entry { Text = "Entry", TextColor = Color.DarkRed, FontFamily = "Dokdo" }); + verticalStack.Add(new Entry { Text = "Entry", TextColor = Color.DarkRed, FontFamily = "Dokdo", MaxLength = -1 }); verticalStack.Add(new Entry { IsPassword = true, TextColor = Color.Black }); verticalStack.Add(new Entry { IsTextPredictionEnabled = false }); verticalStack.Add(new Entry { Placeholder = "This should be placeholder text" }); From 330f36c460dc3df1a17850ef75f0c7385a46c1ed Mon Sep 17 00:00:00 2001 From: Matthew Leibowitz Date: Wed, 7 Apr 2021 06:38:52 +0200 Subject: [PATCH 44/48] iOS is like Superman It can do amazing things, sometimes... And that little green rock... Apply the formatting after every change Fire the text changed event when the text changes, but not when formatting changes --- .../src/Handlers/Button/ButtonHandler.iOS.cs | 11 +++++++++- .../SearchBar/SearchBarHandler.iOS.cs | 13 ++++++++++++ src/Core/src/Platform/iOS/MauiTextField.cs | 21 ++++++++++++++++++- 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/src/Core/src/Handlers/Button/ButtonHandler.iOS.cs b/src/Core/src/Handlers/Button/ButtonHandler.iOS.cs index 8f273c0f7553..191b62f84a4d 100644 --- a/src/Core/src/Handlers/Button/ButtonHandler.iOS.cs +++ b/src/Core/src/Handlers/Button/ButtonHandler.iOS.cs @@ -48,6 +48,9 @@ protected override void SetupDefaults(UIButton nativeView) public static void MapText(ButtonHandler handler, IButton button) { handler.NativeView?.UpdateText(button); + + // Any text update requires that we update any attributed string formatting + MapFormatting(handler, button); } public static void MapTextColor(ButtonHandler handler, IButton button) @@ -57,7 +60,7 @@ public static void MapTextColor(ButtonHandler handler, IButton button) public static void MapCharacterSpacing(ButtonHandler handler, IButton button) { - handler.NativeView?.UpdateCharacterSpacing(button); + MapFormatting(handler, button); } public static void MapPadding(ButtonHandler handler, IButton button) @@ -74,6 +77,12 @@ public static void MapFont(ButtonHandler handler, IButton button) handler.NativeView?.UpdateFont(button, fontManager); } + public static void MapFormatting(ButtonHandler handler, IButton button) + { + // Update all of the attributed text formatting properties + handler.NativeView?.UpdateCharacterSpacing(button); + } + void SetControlPropertiesFromProxy() { if (NativeView == null) diff --git a/src/Core/src/Handlers/SearchBar/SearchBarHandler.iOS.cs b/src/Core/src/Handlers/SearchBar/SearchBarHandler.iOS.cs index d25359c225bb..f887533b4841 100644 --- a/src/Core/src/Handlers/SearchBar/SearchBarHandler.iOS.cs +++ b/src/Core/src/Handlers/SearchBar/SearchBarHandler.iOS.cs @@ -22,6 +22,9 @@ protected override UISearchBar CreateNativeView() public static void MapText(SearchBarHandler handler, ISearchBar searchBar) { handler.NativeView?.UpdateText(searchBar); + + // Any text update requires that we update any attributed string formatting + MapFormatting(handler, searchBar); } public static void MapPlaceholder(SearchBarHandler handler, ISearchBar searchBar) @@ -48,6 +51,16 @@ public static void MapCharacterSpacing(SearchBarHandler handler, ISearchBar sear handler.QueryEditor?.UpdateCharacterSpacing(searchBar); } + public static void MapFormatting(SearchBarHandler handler, ISearchBar searchBar) + { + // Update all of the attributed text formatting properties + handler.QueryEditor?.UpdateCharacterSpacing(searchBar); + + // Setting any of those may have removed text alignment settings, + // so we need to make sure those are applied, too + handler.QueryEditor?.UpdateHorizontalTextAlignment(searchBar); + } + [MissingMapper] public static void MapTextColor(IViewHandler handler, ISearchBar searchBar) { } diff --git a/src/Core/src/Platform/iOS/MauiTextField.cs b/src/Core/src/Platform/iOS/MauiTextField.cs index 265d942ee2f3..902e6b75e4b2 100644 --- a/src/Core/src/Platform/iOS/MauiTextField.cs +++ b/src/Core/src/Platform/iOS/MauiTextField.cs @@ -1,5 +1,6 @@ using System; using CoreGraphics; +using Foundation; using UIKit; namespace Microsoft.Maui.Platform.iOS @@ -20,8 +21,26 @@ public override string? Text get => base.Text; set { + var old = base.Text; + base.Text = value; - TextPropertySet?.Invoke(this, EventArgs.Empty); + + if (old != value) + TextPropertySet?.Invoke(this, EventArgs.Empty); + } + } + + public override NSAttributedString? AttributedText + { + get => base.AttributedText; + set + { + var old = base.AttributedText; + + base.AttributedText = value; + + if (old?.Value != value?.Value) + TextPropertySet?.Invoke(this, EventArgs.Empty); } } From 2aaecfb09877af8c5b573266e7ba826fa33f4901 Mon Sep 17 00:00:00 2001 From: Matthew Leibowitz Date: Wed, 7 Apr 2021 06:43:38 +0200 Subject: [PATCH 45/48] No need to reset everything --- src/Core/src/Handlers/Button/ButtonHandler.iOS.cs | 2 +- src/Core/src/Handlers/Label/LabelHandler.iOS.cs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Core/src/Handlers/Button/ButtonHandler.iOS.cs b/src/Core/src/Handlers/Button/ButtonHandler.iOS.cs index 191b62f84a4d..422cc82833c1 100644 --- a/src/Core/src/Handlers/Button/ButtonHandler.iOS.cs +++ b/src/Core/src/Handlers/Button/ButtonHandler.iOS.cs @@ -60,7 +60,7 @@ public static void MapTextColor(ButtonHandler handler, IButton button) public static void MapCharacterSpacing(ButtonHandler handler, IButton button) { - MapFormatting(handler, button); + handler.NativeView?.UpdateCharacterSpacing(button); } public static void MapPadding(ButtonHandler handler, IButton button) diff --git a/src/Core/src/Handlers/Label/LabelHandler.iOS.cs b/src/Core/src/Handlers/Label/LabelHandler.iOS.cs index b4a21b9fb71d..a6f15863908e 100644 --- a/src/Core/src/Handlers/Label/LabelHandler.iOS.cs +++ b/src/Core/src/Handlers/Label/LabelHandler.iOS.cs @@ -23,7 +23,7 @@ public static void MapTextColor(LabelHandler handler, ILabel label) public static void MapCharacterSpacing(LabelHandler handler, ILabel label) { - MapFormatting(handler, label); + handler.NativeView?.UpdateCharacterSpacing(label); } public static void MapHorizontalTextAlignment(LabelHandler handler, ILabel label) @@ -48,7 +48,7 @@ public static void MapPadding(LabelHandler handler, ILabel label) public static void MapTextDecorations(LabelHandler handler, ILabel label) { - MapFormatting(handler, label); + handler.NativeView?.UpdateTextDecorations(label); } public static void MapFont(LabelHandler handler, ILabel label) @@ -62,7 +62,7 @@ public static void MapFont(LabelHandler handler, ILabel label) public static void MapLineHeight(LabelHandler handler, ILabel label) { - MapFormatting(handler, label); + handler.NativeView?.UpdateLineHeight(label); } public static void MapFormatting(LabelHandler handler, ILabel label) From c3385ba6e8247ca57441987345102481c77585a7 Mon Sep 17 00:00:00 2001 From: Matthew Leibowitz Date: Wed, 7 Apr 2021 19:09:48 +0200 Subject: [PATCH 46/48] Fix tests for Android --- .../DeviceTests/Data/KeyboardClassData.cs | 126 ------------------ .../Handlers/Entry/EntryHandlerTests.cs | 88 ++++++++++-- .../Handlers/Entry/EntryHandlerTests.iOS.cs | 3 +- 3 files changed, 76 insertions(+), 141 deletions(-) delete mode 100644 src/Core/tests/DeviceTests/Data/KeyboardClassData.cs diff --git a/src/Core/tests/DeviceTests/Data/KeyboardClassData.cs b/src/Core/tests/DeviceTests/Data/KeyboardClassData.cs deleted file mode 100644 index 756b35a5a199..000000000000 --- a/src/Core/tests/DeviceTests/Data/KeyboardClassData.cs +++ /dev/null @@ -1,126 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Text; - -namespace Microsoft.Maui.Core.DeviceTests.Data -{ - public class NumericKeyboardClassData : IEnumerable - { - public IEnumerator GetEnumerator() - { - yield return new object[] { Keyboard.Numeric, true }; - yield return new object[] { Keyboard.Default, false }; - yield return new object[] { Keyboard.Chat, false }; - yield return new object[] { Keyboard.Email, false }; - yield return new object[] { Keyboard.Plain, false }; - yield return new object[] { Keyboard.Telephone, false }; - yield return new object[] { Keyboard.Text, false }; - yield return new object[] { Keyboard.Url, false }; - } - - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - } - - public class ChatKeyboardClassData : IEnumerable - { - public IEnumerator GetEnumerator() - { - yield return new object[] { Keyboard.Chat, true }; - yield return new object[] { Keyboard.Default, false }; - yield return new object[] { Keyboard.Numeric, false }; - yield return new object[] { Keyboard.Email, false }; - yield return new object[] { Keyboard.Plain, false }; - yield return new object[] { Keyboard.Telephone, false }; - yield return new object[] { Keyboard.Text, false }; - yield return new object[] { Keyboard.Url, false }; - } - - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - } - - public class EmailKeyboardClassData : IEnumerable - { - public IEnumerator GetEnumerator() - { - yield return new object[] { Keyboard.Email, true }; - yield return new object[] { Keyboard.Default, false }; - yield return new object[] { Keyboard.Numeric, false }; - yield return new object[] { Keyboard.Chat, false }; - yield return new object[] { Keyboard.Plain, false }; - yield return new object[] { Keyboard.Telephone, false }; - yield return new object[] { Keyboard.Text, false }; - yield return new object[] { Keyboard.Url, false }; - } - - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - } - - public class PlainKeyboardClassData : IEnumerable - { - public IEnumerator GetEnumerator() - { - yield return new object[] { Keyboard.Plain, true }; - yield return new object[] { Keyboard.Default, false }; - yield return new object[] { Keyboard.Numeric, false }; - yield return new object[] { Keyboard.Chat, false }; - yield return new object[] { Keyboard.Email, false }; - yield return new object[] { Keyboard.Telephone, false }; - yield return new object[] { Keyboard.Text, false }; - yield return new object[] { Keyboard.Url, false }; - } - - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - } - - public class TelephoneKeyboardClassData : IEnumerable - { - public IEnumerator GetEnumerator() - { - yield return new object[] { Keyboard.Telephone, true }; - yield return new object[] { Keyboard.Default, false }; - yield return new object[] { Keyboard.Numeric, false }; - yield return new object[] { Keyboard.Chat, false }; - yield return new object[] { Keyboard.Email, false }; - yield return new object[] { Keyboard.Plain, false }; - yield return new object[] { Keyboard.Text, false }; - yield return new object[] { Keyboard.Url, false }; - } - - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - } - - public class TextKeyboardClassData : IEnumerable - { - public IEnumerator GetEnumerator() - { - yield return new object[] { Keyboard.Text, true }; - yield return new object[] { Keyboard.Default, false }; - yield return new object[] { Keyboard.Numeric, false }; - yield return new object[] { Keyboard.Chat, false }; - yield return new object[] { Keyboard.Email, false }; - yield return new object[] { Keyboard.Plain, false }; - yield return new object[] { Keyboard.Telephone, false }; - yield return new object[] { Keyboard.Url, false }; - } - - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - } - - public class UrlKeyboardClassData : IEnumerable - { - public IEnumerator GetEnumerator() - { - yield return new object[] { Keyboard.Url, true }; - yield return new object[] { Keyboard.Default, false }; - yield return new object[] { Keyboard.Numeric, false }; - yield return new object[] { Keyboard.Chat, false }; - yield return new object[] { Keyboard.Email, false }; - yield return new object[] { Keyboard.Plain, false }; - yield return new object[] { Keyboard.Telephone, false }; - yield return new object[] { Keyboard.Text, false }; - } - - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - } -} diff --git a/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.cs b/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.cs index 32625c4f9966..9df65607cba5 100644 --- a/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.cs +++ b/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.cs @@ -1,9 +1,7 @@ using System.Threading.Tasks; using Microsoft.Maui.DeviceTests.Stubs; using Microsoft.Maui.Handlers; -using Microsoft.Maui.Core.DeviceTests.Data; using Xunit; -using Xunit.Extensions; namespace Microsoft.Maui.DeviceTests { @@ -255,54 +253,116 @@ public async Task TextChangedEventsFireCorrectly(string initialText, string newT } [Theory(DisplayName = "Validates Numeric Keyboard")] - [ClassData(typeof(NumericKeyboardClassData))] - public async Task ValidateNumericKeyboard(Keyboard keyboard, bool expected) + [InlineData(nameof(Keyboard.Chat), false)] + [InlineData(nameof(Keyboard.Default), false)] + [InlineData(nameof(Keyboard.Email), false)] + [InlineData(nameof(Keyboard.Numeric), true)] + [InlineData(nameof(Keyboard.Plain), false)] + [InlineData(nameof(Keyboard.Telephone), false)] + [InlineData(nameof(Keyboard.Text), false)] + [InlineData(nameof(Keyboard.Url), false)] + public async Task ValidateNumericKeyboard(string keyboardName, bool expected) { + var keyboard = (Keyboard)typeof(Keyboard).GetProperty(keyboardName).GetValue(null); + var entryStub = new EntryStub() { Keyboard = keyboard }; await ValidatePropertyInitValue(entryStub, () => expected, GetNativeIsNumericKeyboard, expected); } [Theory(DisplayName = "Validates Email Keyboard")] - [ClassData(typeof(EmailKeyboardClassData))] - public async Task ValidateEmailKeyboard(Keyboard keyboard, bool expected) + [InlineData(nameof(Keyboard.Chat), false)] + [InlineData(nameof(Keyboard.Default), false)] + [InlineData(nameof(Keyboard.Email), true)] + [InlineData(nameof(Keyboard.Numeric), false)] + [InlineData(nameof(Keyboard.Plain), false)] + [InlineData(nameof(Keyboard.Telephone), false)] + [InlineData(nameof(Keyboard.Text), false)] + [InlineData(nameof(Keyboard.Url), false)] + public async Task ValidateEmailKeyboard(string keyboardName, bool expected) { + var keyboard = (Keyboard)typeof(Keyboard).GetProperty(keyboardName).GetValue(null); + var entryStub = new EntryStub() { Keyboard = keyboard }; await ValidatePropertyInitValue(entryStub, () => expected, GetNativeIsEmailKeyboard, expected); } [Theory(DisplayName = "Validates Telephone Keyboard")] - [ClassData(typeof(TelephoneKeyboardClassData))] - public async Task ValidateTelephoneKeyboard(Keyboard keyboard, bool expected) + [InlineData(nameof(Keyboard.Chat), false)] + [InlineData(nameof(Keyboard.Default), false)] + [InlineData(nameof(Keyboard.Email), false)] + [InlineData(nameof(Keyboard.Numeric), false)] + [InlineData(nameof(Keyboard.Plain), false)] + [InlineData(nameof(Keyboard.Telephone), true)] + [InlineData(nameof(Keyboard.Text), false)] + [InlineData(nameof(Keyboard.Url), false)] + public async Task ValidateTelephoneKeyboard(string keyboardName, bool expected) { + var keyboard = (Keyboard)typeof(Keyboard).GetProperty(keyboardName).GetValue(null); + var entryStub = new EntryStub() { Keyboard = keyboard }; await ValidatePropertyInitValue(entryStub, () => expected, GetNativeIsTelephoneKeyboard, expected); } [Theory(DisplayName = "Validates Url Keyboard")] - [ClassData(typeof(UrlKeyboardClassData))] - public async Task ValidateUrlKeyboard(Keyboard keyboard, bool expected) + [InlineData(nameof(Keyboard.Chat), false)] + [InlineData(nameof(Keyboard.Default), false)] + [InlineData(nameof(Keyboard.Email), false)] + [InlineData(nameof(Keyboard.Numeric), false)] + [InlineData(nameof(Keyboard.Plain), false)] + [InlineData(nameof(Keyboard.Telephone), false)] + [InlineData(nameof(Keyboard.Text), false)] + [InlineData(nameof(Keyboard.Url), true)] + public async Task ValidateUrlKeyboard(string keyboardName, bool expected) { + var keyboard = (Keyboard)typeof(Keyboard).GetProperty(keyboardName).GetValue(null); + var entryStub = new EntryStub() { Keyboard = keyboard }; await ValidatePropertyInitValue(entryStub, () => expected, GetNativeIsUrlKeyboard, expected); } [Theory(DisplayName = "Validates Text Keyboard")] - [ClassData(typeof(TextKeyboardClassData))] - public async Task ValidateTextKeyboard(Keyboard keyboard, bool expected) +#if __ANDROID__ + [InlineData(nameof(Keyboard.Chat), true)] +#else + [InlineData(nameof(Keyboard.Chat), false)] +#endif + [InlineData(nameof(Keyboard.Default), false)] + [InlineData(nameof(Keyboard.Email), false)] + [InlineData(nameof(Keyboard.Numeric), false)] + [InlineData(nameof(Keyboard.Plain), false)] + [InlineData(nameof(Keyboard.Telephone), false)] + [InlineData(nameof(Keyboard.Text), true)] + [InlineData(nameof(Keyboard.Url), false)] + public async Task ValidateTextKeyboard(string keyboardName, bool expected) { + var keyboard = (Keyboard)typeof(Keyboard).GetProperty(keyboardName).GetValue(null); + var entryStub = new EntryStub() { Keyboard = keyboard }; await ValidatePropertyInitValue(entryStub, () => expected, GetNativeIsTextKeyboard, expected); } [Theory(DisplayName = "Validates Chat Keyboard")] - [ClassData(typeof(ChatKeyboardClassData))] - public async Task ValidateChatKeyboard(Keyboard keyboard, bool expected) + [InlineData(nameof(Keyboard.Chat), true)] + [InlineData(nameof(Keyboard.Default), false)] + [InlineData(nameof(Keyboard.Email), false)] + [InlineData(nameof(Keyboard.Numeric), false)] + [InlineData(nameof(Keyboard.Plain), false)] + [InlineData(nameof(Keyboard.Telephone), false)] +#if __ANDROID__ + [InlineData(nameof(Keyboard.Text), true)] +#else + [InlineData(nameof(Keyboard.Text), false)] +#endif + [InlineData(nameof(Keyboard.Url), false)] + public async Task ValidateChatKeyboard(string keyboardName, bool expected) { + var keyboard = (Keyboard)typeof(Keyboard).GetProperty(keyboardName).GetValue(null); + var entryStub = new EntryStub() { Keyboard = keyboard }; await ValidatePropertyInitValue(entryStub, () => expected, GetNativeIsChatKeyboard, expected); diff --git a/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.iOS.cs b/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.iOS.cs index 2324ae2739e3..20948f75b774 100644 --- a/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.iOS.cs +++ b/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.iOS.cs @@ -166,7 +166,8 @@ bool GetNativeIsChatKeyboard(EntryHandler entryHandler) var nativeEntry = GetNativeEntry(entryHandler); return nativeEntry.AutocapitalizationType == UITextAutocapitalizationType.Sentences && - nativeEntry.AutocorrectionType == UITextAutocorrectionType.Yes; + nativeEntry.AutocorrectionType == UITextAutocorrectionType.Yes && + nativeEntry.SpellCheckingType == UITextSpellCheckingType.No; } double GetNativeUnscaledFontSize(EntryHandler entryHandler) => From 4232070a4233209b65cd8c35858826816c29a41c Mon Sep 17 00:00:00 2001 From: Matthew Leibowitz Date: Wed, 7 Apr 2021 19:33:40 +0200 Subject: [PATCH 47/48] Fix iOS tests --- src/Core/src/Platform/iOS/TextFieldExtensions.cs | 4 ++++ src/Core/tests/DeviceTests/Stubs/EditorStub.cs | 2 +- src/Core/tests/DeviceTests/Stubs/EntryStub.cs | 2 +- src/Core/tests/DeviceTests/Stubs/SearchBarStub.cs | 2 +- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Core/src/Platform/iOS/TextFieldExtensions.cs b/src/Core/src/Platform/iOS/TextFieldExtensions.cs index 52299a69c5e9..ee936d3d9ba5 100644 --- a/src/Core/src/Platform/iOS/TextFieldExtensions.cs +++ b/src/Core/src/Platform/iOS/TextFieldExtensions.cs @@ -86,6 +86,10 @@ public static void UpdateKeyboard(this UITextField textField, IEntry entry) var keyboard = entry.Keyboard; textField.ApplyKeyboard(keyboard); + + if (keyboard is not CustomKeyboard) + textField.UpdateIsTextPredictionEnabled(entry); + textField.ReloadInputViews(); } diff --git a/src/Core/tests/DeviceTests/Stubs/EditorStub.cs b/src/Core/tests/DeviceTests/Stubs/EditorStub.cs index 49a1b5968f03..5ee389f1271b 100644 --- a/src/Core/tests/DeviceTests/Stubs/EditorStub.cs +++ b/src/Core/tests/DeviceTests/Stubs/EditorStub.cs @@ -26,7 +26,7 @@ public string Text public int MaxLength { get; set; } = int.MaxValue; - public bool IsTextPredictionEnabled { get; set; } + public bool IsTextPredictionEnabled { get; set; } = true; public Keyboard Keyboard { get; set; } diff --git a/src/Core/tests/DeviceTests/Stubs/EntryStub.cs b/src/Core/tests/DeviceTests/Stubs/EntryStub.cs index baf4e08c632c..79d8c42b8291 100644 --- a/src/Core/tests/DeviceTests/Stubs/EntryStub.cs +++ b/src/Core/tests/DeviceTests/Stubs/EntryStub.cs @@ -18,7 +18,7 @@ public string Text public bool IsPassword { get; set; } - public bool IsTextPredictionEnabled { get; set; } + public bool IsTextPredictionEnabled { get; set; } = true; public string Placeholder { get; set; } diff --git a/src/Core/tests/DeviceTests/Stubs/SearchBarStub.cs b/src/Core/tests/DeviceTests/Stubs/SearchBarStub.cs index 29a4e6ebdcad..bc96b252aa9f 100644 --- a/src/Core/tests/DeviceTests/Stubs/SearchBarStub.cs +++ b/src/Core/tests/DeviceTests/Stubs/SearchBarStub.cs @@ -16,7 +16,7 @@ public partial class SearchBarStub : StubBase, ISearchBar public TextAlignment HorizontalTextAlignment { get; set; } - public bool IsTextPredictionEnabled { get; set; } + public bool IsTextPredictionEnabled { get; set; } = true; public bool IsReadOnly { get; set; } From e46da290afb48a2449b7baad9be2c70ef324ca96 Mon Sep 17 00:00:00 2001 From: Matthew Leibowitz Date: Wed, 7 Apr 2021 19:58:24 +0200 Subject: [PATCH 48/48] Fix tests properly --- src/Core/src/Platform/Android/EditTextExtensions.cs | 2 +- .../Handlers/Entry/EntryHandlerTests.Android.cs | 5 ++--- .../tests/DeviceTests/Handlers/Entry/EntryHandlerTests.cs | 8 -------- 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/src/Core/src/Platform/Android/EditTextExtensions.cs b/src/Core/src/Platform/Android/EditTextExtensions.cs index 473fad13be6e..f07827611884 100644 --- a/src/Core/src/Platform/Android/EditTextExtensions.cs +++ b/src/Core/src/Platform/Android/EditTextExtensions.cs @@ -210,7 +210,7 @@ internal static void SetInputType(this AppCompatEditText editText, IEntry entry) var keyboard = entry.Keyboard; var nativeInputTypeToUpdate = keyboard.ToInputType(); - if (!(keyboard is CustomKeyboard)) + if (keyboard is not CustomKeyboard) { // TODO: IsSpellCheckEnabled handling must be here. diff --git a/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.Android.cs b/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.Android.cs index cb3f327a15ac..46940c3c1f41 100644 --- a/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.Android.cs +++ b/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.Android.cs @@ -141,10 +141,9 @@ bool GetNativeIsChatKeyboard(EntryHandler entryHandler) var editText = GetNativeEntry(entryHandler); var inputTypes = editText.InputType; - return (inputTypes.HasFlag(InputTypes.ClassText) && inputTypes.HasFlag(InputTypes.TextFlagCapSentences) && inputTypes.HasFlag(InputTypes.TextFlagNoSuggestions)); + return inputTypes.HasFlag(InputTypes.ClassText) && inputTypes.HasFlag(InputTypes.TextFlagCapSentences) && inputTypes.HasFlag(InputTypes.TextFlagNoSuggestions); } - bool GetNativeIsEmailKeyboard(EntryHandler entryHandler) { var editText = GetNativeEntry(entryHandler); @@ -174,7 +173,7 @@ bool GetNativeIsTextKeyboard(EntryHandler entryHandler) var editText = GetNativeEntry(entryHandler); var inputTypes = editText.InputType; - return inputTypes.HasFlag(InputTypes.ClassText) && inputTypes.HasFlag(InputTypes.TextFlagCapSentences); + return inputTypes.HasFlag(InputTypes.ClassText) && inputTypes.HasFlag(InputTypes.TextFlagCapSentences) && !inputTypes.HasFlag(InputTypes.TextFlagNoSuggestions); } double GetNativeUnscaledFontSize(EntryHandler entryHandler) diff --git a/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.cs b/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.cs index 9df65607cba5..88bc56bf6b79 100644 --- a/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.cs +++ b/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.cs @@ -325,11 +325,7 @@ public async Task ValidateUrlKeyboard(string keyboardName, bool expected) } [Theory(DisplayName = "Validates Text Keyboard")] -#if __ANDROID__ - [InlineData(nameof(Keyboard.Chat), true)] -#else [InlineData(nameof(Keyboard.Chat), false)] -#endif [InlineData(nameof(Keyboard.Default), false)] [InlineData(nameof(Keyboard.Email), false)] [InlineData(nameof(Keyboard.Numeric), false)] @@ -353,11 +349,7 @@ public async Task ValidateTextKeyboard(string keyboardName, bool expected) [InlineData(nameof(Keyboard.Numeric), false)] [InlineData(nameof(Keyboard.Plain), false)] [InlineData(nameof(Keyboard.Telephone), false)] -#if __ANDROID__ - [InlineData(nameof(Keyboard.Text), true)] -#else [InlineData(nameof(Keyboard.Text), false)] -#endif [InlineData(nameof(Keyboard.Url), false)] public async Task ValidateChatKeyboard(string keyboardName, bool expected) {