This repository has been 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
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Android] TalkBack now reads name and helptext on buttons. (#13244) f…
…ixes #5150 * Read name and helptext without disrupting automation id. * - Fix Merge * - remove if/defs * - fix Legacy Renderers * - fix UI Test * - fix invalid AutomationId with cell reuse * - fix Container so it's not read by accessibility Co-authored-by: Ry Lowry <rylowry@gmail.com>
- Loading branch information
Showing
12 changed files
with
336 additions
and
49 deletions.
There are no files selected for viewing
56 changes: 56 additions & 0 deletions
56
Xamarin.Forms.ControlGallery.Android/ContentDescriptionEffectRenderer.cs
This file contains 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,56 @@ | ||
using System.ComponentModel; | ||
using AViews = Android.Views; | ||
using Xamarin.Forms; | ||
using Xamarin.Forms.ControlGallery.Android; | ||
using Xamarin.Forms.Controls.Issues; | ||
using Xamarin.Forms.Platform.Android; | ||
using AndroidX.Core.View.Accessibiity; | ||
using AndroidX.Core.View; | ||
|
||
[assembly: ExportEffect(typeof(ContentDescriptionEffectRenderer), ContentDescriptionEffect.EffectName)] | ||
namespace Xamarin.Forms.ControlGallery.Android | ||
{ | ||
public class ContentDescriptionEffectRenderer : PlatformEffect | ||
{ | ||
protected override void OnAttached() | ||
{ | ||
} | ||
|
||
protected override void OnDetached() | ||
{ | ||
} | ||
|
||
protected override void OnElementPropertyChanged(PropertyChangedEventArgs args) | ||
{ | ||
System.Diagnostics.Debug.WriteLine("OnElementPropertyChanged" + args.PropertyName); | ||
|
||
var viewGroup = Control as AViews.ViewGroup; | ||
var nativeView = Control as AViews.View; | ||
|
||
if (nativeView != null && viewGroup != null && viewGroup.ChildCount > 0) | ||
{ | ||
nativeView = viewGroup.GetChildAt(0); | ||
} | ||
|
||
if (nativeView == null) | ||
{ | ||
return; | ||
} | ||
|
||
var info = AccessibilityNodeInfoCompat.Obtain(nativeView); | ||
ViewCompat.OnInitializeAccessibilityNodeInfo(nativeView, info); | ||
|
||
System.Diagnostics.Debug.WriteLine(info.ContentDescription); | ||
System.Diagnostics.Debug.WriteLine(nativeView.ContentDescription); | ||
|
||
Element.SetValue( | ||
ContentDescriptionEffectProperties.NameAndHelpTextProperty, | ||
info.ContentDescription); | ||
|
||
Element.SetValue( | ||
ContentDescriptionEffectProperties.ContentDescriptionProperty, | ||
nativeView.ContentDescription); | ||
} | ||
|
||
} | ||
} |
This file contains 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
146 changes: 146 additions & 0 deletions
146
Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue5150.cs
This file contains 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,146 @@ | ||
using System.ComponentModel; | ||
using Xamarin.Forms.CustomAttributes; | ||
using Xamarin.Forms.Internals; | ||
|
||
#if UITEST | ||
using CategoryAttribute = NUnit.Framework.CategoryAttribute; | ||
using Xamarin.Forms.Core.UITests; | ||
using Xamarin.UITest; | ||
using NUnit.Framework; | ||
#endif | ||
|
||
namespace Xamarin.Forms.Controls.Issues | ||
{ | ||
|
||
public static class ContentDescriptionEffectProperties | ||
{ | ||
public static readonly BindableProperty ContentDescriptionProperty = BindableProperty.CreateAttached( | ||
"ContentDescription", | ||
typeof(string), | ||
typeof(ContentDescriptionEffectProperties), | ||
null); | ||
|
||
public static readonly BindableProperty NameAndHelpTextProperty = BindableProperty.CreateAttached( | ||
"NameAndHelpText", | ||
typeof(string), | ||
typeof(ContentDescriptionEffectProperties), | ||
null); | ||
|
||
public static string GetContentDescription(BindableObject view) | ||
{ | ||
return (string)view.GetValue(ContentDescriptionProperty); | ||
} | ||
|
||
public static string GetNameAndHelpText(BindableObject view) | ||
{ | ||
return (string)view.GetValue(NameAndHelpTextProperty); | ||
} | ||
} | ||
|
||
public class ContentDescriptionEffect : RoutingEffect | ||
{ | ||
public const string EffectName = "ContentDescriptionEffect"; | ||
|
||
public ContentDescriptionEffect() : base($"{Effects.ResolutionGroupName}.{EffectName}") | ||
{ | ||
} | ||
} | ||
|
||
[Preserve(AllMembers = true)] | ||
[Issue(IssueTracker.Github, 5150, "AutomationProperties.Name, AutomationProperties.HelpText on Button not read by Android TalkBack", PlatformAffected.Android)] | ||
public class Issue5150 : TestContentPage // or TestMasterDetailPage, etc ... | ||
{ | ||
void AddView(StackLayout layout, View view, string labelPrefix, string automationId, string buttonName = null, string buttonHelp = null) | ||
{ | ||
var automationIdLabel = new Label(); | ||
automationIdLabel.Text = $"AutomationId = {automationId}"; | ||
automationIdLabel.AutomationId = $"{labelPrefix}-automationIdLabel"; | ||
|
||
var contentDescriptionLabel = new Label(); | ||
contentDescriptionLabel.AutomationId = $"{labelPrefix}-contentDescriptionLabel"; | ||
|
||
var nameAndHelpTextLabel = new Label(); | ||
nameAndHelpTextLabel.AutomationId = $"{labelPrefix}-nameAndHelpTextLabel"; | ||
|
||
view.AutomationId = automationId; | ||
view.Effects.Add(new ContentDescriptionEffect()); | ||
view.PropertyChanged += (object sender, PropertyChangedEventArgs e) => { | ||
if (e.PropertyName == ContentDescriptionEffectProperties.ContentDescriptionProperty.PropertyName) | ||
{ | ||
contentDescriptionLabel.Text = $"ContentDescription = {ContentDescriptionEffectProperties.GetContentDescription(view)}"; | ||
} | ||
if (e.PropertyName == ContentDescriptionEffectProperties.NameAndHelpTextProperty.PropertyName) | ||
{ | ||
nameAndHelpTextLabel.Text = $"Name + HelpText = {ContentDescriptionEffectProperties.GetNameAndHelpText(view)}"; | ||
} | ||
}; | ||
layout.Children.Add(view); | ||
layout.Children.Add(automationIdLabel); | ||
layout.Children.Add(contentDescriptionLabel); | ||
layout.Children.Add(nameAndHelpTextLabel); | ||
|
||
AutomationProperties.SetIsInAccessibleTree(view, true); | ||
AutomationProperties.SetName(view, buttonName); | ||
AutomationProperties.SetHelpText(view, buttonHelp); | ||
} | ||
|
||
void AddButton(StackLayout layout, string labelPrefix, string automationId, string buttonText, string buttonName = null, string buttonHelp = null) | ||
{ | ||
var button = new Button(); | ||
button.Text = buttonText; | ||
AddView(layout, button, labelPrefix, automationId, buttonName, buttonHelp); | ||
} | ||
|
||
protected override void Init() | ||
{ | ||
var scrollView = new ScrollView(); | ||
var layout = new StackLayout(); | ||
scrollView.Content = layout; | ||
|
||
layout.Children.Add(new Label | ||
{ | ||
Text = "On the Android platform, the 'Name + Help Text' " + | ||
"labels below each button should match the text read by " + | ||
"TalkBack." | ||
}); | ||
|
||
AddButton(layout, "button1prop", "button1", "Button 1", "Name 1"); | ||
AddButton(layout, "button2prop", "button2", "Button 2", buttonHelp: "Help 2."); | ||
AddButton(layout, "button3prop", "button3", "Button 3", "Name 3", "Help 3."); | ||
AddButton(layout, "button4prop", "button4", null , buttonHelp: "Help 4."); | ||
|
||
AddView(layout, new Switch(), "switch1prop", "switch1", "Switch 1 Name", "Switch Help 1."); | ||
|
||
var image = new Image(); | ||
image.Source = ImageSource.FromFile("coffee.png"); | ||
AddView(layout, image, "image1prop", "image1", "Coffee", "Get some coffee!"); | ||
|
||
Content = scrollView; | ||
} | ||
|
||
#if UITEST && __ANDROID__ | ||
void Verify(string labelPrefix, string automationId, string expectedNameAndHelpText) | ||
{ | ||
RunningApp.ScrollTo(automationId); | ||
RunningApp.WaitForElement(q => q.Marked(automationId)); | ||
RunningApp.ScrollTo($"{labelPrefix}-nameAndHelpTextLabel"); | ||
RunningApp.WaitForElement(q => q.Text($"Name + HelpText = {expectedNameAndHelpText}")); | ||
} | ||
|
||
[Test] | ||
[Category(UITestCategories.Button)] | ||
[Category(UITestCategories.Accessibility)] | ||
[Ignore("Automated Test not relevant until https://github.com/xamarin/Xamarin.Forms/issues/1529 is fixed")] | ||
public void Issue5150Test() | ||
{ | ||
Verify("button1prop", "button1", "Name 1"); | ||
Verify("button2prop", "button2", "Button 2. Help 2."); | ||
Verify("button3prop", "button3", "Name 3. Help 3."); | ||
Verify("button4prop", "button4", "Help 4."); | ||
Verify("switch1prop", "switch1", "Switch 1 Name. Switch Help 1."); | ||
Verify("image1prop", "image1", "Coffee. Get some coffee!"); | ||
} | ||
#endif | ||
} | ||
} |
This file contains 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 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 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 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.