This repository was archived by the owner on May 1, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Fix up Android Accessibility behind a flag #14089
Merged
Merged
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
c2e99c0
Fix up Android Accessibility behind a flag
PureWeen 8aef4da
- automation id
PureWeen 18937af
- set back button to standard "Navigate Up"
PureWeen dce4f1a
- view compat
PureWeen 5575507
- add flag check
PureWeen 2a38298
- fix assigning of delegate
PureWeen bfb4d86
- add flag to forms appcompat activity
PureWeen 42f0595
- fix nav drawer
PureWeen File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
51 changes: 51 additions & 0 deletions
51
Xamarin.Forms.Platform.Android/AccessibilityDelegateAutomationId.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Text; | ||
using Android.Views.Accessibility; | ||
using AndroidX.AppCompat.Widget; | ||
using AndroidX.Core.View; | ||
using AndroidX.Core.View.Accessibiity; | ||
using Xamarin.Forms.Platform.Android.FastRenderers; | ||
|
||
namespace Xamarin.Forms.Platform.Android | ||
{ | ||
class AccessibilityDelegateAutomationId : AccessibilityDelegateCompat | ||
|
||
{ | ||
BindableObject _element; | ||
|
||
public AccessibilityDelegateAutomationId(BindableObject element) : base() | ||
{ | ||
_element = element; | ||
} | ||
|
||
|
||
public override void OnInitializeAccessibilityNodeInfo(global::Android.Views.View host, AccessibilityNodeInfoCompat info) | ||
{ | ||
base.OnInitializeAccessibilityNodeInfo(host, info); | ||
|
||
if (_element == null) | ||
return; | ||
|
||
if(Flags.IsAccessibilityExperimentalSet()) | ||
{ | ||
var value = AutomationPropertiesProvider.ConcatenateNameAndHelpText(_element); | ||
if (!string.IsNullOrWhiteSpace(value)) | ||
{ | ||
host.ContentDescription = value; | ||
} | ||
else if(host.ContentDescription == (_element as VisualElement)?.AutomationId) | ||
{ | ||
host.ContentDescription = null; | ||
} | ||
} | ||
} | ||
|
||
protected override void Dispose(bool disposing) | ||
{ | ||
_element = null; | ||
base.Dispose(disposing); | ||
} | ||
|
||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,9 @@ | ||
using System; | ||
using System.ComponentModel; | ||
using System.Runtime.InteropServices.WindowsRuntime; | ||
using Android.Views; | ||
using Android.Widget; | ||
using AndroidX.Core.View; | ||
using AView = Android.Views.View; | ||
|
||
namespace Xamarin.Forms.Platform.Android.FastRenderers | ||
|
@@ -30,52 +32,102 @@ internal static void GetDrawerAccessibilityResources(global::Android.Content.Con | |
resourceIdClose = context.Resources.GetIdentifier($"{automationIdParent}{s_defaultDrawerIdCloseSuffix}", "string", context.ApplicationInfo.PackageName); | ||
} | ||
|
||
static bool ShoudISetImportantForAccessibilityToNoIfAutomationIdIsSet(AView control, Element element) | ||
{ | ||
if (!Flags.IsAccessibilityExperimentalSet()) | ||
return false; | ||
|
||
internal static void SetAutomationId(AView control, Element element, string value = null) | ||
{ | ||
if (!control.IsAlive() || element == null) | ||
if (element == null) | ||
return false; | ||
|
||
if (String.IsNullOrWhiteSpace(element.AutomationId)) | ||
return false; | ||
|
||
// User has specifically said what they want | ||
if (AutomationProperties.GetIsInAccessibleTree(element) == true) | ||
return false; | ||
|
||
// User has explicitly set name and help text so we honor that | ||
if (!String.IsNullOrWhiteSpace(ConcatenateNameAndHelpText(element))) | ||
return false; | ||
|
||
if (element is Layout || | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This set of controls isn't going to change This is a bug that's very specific to XF 5 and won't surface in MAUI as we won't be using ContentDescription |
||
element is ItemsView || | ||
element is BoxView || | ||
element is ScrollView || | ||
element is TableView || | ||
element is WebView || | ||
element is Page || | ||
element is Shapes.Path || | ||
element is Frame || | ||
element is ListView || | ||
element is Image) | ||
{ | ||
return; | ||
return true; | ||
} | ||
|
||
SetAutomationId(control, element.AutomationId, value); | ||
return false; | ||
} | ||
|
||
internal static void SetAutomationId(AView control, string automationId, string value = null) | ||
internal static void SetAutomationId(AView control, Element element, string value = null) | ||
{ | ||
if (!control.IsAlive()) | ||
{ | ||
return; | ||
} | ||
|
||
automationId = value ?? automationId; | ||
string automationId = value ?? element?.AutomationId; | ||
if (!string.IsNullOrEmpty(automationId)) | ||
{ | ||
control.ContentDescription = automationId; | ||
|
||
if (ShoudISetImportantForAccessibilityToNoIfAutomationIdIsSet(control, element)) | ||
{ | ||
control.ImportantForAccessibility = ImportantForAccessibility.No; | ||
} | ||
else if (Flags.IsAccessibilityExperimentalSet() && control.GetAccessibilityDelegate() == null) | ||
ViewCompat.SetAccessibilityDelegate(control, new AccessibilityDelegateAutomationId(element)); | ||
|
||
} | ||
} | ||
|
||
internal static void SetBasicContentDescription( | ||
AView control, | ||
BindableObject bindableObject, | ||
Element element, | ||
string defaultContentDescription) | ||
{ | ||
if (bindableObject == null || control == null) | ||
if (element == null || control == null) | ||
return; | ||
|
||
string value = ConcatenateNameAndHelpText(bindableObject); | ||
string value = ConcatenateNameAndHelpText(element); | ||
|
||
var contentDescription = !string.IsNullOrWhiteSpace(value) ? value : defaultContentDescription; | ||
|
||
if (String.IsNullOrWhiteSpace(contentDescription) && bindableObject is Element element) | ||
if (String.IsNullOrWhiteSpace(contentDescription)) | ||
{ | ||
if(Flags.IsAccessibilityExperimentalSet()) | ||
{ | ||
SetAutomationId(control, element, element.AutomationId); | ||
return; | ||
} | ||
|
||
contentDescription = element.AutomationId; | ||
} | ||
|
||
if (Flags.IsAccessibilityExperimentalSet()) | ||
{ | ||
if (!AutomationProperties.GetIsInAccessibleTree(element).HasValue) | ||
{ | ||
control.ImportantForAccessibility = ImportantForAccessibility.Auto; | ||
} | ||
} | ||
|
||
control.ContentDescription = contentDescription; | ||
} | ||
|
||
internal static void SetContentDescription( | ||
AView control, | ||
BindableObject element, | ||
Element element, | ||
string defaultContentDescription, | ||
string defaultHint) | ||
{ | ||
|
@@ -96,12 +148,21 @@ internal static void SetFocusable(AView control, Element element, ref bool? defa | |
{ | ||
defaultFocusable = control.Focusable; | ||
} | ||
|
||
if (!defaultImportantForAccessibility.HasValue) | ||
{ | ||
defaultImportantForAccessibility = control.ImportantForAccessibility; | ||
// Auto is the default just use that | ||
if (Flags.IsAccessibilityExperimentalSet()) | ||
defaultImportantForAccessibility = ImportantForAccessibility.Auto; | ||
else | ||
defaultImportantForAccessibility = control.ImportantForAccessibility; | ||
} | ||
|
||
bool? isInAccessibleTree = (bool?)element.GetValue(AutomationProperties.IsInAccessibleTreeProperty); | ||
|
||
if (!isInAccessibleTree.HasValue && Flags.IsAccessibilityExperimentalSet()) | ||
return; | ||
|
||
control.Focusable = (bool)(isInAccessibleTree ?? defaultFocusable); | ||
control.ImportantForAccessibility = !isInAccessibleTree.HasValue ? (ImportantForAccessibility)defaultImportantForAccessibility : (bool)isInAccessibleTree ? ImportantForAccessibility.Yes : ImportantForAccessibility.No; | ||
} | ||
|
@@ -253,12 +314,16 @@ internal static void SetupDefaults(AView control, ref string defaultContentDescr | |
|
||
internal static void SetupDefaults(AView control, ref string defaultContentDescription, ref string defaultHint) | ||
{ | ||
if (defaultContentDescription == null) | ||
defaultContentDescription = control.ContentDescription; | ||
|
||
if (control is TextView textView && defaultHint == null) | ||
// Setting defaults for these values makes no sense | ||
if (!Flags.IsAccessibilityExperimentalSet()) | ||
{ | ||
defaultHint = textView.Hint; | ||
if (defaultContentDescription == null) | ||
defaultContentDescription = control.ContentDescription; | ||
|
||
if (control is TextView textView && defaultHint == null) | ||
{ | ||
defaultHint = textView.Hint; | ||
} | ||
} | ||
} | ||
|
||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,21 @@ | ||
using System.Linq; | ||
|
||
namespace Xamarin.Forms | ||
{ | ||
internal static class Flags | ||
{ | ||
internal const string UseLegacyRenderers = "UseLegacyRenderers"; | ||
|
||
internal const string AccessibilityExperimental = "Accessibility_Experimental"; | ||
|
||
public static bool IsFlagSet(string flagName) | ||
{ | ||
return Device.Flags != null && Device.Flags.Contains(flagName); | ||
} | ||
|
||
public static bool IsAccessibilityExperimentalSet() | ||
{ | ||
return IsFlagSet(AccessibilityExperimental); | ||
} | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we come up with a better, shorter name for this bool?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the name is clear about what it's doing then no
If it's not clear then yes
It's better to be verbose and clear with methods names then short/clever/and confusing