Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using NUnit.Framework;
using UITest.Appium;
using UITest.Core;

#if TEST_FAILS_ON_ANDROID
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We will probably want to add some extra code to make sure this test still passes

Copy link
Contributor Author

@bhavanesh2001 bhavanesh2001 Jun 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although I think firing Focus/Unfocus events based on dialog show/dismiss is questionable, I wired up mappers for Focus() and Unfocus() calls to ensure they still work.

namespace Microsoft.Maui.TestCases.Tests.Issues
{
public class Issue2339 : _IssuesUITest
Expand All @@ -27,4 +27,5 @@ public void FocusAndUnFocusMultipleTimes()
App.WaitForElement("Picker UnFocused: 2");
}
}
}
}
#endif
20 changes: 0 additions & 20 deletions src/Core/src/Handlers/Picker/PickerHandler.Android.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,13 @@ protected override MauiPicker CreatePlatformView() =>

protected override void ConnectHandler(MauiPicker platformView)
{
platformView.FocusChange += OnFocusChange;
platformView.Click += OnClick;

base.ConnectHandler(platformView);
}

protected override void DisconnectHandler(MauiPicker platformView)
{
platformView.FocusChange -= OnFocusChange;
platformView.Click -= OnClick;

base.DisconnectHandler(platformView);
Expand Down Expand Up @@ -86,24 +84,6 @@ public static void MapVerticalTextAlignment(IPickerHandler handler, IPicker pick
handler.PlatformView?.UpdateVerticalAlignment(picker.VerticalTextAlignment);
}

void OnFocusChange(object? sender, global::Android.Views.View.FocusChangeEventArgs e)
{
if (PlatformView == null)
return;

if (e.HasFocus)
{
if (PlatformView.Clickable)
PlatformView.CallOnClick();
else
OnClick(PlatformView, EventArgs.Empty);
}
else if (_dialog != null)
{
_dialog.Hide();
_dialog = null;
}
}

void OnClick(object? sender, EventArgs e)
{
Expand Down
8 changes: 4 additions & 4 deletions src/Core/src/Platform/Android/MauiDatePicker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Android.Content;
using Android.Runtime;
using Android.Text;
using Android.Text.Method;
using Android.Util;
using Android.Views;
using AndroidX.AppCompat.Widget;
Expand Down Expand Up @@ -31,6 +32,8 @@ protected MauiDatePicker(IntPtr javaReference, JniHandleOwnership transfer) : ba
{
}

protected override IMovementMethod? DefaultMovementMethod => null;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we comment the three places we are doing this with why we are doing this?

Indicate that according to the docs this MovementMethod is purely related to moving the cursor inside the box but since the text is readonly we remove it to avoid cursor related keyboard navigation?


public Action? ShowPicker { get; set; }
public Action? HidePicker { get; set; }

Expand All @@ -44,10 +47,7 @@ void Initialize()
if (Background != null)
DrawableCompat.Wrap(Background);

Focusable = true;
FocusableInTouchMode = false;
Clickable = true;
InputType = InputTypes.Null;
PickerManager.Init(this);

SetOnClickListener(this);
}
Expand Down
16 changes: 3 additions & 13 deletions src/Core/src/Platform/Android/MauiPicker.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Android.Content;
using Android.Runtime;
using Android.Text.Method;
using Android.Views;
using AndroidX.AppCompat.Widget;
using AndroidX.Core.Graphics.Drawable;
Expand All @@ -9,25 +10,12 @@ namespace Microsoft.Maui.Platform
{
public class MauiPicker : MauiPickerBase
{
public bool ShowPopupOnFocus { get; set; }

public MauiPicker(Context context) : base(context)
{
PickerManager.Init(this);
}

public override bool OnTouchEvent(MotionEvent? e)
{
PickerManager.OnTouchEvent(this, e);
return base.OnTouchEvent(e); // Raises the OnClick event if focus is already received
}

protected override void OnFocusChanged(bool gainFocus, [GeneratedEnum] FocusSearchDirection direction, ARect? previouslyFocusedRect)
{
base.OnFocusChanged(gainFocus, direction, previouslyFocusedRect);
PickerManager.OnFocusChanged(gainFocus, this);
}

protected override void Dispose(bool disposing)
{
if (disposing)
Expand All @@ -44,5 +32,7 @@ public MauiPickerBase(Context context) : base(context)
if (Background != null)
DrawableCompat.Wrap(Background);
}

protected override IMovementMethod? DefaultMovementMethod => null;
}
}
8 changes: 4 additions & 4 deletions src/Core/src/Platform/Android/MauiTimePicker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Android.Content;
using Android.Runtime;
using Android.Text;
using Android.Text.Method;
using Android.Util;
using Android.Views;
using AndroidX.AppCompat.Widget;
Expand Down Expand Up @@ -31,6 +32,8 @@ protected MauiTimePicker(IntPtr javaReference, JniHandleOwnership transfer) : ba
{
}

protected override IMovementMethod? DefaultMovementMethod => null;

public Action? ShowPicker { get; set; }
public Action? HidePicker { get; set; }

Expand All @@ -44,10 +47,7 @@ void Initialize()
if (Background != null)
DrawableCompat.Wrap(Background);

Focusable = true;
FocusableInTouchMode = false;
Clickable = true;
InputType = InputTypes.Null;
PickerManager.Init(this);

SetOnClickListener(this);
}
Expand Down
50 changes: 5 additions & 45 deletions src/Core/src/Platform/Android/PickerManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,60 +11,20 @@ namespace Microsoft.Maui.Platform
{
internal static class PickerManager
{
readonly static HashSet<Keycode> AvailableKeys = new HashSet<Keycode>(new[] {
Keycode.Tab, Keycode.Forward, Keycode.DpadDown, Keycode.DpadLeft, Keycode.DpadRight, Keycode.DpadUp
});

public static void Init(EditText editText)
{
editText.Focusable = true;
editText.Clickable = true;
editText.InputType = InputTypes.Null;

editText.KeyPress += OnKeyPress;
}

public static void OnTouchEvent(EditText sender, MotionEvent? e)
{
if (e != null && e.Action == MotionEventActions.Up && !sender.IsFocused)
{
sender.RequestFocus();
}
}

public static void OnFocusChanged(bool gainFocus, EditText sender)
{
if (gainFocus)
sender.CallOnClick();
}
editText.FocusableInTouchMode = false;
editText.Clickable = true;

static void OnKeyPress(object? sender, AView.KeyEventArgs e)
{
//To prevent user from entering text when focus is received
e.Handled = true;
if (!AvailableKeys.Contains(e.KeyCode))
{
return;
}
(sender as AView)?.CallOnClick();
// InputType needs to be set before setting KeyListener
editText.InputType = InputTypes.Null;
editText.KeyListener = null;
}

public static void Dispose(EditText editText)
{
editText.KeyPress -= OnKeyPress;
editText.SetOnClickListener(null);
}

public static Java.Lang.ICharSequence GetTitle(Color titleColor, string title)
{
if (titleColor == null)
return new Java.Lang.String(title);

var spannableTitle = new SpannableString(title ?? string.Empty);
#pragma warning disable CA1416 // https://github.com/xamarin/xamarin-android/issues/6962
spannableTitle.SetSpan(new ForegroundColorSpan(titleColor.ToPlatform()), 0, spannableTitle.Length(), SpanTypes.ExclusiveExclusive);
#pragma warning restore CA1416
return spannableTitle;
}
}
}
7 changes: 7 additions & 0 deletions src/Core/src/PublicAPI/net-android/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
@@ -1 +1,8 @@
#nullable enable
*REMOVED*Microsoft.Maui.Platform.MauiPicker.ShowPopupOnFocus.get -> bool
*REMOVED*Microsoft.Maui.Platform.MauiPicker.ShowPopupOnFocus.set -> void
*REMOVED*override Microsoft.Maui.Platform.MauiPicker.OnFocusChanged(bool gainFocus, Android.Views.FocusSearchDirection direction, Android.Graphics.Rect? previouslyFocusedRect) -> void
*REMOVED*override Microsoft.Maui.Platform.MauiPicker.OnTouchEvent(Android.Views.MotionEvent? e) -> bool
override Microsoft.Maui.Platform.MauiDatePicker.DefaultMovementMethod.get -> Android.Text.Method.IMovementMethod?
override Microsoft.Maui.Platform.MauiPickerBase.DefaultMovementMethod.get -> Android.Text.Method.IMovementMethod?
override Microsoft.Maui.Platform.MauiTimePicker.DefaultMovementMethod.get -> Android.Text.Method.IMovementMethod?
Loading