xamarin / Xamarin.Forms

Xamarin.Forms is no longer supported. Migrate your apps to .NET MAUI.
https://aka.ms/xamarin-upgrade
Other
5.62k stars 1.87k forks source link

UWP Entry.ReturnType overrides anything set by Entry.Keyboard #3820

Open nbevans opened 6 years ago

nbevans commented 6 years ago

Description

I wondered why my Keyboard.Numeric wasn't working on an Entry control. It seems when the ReturnType support was added to UWP that it wasn't done right. Because UpdateReturnType in the renderer will overwrite the InputScope which was just set by UpdateInputScope.

A possible way to fix this is to combine the UpdateReturnType and UpdateInputScope methods into one, since they both share the same underlying InputScope property on the Control.

See lines #231 and #301 in https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.UAP/EntryRenderer.cs

Steps to Reproduce

  1. Make an Entry control use Keyboard.Numeric (for example)
  2. Observe that Entry control erroneously offers full textual input if you bring up the onscreen keyboard in Win10.

Expected Behavior

The Entry control to respect the chosen Keyboard mode.

Actual Behavior

The Entry control doesn't respect the Keyboard mode but does respect the ReturnType mode.

Basic Information

nbevans commented 6 years ago

Hacky renderer workaround:

        private void InvokePrivateMethod(string methodName) {
            var m1 = typeof(EntryRenderer).GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance);
            m1.Invoke(this, new object[] { });
        }

        protected override void OnElementChanged(ElementChangedEventArgs<Entry> e) {
            base.OnElementChanged(e);

            // Hack to fix broken Control.InputScope / Element.Keyboard. Though this will break ReturnType.
            InvokePrivateMethod("UpdateInputScope");
        }
hartez commented 6 years ago

_3820 Repro.zip

WayaFlyfeather commented 5 years ago

(Please bear with me, as this is my first post here…)

So, if I get this correctly, Control.InputScope should really be set from the Entry.Keyboard value. Only in the case the entry.Keyboard.ToInputScope results in the Default keyboard is the ReturnType relevant?

In that case I would propose to remove the UpdateReturnType() method entirely, and instead add a check to the value returned from entry.Keyboard.ToinputScope in UpdateInputScope; if it's a default keyboard, it is instead set from ReturnType.ToInputScope().

Calls to UpdateReturnType() should then instead go to UpdateInputScope() (or be eliminated when superfluous).

If this sounds correct, I'd be happy to do it? (This would also be a first…)

WayaFlyfeather commented 5 years ago

In that case I would propose to remove the UpdateReturnType() method entirely, and instead add a check to the value returned from entry.Keyboard.ToinputScope in UpdateInputScope; if it's a default keyboard, it is instead set from ReturnType.ToInputScope().

Actually, on second thought, it's probably cleaner & simpler to just check if the Entry's Keyboard is Default; if it is use the InputScope determined by the Entry's ReturnType, otherwise determine from the Keyboard value. Like this in UpdateInputScope:

if (entry.Keyboard != Keyboard.Default)
    Control.InputScope = entry.Keyboard.ToInputScope();
else
    Control.InputScope = entry.ReturnType.ToInputScope(); 

Would still be happy to do it ;)