maui
maui copied to clipboard
MAUI Picker always open up in Android 8 and below
Description
Navigate from one page to another page, MAUI Picker always open up, with out selecting it on Android version 8 and below. Easily reproducible in Android Emulator.
Steps to Reproduce
- Clone the repo https://github.com/sujith2ss/test
- Build and run it on Android 8 device or emulator
- Click on the Next Button on App
- See the picker is opened already.
Link to public reproduction project repository
https://github.com/sujith2ss/test
Version with bug
7.0.49
Last version that worked well
Unknown/Other
Affected platforms
Android
Affected platform versions
Android 8 and below
Did you find any workaround?
No response
Relevant log output
No response
Demo video attached https://github.com/sujith2ss/test/blob/main/demo.mp4
https://github.com/dotnet/maui/assets/135240873/9ffdcd6a-8859-4d3c-9e03-9d9e81ea62f2
I am experiencing this with Android 12+, API versions 32/33. The only difference is that it happens with a TabView and occurs when the tab containing the picker becomes visible on an animation that switches between the tabs. I was able to fix it by removing a line that makes the tab item focused.
@gktval I didn't notice this issue in andorid version higher than 8. In android 8.0 or below if we try focus or unfocus the result are same. In the example code you can see only page navigation to another page, but the picker is getting opened automatically.
Also experiencing this on Android 13 API Version 33.
This occurs if the Picker is the first visible control on a page and the page regains focus from another page or a popup disappearing.
Yeah, there is some code in the PickerHandler.android.cs that says 'if focused, run click method'. I have no idea why this code is there. For most of the picker related handlers, I had to rewrite them from scratch because they were either not working properly or having memory leaks.
Just to add same here as @AndieH68 Android 13 API version 33.
Verified this on Visual Studio Enterprise 17.9.0 Preview 1(8.0.3). Repro on Android 8.0-API26, not repro on Android 13.0-API33, Windows 11 with below Project: Sample.zip
any updates?
I have this issue as well. Whenever navigating to a page with a picker on Android, the picker automatically opens. Is there a workaround other than building a custom control?
automatically
Yes there is a work around, I am away for the weekend but will post the work around I used and try to find the link for the fix so others can see it within here. Sorry but can not update until Monday.
Placing the picker in a scroll view fixed it for me for on initial page navigation, but not whenever I navigate back to the page. I'm interested to see your work around when you are able to share. Thanks!
P.S. I also tried calling unfocus() in OnAppearing and listing the items in the xaml instead of using ItemsSource, neither which fixed the issue.
I could not find the reference for how I came to this fix, as I did not create this somebody else figured this out and I have just used it. In your .xaml page add this as the top element so it is target by the bug as the first element.
<!-- element added her for .Net 8 fix to stop popups auto opening on refocus to page.-->
<Entry
x:Name="FakeEntry"
Margin="0,0,0,0"
HeightRequest="1"
MaximumHeightRequest="1"
TextColor="Black"
Placeholder=""/>
in your code behind. You need to add the following because the Android Underline is present on all entry elements so the invisible element will still have an underline, below will remove it.
// Complete below function is required to fix .Net 8 upgrade which breaks the picker class
// Had to add invisible text input element also and then hide it (not invisible) to stop page focus causing
// pickers to be opened all the time.
protected override void OnHandlerChanged()
{
base.OnHandlerChanged();
#if ANDROID
Android.Graphics.Drawables.GradientDrawable gd = new Android.Graphics.Drawables.GradientDrawable();
gd.SetStroke(0, Android.Graphics.Color.Transparent);
gd.SetColor(Android.Graphics.Color.Transparent);
// Invisible Text Entry box for .Net 8 fix for popups auto being called on return to page focus.
var view = FakeEntry.Handler.PlatformView as AndroidX.AppCompat.Widget.AppCompatEditText;
view.Background = null;
view.SetBackgroundColor(Android.Graphics.Color.Transparent);
view.SetPadding(0, 0, 0, 0);
view.SetCursorVisible(false);
view.SetBackground(gd);
#endif
}
All credit goes to somebody else.
I created a more generic fix. I have been testing it and it seems to work.
First, you have to create this handler:
public PickerHandlerFixAndroidFocus( ) {
_onFocusChangeMethod = typeof( PickerHandler ).GetMethod( "OnFocusChange", BindingFlags.Instance | BindingFlags.NonPublic );
_onClickMethod = typeof( PickerHandler ).GetMethod( "OnClick", BindingFlags.Instance | BindingFlags.NonPublic );
System.Diagnostics.Debug.Assert( _onFocusChangeMethod != null && _onClickMethod != null );
}
protected override void ConnectHandler( MauiPicker platformView ) {
base.ConnectHandler( platformView );
var focusChangeDelegate = ( System.EventHandler< Android.Views.View.FocusChangeEventArgs > )Delegate.CreateDelegate( typeof( System.EventHandler<Android.Views.View.FocusChangeEventArgs> ), this, _onFocusChangeMethod );
var clickDelegate = ( System.EventHandler )Delegate.CreateDelegate( typeof( System.EventHandler ), this, _onClickMethod );
platformView.Click -= clickDelegate;
platformView.FocusChange -= focusChangeDelegate;
platformView.Click += OnClick;
platformView.FocusChange += OnFocusChange;
}
void OnClick( object? sender, EventArgs e ) {
var diff = DateTime.Now - _lastFocusTimeStamp;
if( diff <= _timeToIgnoreClickAfterFocus ) {
_lastFocusTimeStamp = DateTime.MinValue;
return;
}
_onClickMethod!.Invoke( this, [ sender, e ] );
}
void OnFocusChange( object? sender, global::Android.Views.View.FocusChangeEventArgs e ) {
if( e.HasFocus ) {
_lastFocusTimeStamp = DateTime.Now;
return;
}
_lastFocusTimeStamp = DateTime.MinValue;
_onFocusChangeMethod!.Invoke( this, [ sender, e ] );
}
DateTime _lastFocusTimeStamp = DateTime.MinValue;
MethodInfo? _onClickMethod;
MethodInfo? _onFocusChangeMethod;
readonly TimeSpan _timeToIgnoreClickAfterFocus = TimeSpan.FromSeconds( 0.1f );
}
And then you just register it in your MauiProgram.cs (Android only):
builder.ConfigureMauiHandlers( cf => {
#if ANDROID
cf.AddHandler( typeof( Picker ), typeof( PickerHandlerFixAndroidFocus ) );
#endif
} )```
Also experiencing this on Android 13 API Version 33.
This occurs if the Picker is the first visible control on a page and the page regains focus from another page or a popup disappearing.
I had the same problem when closing a popup. The first control that is focusable would get the focus automatically triggering the OnFocus event.
In my case, I could solve this by adding a positive ZIndex value to the control I didn't want to have autofocus on. Now if I open and close the popup, the focus does not go back to control with the ZIndex.
Focus goes to whichever control has a lower zindex.
No idea why this would work or what the side effects are, but I'm putting this out there in case it can help someone else.
Also experiencing this on Android 13 API Version 33. This occurs if the Picker is the first visible control on a page and the page regains focus from another page or a popup disappearing.
I had the same problem when closing a popup. The first control that is focusable would get the focus automatically triggering the OnFocus event.
In my case, I could solve this by adding a positive ZIndex value to the control I didn't want to have autofocus on. Now if I open and close the popup, the focus does not go back to control with the ZIndex.
Focus goes to whichever control has a lower zindex.
No idea why this would work or what the side effects are, but I'm putting this out there in case it can help someone else.
Found this work does not work when controls are inside of a ScrollView
@RichardMarsh, did you try my fix? It is working great for me.
@RichardMarsh, did you try my fix? It is working great for me.
Going to give it a bash soon
@mchiz - many thanks, works like a charm!
@mchiz Thanks for your handler, it's working great
@RichardMarsh, did you try my fix? It is working great for me.
Not working for me. Any changes required?
This is still a problem and workarounds are very inconsistent in working.