I'm developing an app for blind or visually impaired people using Xamarin.Forms. All automation properties I need are set. This app uses BLE communication with a custom device. I can set the power level of the device, only if it is switched on (if the device is switched off, you can't set de power level). In my view I have two buttons to power up and down. So when I tap the power up button when the device is off, I show an alert saying that the device is off and is going to switch on (when "accept" button tapped). When the alert is gone, the screen reader reads app's title, and the button has lost the focus. Is it the normal behavior?
I thought that when the alert went away, the button would regain focus.
I use this method to show alerts:
public async Task ShowMessage(string message, string title, string buttonText, Action afterHideCallback) { await (Application.Current.MainPage as NavigationPage).CurrentPage.DisplayAlert(title, message, buttonText); afterHideCallback?.Invoke(); }
I'm testing with 2 smartphones with Android 6.0 and 9.0.
Do you know if it is possible to maintain the focus on the button?
Edit: It seems that the button maintains the focus in Android 9.0, but visually is not focused. So in Android 9.0 (with Samsung's Voice Assistant) it works the way I want it to. In Android 6.0, the button is visually focused, but I can't activate it with double tap. I don't know why, but it seems that in Android 9.0 doesn't work, I don't know why the previous test worked...
Do you want to achieve the result like this GIF?
If so, you can add the this.SendAccessibilityEvent((EventTypes)(int)WindowsChange.AccessibilityFocused);
like following custom renderer.
[assembly: Xamarin.Forms.ExportRenderer(typeof(Xamarin.Forms.ImageButton),typeof(App37.Droid.AndroidCustomView))] namespace App37.Droid { public class AndroidCustomView: ImageButtonRenderer { Context context; public AndroidCustomView(Context context) : base(context) { this.context = context; } protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.ImageButton> e) { base.OnElementChanged(e); Console.WriteLine("created from Android"); this.SetFocusable(ViewFocusability.Focusable); this.FocusableInTouchMode = true; MessagingCenter.Subscribe<object, string>(this, "ChangeVenue", (sender, msg) => { var res = this.RequestFocus(); this.SendAccessibilityEvent((EventTypes)(int)WindowsChange.AccessibilityFocused); if (this.HasFocus) { Toast.MakeText(context, "getFocus", ToastLength.Long).Show(); } }); } } }
You can check the android version when run the setFocusable(boolean focusable)
and setFocusable (int focusable)
the method. If the api blew the Android 8 use setFocusable (int focusable)
, other versions, use setFocusable(boolean focusable)
.
Answers
You can try to use
button.Focus();
to get the focus.When you click accept button in
DisplayAlert
, the alert will disappear, and executeafterHideCallback
, you can get the focus back bybutton.Focus();
like following code.Hello @LeonLu for your time.
I tried calling button.Focus() method, but it returns false. I used this code:
So it doesn't work
I found
button.Focus();
is an known issue for xamarin.forms, please see this threadhttps://github.com/xamarin/Xamarin.Forms/issues/5616
the Focus method is not functional on many mobile controls (e.g., Button, WebView) because there is no native option to put focus on such native objects. This issue was reprotected in github in 2019
However, I test with code to get the focus in custom renderer, it worked.
Here is running GIF.
Thank you @LeonLu
I know that in the first post I explained than a Button loses the focus, but I realized that it is an ImageButton. I tried modifying your code:
I did something wrong, because when I navigate to a page with a ImageButton, I get this exception at runtime:
Do you know what is wrong?? Thank in advance.
If you use
ImageButton
, you should change the value ofExportRenderer
fromXamarin.Forms.Button
toXamarin.Forms.ImageButton
like following assembly[assembly: Xamarin.Forms.ExportRenderer(typeof(Xamarin.Forms.ImageButton), typeof(MyApp.Droid.Renderers.AndroidCustomView))]
You are right, my mistake...
With this renderer, when screen reader is disabled
button.Focus()
method works, but when screen reader is enabled it doesn't...Do you want to achieve the result like this GIF?
If so, you can add the
this.SendAccessibilityEvent((EventTypes)(int)WindowsChange.AccessibilityFocused);
like following custom renderer.Hello @LeonLu thank you again.
Yes, this is what I want.
I checked it with a Samsung smartphone with Android 9. Even if the
ImageButton
isn't highlighted with the square, it is focused and the double tap works in it.But when I tried running it in LG device with Android 6, I get this exception in the
this.SetFocusable(ViewFocusability.Focusable);
line:I checked the documentation, and this method was added in API level 26 (Android 8), but there is another
setFocusable (boolean focusable)
overload added in API level 1. I guess this method won't do what I need, right?In worst case, I will recommend Android 8 devices, and do a version check before calling the method.
You can check the android version when run the
setFocusable(boolean focusable)
andsetFocusable (int focusable)
the method. If the api blew the Android 8 usesetFocusable (int focusable)
, other versions, usesetFocusable(boolean focusable)
.Thank you again @LeonLu , even if
setFocusable(boolean focusable)
doesn't work, it is enough for our purposes.You are welcome.