Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
Expand Up @@ -577,7 +577,7 @@ void HandlePropertyChanged(object sender, PropertyChangedEventArgs e)
{
UpdateUseLargeTitles();
}
else if (e.PropertyName == NavigationPage.BackButtonTitleProperty.PropertyName || e.PropertyName == NavigationPage.TitleProperty.PropertyName)
else if (e.PropertyName == NavigationPage.BackButtonTitleProperty.PropertyName || e.PropertyName == NavigationPage.TitleProperty.PropertyName || e.PropertyName == NavigationPage.BackButtonAccessibilityLabelProperty.PropertyName)
{
var pack = (ParentingViewController)TopViewController;
pack?.UpdateTitleArea(pack.Child);
Expand Down Expand Up @@ -1637,7 +1637,7 @@ void HandleChildPropertyChanged(object sender, PropertyChangedEventArgs e)
else if (e.PropertyName == NavigationPage.TitleIconImageSourceProperty.PropertyName ||
e.PropertyName == NavigationPage.TitleViewProperty.PropertyName)
UpdateTitleArea(Child);
else if (e.PropertyName == NavigationPage.BackButtonTitleProperty.PropertyName)
else if (e.PropertyName == NavigationPage.BackButtonTitleProperty.PropertyName || e.PropertyName == NavigationPage.BackButtonAccessibilityLabelProperty.PropertyName)
UpdateBackButtonTitle(Child);
else if (e.PropertyName == NavigationPage.IconColorProperty.PropertyName)
UpdateIconColor();
Expand Down Expand Up @@ -1788,18 +1788,30 @@ internal void UpdateLeftBarButtonItem(Page pageBeingRemoved = null)

public bool NeedsTitleViewContainer(Page page) => NavigationPage.GetTitleIconImageSource(page) != null || NavigationPage.GetTitleView(page) != null;

internal void UpdateBackButtonTitle(Page page) => UpdateBackButtonTitle(page.Title, NavigationPage.GetBackButtonTitle(page));
internal void UpdateBackButtonTitle(Page page) => UpdateBackButtonTitle(page.Title, NavigationPage.GetBackButtonTitle(page), NavigationPage.GetBackButtonAccessibilityLabel(page));

internal void UpdateBackButtonTitle(string title, string backButtonTitle)
internal void UpdateBackButtonTitle(string title, string backButtonTitle, string backButtonAccessibilityLabel = null)
{
if (!string.IsNullOrWhiteSpace(title))
{
NavigationItem.Title = title;
}

if (backButtonTitle != null)
if (backButtonTitle is not null || !string.IsNullOrEmpty(backButtonAccessibilityLabel))
{
// adding a custom event handler to UIBarButtonItem for navigating back seems to be ignored.
NavigationItem.BackBarButtonItem = new UIBarButtonItem { Title = backButtonTitle, Style = UIBarButtonItemStyle.Plain };
var barButtonItem = new UIBarButtonItem { Style = UIBarButtonItemStyle.Plain };
barButtonItem.Title = backButtonTitle ?? title;
if (!string.IsNullOrEmpty(backButtonAccessibilityLabel))
{
barButtonItem.AccessibilityLabel = backButtonAccessibilityLabel;
}
NavigationItem.BackBarButtonItem = barButtonItem;
Comment thread
Vignesh-SF3580 marked this conversation as resolved.
}
else
{
NavigationItem.BackBarButtonItem = null;
}
}

internal void UpdateTitleArea(Page page)
Expand All @@ -1819,11 +1831,13 @@ internal void UpdateTitleArea(Page page)
if (!(OperatingSystem.IsIOSVersionAtLeast(11) || OperatingSystem.IsMacCatalystVersionAtLeast(11)) && !isBackButtonTextSet)
backButtonText = "";

string backButtonAccessibilityLabel = NavigationPage.GetBackButtonAccessibilityLabel(page);

_navigation.TryGetTarget(out NavigationRenderer n);

// First page and we have a flyout detail to contend with
UpdateLeftBarButtonItem();
UpdateBackButtonTitle(page.Title ?? n?.NavPage.Title, backButtonText);
UpdateBackButtonTitle(page.Title ?? n?.NavPage.Title, backButtonText, backButtonAccessibilityLabel);

//var hadTitleView = NavigationItem.TitleView != null;
ClearTitleViewContainer();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,10 @@ protected virtual void UpdateToolbarIconAccessibilityText(AToolbar toolbar, Shel
var backButtonHandler = Shell.GetEffectiveBackButtonBehavior(Page);
var image = GetFlyoutIcon(backButtonHandler, Page);
var text = backButtonHandler.GetPropertyIfSet(BackButtonBehavior.TextOverrideProperty, String.Empty);

var accessibilityLabel = backButtonHandler.GetPropertyIfSet<string>(
BackButtonBehavior.AccessibilityLabelProperty, null);

var automationId = image?.AutomationId ?? text;

//if AutomationId was specified the user wants to use UITests and interact with FlyoutIcon
Expand All @@ -573,6 +577,12 @@ protected virtual void UpdateToolbarIconAccessibilityText(AToolbar toolbar, Shel
else
toolbar.SetNavigationContentDescription(Resource.String.nav_app_bar_open_drawer_description);
}

// Custom accessibility label takes final priority over all other descriptions
if (!string.IsNullOrEmpty(accessibilityLabel))
{
toolbar.NavigationContentDescription = accessibilityLabel;
}
Comment thread
Vignesh-SF3580 marked this conversation as resolved.
}

protected virtual Task UpdateDrawerArrowFromBackButtonBehavior(Context context, AToolbar toolbar, DrawerLayout drawerLayout, BackButtonBehavior backButtonHandler)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -599,26 +599,46 @@ void UpdateLeftToolbarItems()

if (NavigationItem.LeftBarButtonItem != null)
{
var customAccessibilityLabel = behavior.GetPropertyIfSet<string?>(BackButtonBehavior.AccessibilityLabelProperty, null);
bool hasCustomLabel = !string.IsNullOrEmpty(customAccessibilityLabel);

if (String.IsNullOrWhiteSpace(image?.AutomationId))
{
if (IsRootPage || !backButtonVisible)
{
NavigationItem.LeftBarButtonItem.AccessibilityIdentifier = "OK";
NavigationItem.LeftBarButtonItem.AccessibilityLabel = "Menu";
NavigationItem.LeftBarButtonItem.AccessibilityLabel = hasCustomLabel ? customAccessibilityLabel : "Menu";
}
else
{
NavigationItem.LeftBarButtonItem.AccessibilityIdentifier = "Back";
if (hasCustomLabel)
{
NavigationItem.LeftBarButtonItem.AccessibilityLabel = customAccessibilityLabel;
}
else
{
NavigationItem.LeftBarButtonItem.AccessibilityLabel = null;
}
}
}
else
{
NavigationItem.LeftBarButtonItem.AccessibilityIdentifier = image.AutomationId;
if (hasCustomLabel)
{
NavigationItem.LeftBarButtonItem.AccessibilityLabel = customAccessibilityLabel;
}
}

if (image != null)
{
#pragma warning disable CS0618 // Type or member is obsolete
NavigationItem.LeftBarButtonItem.SetAccessibilityHint(image);
NavigationItem.LeftBarButtonItem.SetAccessibilityLabel(image);
if (!hasCustomLabel)
{
NavigationItem.LeftBarButtonItem.SetAccessibilityLabel(image);
}
#pragma warning restore CS0618 // Type or member is obsolete
}
}
Expand All @@ -637,6 +657,7 @@ void UpdateBackButtonTitle()

var behavior = BackButtonBehavior;
var text = behavior.GetPropertyIfSet<string?>(BackButtonBehavior.TextOverrideProperty, null);
var accessibilityLabel = behavior.GetPropertyIfSet<string?>(BackButtonBehavior.AccessibilityLabelProperty, null);

var navController = ViewController?.NavigationController;

Expand All @@ -653,13 +674,30 @@ void UpdateBackButtonTitle()
var previousNavItem = viewControllers[count - 2].NavigationItem;
if (previousNavItem != null)
{
if (text is not null)
if (text is not null || !string.IsNullOrEmpty(accessibilityLabel))
{
var barButtonItem = (previousNavItem.BackBarButtonItem ??= new UIBarButtonItem());
barButtonItem.Title = text;
if (text is not null)
{
barButtonItem.Title = text;
}
else if (barButtonItem.Title is null)
{
// Preserve default back button title when only accessibility label is set
barButtonItem.Title = previousNavItem.Title;
}
if (!string.IsNullOrEmpty(accessibilityLabel))
{
barButtonItem.AccessibilityLabel = accessibilityLabel;
}
else
{
barButtonItem.AccessibilityLabel = null;
}
}
else if (previousNavItem.BackBarButtonItem != null)
{
previousNavItem.BackBarButtonItem.AccessibilityLabel = null;
previousNavItem.BackBarButtonItem = null;
}
}
Expand Down
19 changes: 19 additions & 0 deletions src/Controls/src/Core/NavigationPage/NavigationPage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ public partial class NavigationPage : Page, IPageContainer<Page>, IBarElement, I
/// <summary>Bindable property for attached property <c>BackButtonTitle</c>.</summary>
public static readonly BindableProperty BackButtonTitleProperty = BindableProperty.CreateAttached("BackButtonTitle", typeof(string), typeof(Page), null);

/// <summary>Bindable property for attached property <c>BackButtonAccessibilityLabel</c>.</summary>
public static readonly BindableProperty BackButtonAccessibilityLabelProperty = BindableProperty.CreateAttached("BackButtonAccessibilityLabel", typeof(string), typeof(Page), null);

/// <summary>Bindable property for attached property <c>HasNavigationBar</c>.</summary>
public static readonly BindableProperty HasNavigationBarProperty =
BindableProperty.CreateAttached("HasNavigationBar", typeof(bool), typeof(Page), true);
Expand Down Expand Up @@ -176,6 +179,14 @@ public static string GetBackButtonTitle(BindableObject page)
return (string)page.GetValue(BackButtonTitleProperty);
}

/// <summary>Gets the accessibility label for the back button of the specified <paramref name="page"/>.</summary>
/// <param name="page">The <see cref="Microsoft.Maui.Controls.Page"/> whose back-button's accessibility label is being requested.</param>
/// <returns>The accessibility label read by screen readers for the back button, or <see langword="null"/> if not set.</returns>
public static string GetBackButtonAccessibilityLabel(BindableObject page)
{
return (string)page.GetValue(BackButtonAccessibilityLabelProperty);
}

/// <summary>Returns a value that indicates whether <paramref name="page"/> has a back button.</summary>
/// <param name="page">The page parameter.</param>
public static bool GetHasBackButton(Page page)
Expand Down Expand Up @@ -355,6 +366,14 @@ public static void SetBackButtonTitle(BindableObject page, string value)
page.SetValue(BackButtonTitleProperty, value);
}

/// <summary>Sets the accessibility label for the back button of <paramref name="page"/>, allowing the text read by screen readers to differ from the visible back button title.</summary>
/// <param name="page">The page parameter.</param>
/// <param name="value">The accessibility label value to set.</param>
public static void SetBackButtonAccessibilityLabel(BindableObject page, string value)
{
page.SetValue(BackButtonAccessibilityLabelProperty, value);
}

/// <summary>Adds or removes a back button to <paramref name="page"/>, with optional animation.</summary>
/// <param name="page">The page parameter.</param>
/// <param name="value">The value to set.</param>
Expand Down
11 changes: 9 additions & 2 deletions src/Controls/src/Core/NavigationPage/NavigationPageToolbar.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ void OnPagePropertyChanged(object sender, System.ComponentModel.PropertyChangedE
e.IsOneOf(
PlatformConfiguration.WindowsSpecific.Page.ToolbarDynamicOverflowEnabledProperty,
PlatformConfiguration.WindowsSpecific.Page.ToolbarPlacementProperty) ||
e.Is(FlyoutPage.FlyoutLayoutBehaviorProperty))
e.Is(FlyoutPage.FlyoutLayoutBehaviorProperty) ||
e.Is(NavigationPage.BackButtonAccessibilityLabelProperty))
{
ApplyChanges(_currentNavigationPage);
}
Expand Down Expand Up @@ -248,10 +249,16 @@ void ApplyChanges(NavigationPage navigationPage)
else
BarHeight = null;

if (previousPage != null)
if (previousPage is not null)
{
BackButtonTitle = NavigationPage.GetBackButtonTitle(previousPage);
BackButtonAccessibilityLabel = NavigationPage.GetBackButtonAccessibilityLabel(previousPage);
}
else
{
BackButtonTitle = null;
BackButtonAccessibilityLabel = null;
}

TitleIcon = NavigationPage.GetTitleIconImageSource(currentPage);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,16 @@ public static void UpdateBackButton(this AToolbar nativeToolbar, Toolbar toolbar
if (nativeToolbar.NavigationIcon is DrawerArrowDrawable iconDrawable)
iconDrawable.Progress = 1;

var backButtonAccessibilityLabel = toolbar.BackButtonAccessibilityLabel;
var backButtonTitle = toolbar.BackButtonTitle;
ImageSource image = toolbar.TitleIcon;

if (!string.IsNullOrEmpty(backButtonTitle))
if (!string.IsNullOrEmpty(backButtonAccessibilityLabel))
{
// Accessibility label takes priority — TalkBack reads this instead of the title.
nativeToolbar.NavigationContentDescription = backButtonAccessibilityLabel;
}
else if (!string.IsNullOrEmpty(backButtonTitle))
{
nativeToolbar.NavigationContentDescription = backButtonTitle;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,32 @@ public static void UpdateBackButton(this MauiToolbar platformToolbar, Toolbar to

UpdateBackButtonVisibility(platformToolbar, toolbar);

// Set Narrator text for the back button when a custom label is provided.
// We save the default value before first override and restore it when the label is cleared,
// so WinUI's default "Back" announcement is preserved.
if (platformToolbar.NavigationViewBackButton is not null)
{
var backButton = platformToolbar.NavigationViewBackButton;
var accessibilityLabel = toolbar.BackButtonAccessibilityLabel;

if (!string.IsNullOrEmpty(accessibilityLabel))
{
// Save the default value before first override
if (backButton.Tag is not string)
{
backButton.Tag = Microsoft.UI.Xaml.Automation.AutomationProperties.GetName(backButton);
}
Comment thread
Vignesh-SF3580 marked this conversation as resolved.

Microsoft.UI.Xaml.Automation.AutomationProperties.SetName(backButton, accessibilityLabel);
}
else if (backButton.Tag is string savedDefault)
{
// Restore the original default ("Back") when the custom label is cleared
Microsoft.UI.Xaml.Automation.AutomationProperties.SetName(backButton, savedDefault);
backButton.Tag = null;
}
}

toolbar.Handler?.UpdateValue(nameof(Toolbar.BarBackground));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,13 @@ virtual Microsoft.Maui.Controls.LongPressingEventArgs.GetPosition(Microsoft.Maui
~static readonly Microsoft.Maui.Controls.ToolbarItem.BadgeTextColorProperty -> Microsoft.Maui.Controls.BindableProperty
~static readonly Microsoft.Maui.Controls.ToolbarItem.BadgeTextProperty -> Microsoft.Maui.Controls.BindableProperty
~virtual Microsoft.Maui.Controls.Platform.Compatibility.ShellItemRenderer.UpdateShellSectionBadge(Microsoft.Maui.Controls.ShellSection shellSection, int index) -> void
~static Microsoft.Maui.Controls.NavigationPage.GetBackButtonAccessibilityLabel(Microsoft.Maui.Controls.BindableObject page) -> string
~static Microsoft.Maui.Controls.NavigationPage.SetBackButtonAccessibilityLabel(Microsoft.Maui.Controls.BindableObject page, string value) -> void
~static readonly Microsoft.Maui.Controls.NavigationPage.BackButtonAccessibilityLabelProperty -> Microsoft.Maui.Controls.BindableProperty
~Microsoft.Maui.Controls.BackButtonBehavior.AccessibilityLabel.get -> string
~Microsoft.Maui.Controls.BackButtonBehavior.AccessibilityLabel.set -> void
~static readonly Microsoft.Maui.Controls.BackButtonBehavior.AccessibilityLabelProperty -> Microsoft.Maui.Controls.BindableProperty
~Microsoft.Maui.Controls.Toolbar.BackButtonAccessibilityLabel.get -> string
~Microsoft.Maui.Controls.Toolbar.BackButtonAccessibilityLabel.set -> void
static Microsoft.Maui.Controls.Toolbar.MapBackButtonAccessibilityLabel(Microsoft.Maui.Handlers.IToolbarHandler! arg1, Microsoft.Maui.Controls.Toolbar! arg2) -> void
static Microsoft.Maui.Controls.Toolbar.MapBackButtonAccessibilityLabel(Microsoft.Maui.Handlers.ToolbarHandler! arg1, Microsoft.Maui.Controls.Toolbar! arg2) -> void
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,11 @@ virtual Microsoft.Maui.Controls.LongPressingEventArgs.GetPosition(Microsoft.Maui
~static readonly Microsoft.Maui.Controls.ToolbarItem.BadgeColorProperty -> Microsoft.Maui.Controls.BindableProperty
~static readonly Microsoft.Maui.Controls.ToolbarItem.BadgeTextColorProperty -> Microsoft.Maui.Controls.BindableProperty
~static readonly Microsoft.Maui.Controls.ToolbarItem.BadgeTextProperty -> Microsoft.Maui.Controls.BindableProperty
~static Microsoft.Maui.Controls.NavigationPage.GetBackButtonAccessibilityLabel(Microsoft.Maui.Controls.BindableObject page) -> string
~static Microsoft.Maui.Controls.NavigationPage.SetBackButtonAccessibilityLabel(Microsoft.Maui.Controls.BindableObject page, string value) -> void
~static readonly Microsoft.Maui.Controls.NavigationPage.BackButtonAccessibilityLabelProperty -> Microsoft.Maui.Controls.BindableProperty
~Microsoft.Maui.Controls.BackButtonBehavior.AccessibilityLabel.get -> string
~Microsoft.Maui.Controls.BackButtonBehavior.AccessibilityLabel.set -> void
~static readonly Microsoft.Maui.Controls.BackButtonBehavior.AccessibilityLabelProperty -> Microsoft.Maui.Controls.BindableProperty
~Microsoft.Maui.Controls.Toolbar.BackButtonAccessibilityLabel.get -> string
~Microsoft.Maui.Controls.Toolbar.BackButtonAccessibilityLabel.set -> void
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,11 @@ virtual Microsoft.Maui.Controls.LongPressingEventArgs.GetPosition(Microsoft.Maui
~static readonly Microsoft.Maui.Controls.ToolbarItem.BadgeColorProperty -> Microsoft.Maui.Controls.BindableProperty
~static readonly Microsoft.Maui.Controls.ToolbarItem.BadgeTextColorProperty -> Microsoft.Maui.Controls.BindableProperty
~static readonly Microsoft.Maui.Controls.ToolbarItem.BadgeTextProperty -> Microsoft.Maui.Controls.BindableProperty
~static Microsoft.Maui.Controls.NavigationPage.GetBackButtonAccessibilityLabel(Microsoft.Maui.Controls.BindableObject page) -> string
~static Microsoft.Maui.Controls.NavigationPage.SetBackButtonAccessibilityLabel(Microsoft.Maui.Controls.BindableObject page, string value) -> void
~static readonly Microsoft.Maui.Controls.NavigationPage.BackButtonAccessibilityLabelProperty -> Microsoft.Maui.Controls.BindableProperty
Comment thread
Vignesh-SF3580 marked this conversation as resolved.
~Microsoft.Maui.Controls.BackButtonBehavior.AccessibilityLabel.get -> string
~Microsoft.Maui.Controls.BackButtonBehavior.AccessibilityLabel.set -> void
~static readonly Microsoft.Maui.Controls.BackButtonBehavior.AccessibilityLabelProperty -> Microsoft.Maui.Controls.BindableProperty
~Microsoft.Maui.Controls.Toolbar.BackButtonAccessibilityLabel.get -> string
~Microsoft.Maui.Controls.Toolbar.BackButtonAccessibilityLabel.set -> void
10 changes: 10 additions & 0 deletions src/Controls/src/Core/PublicAPI/net-tizen/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,13 @@ virtual Microsoft.Maui.Controls.LongPressingEventArgs.GetPosition(Microsoft.Maui
~Microsoft.Maui.Controls.Editor.ReturnCommandParameter.set -> void
~static readonly Microsoft.Maui.Controls.Editor.ReturnCommandParameterProperty -> Microsoft.Maui.Controls.BindableProperty
~static readonly Microsoft.Maui.Controls.Editor.ReturnCommandProperty -> Microsoft.Maui.Controls.BindableProperty
~static Microsoft.Maui.Controls.NavigationPage.GetBackButtonAccessibilityLabel(Microsoft.Maui.Controls.BindableObject page) -> string
~static Microsoft.Maui.Controls.NavigationPage.SetBackButtonAccessibilityLabel(Microsoft.Maui.Controls.BindableObject page, string value) -> void
~static readonly Microsoft.Maui.Controls.NavigationPage.BackButtonAccessibilityLabelProperty -> Microsoft.Maui.Controls.BindableProperty
~Microsoft.Maui.Controls.BackButtonBehavior.AccessibilityLabel.get -> string
~Microsoft.Maui.Controls.BackButtonBehavior.AccessibilityLabel.set -> void
~static readonly Microsoft.Maui.Controls.BackButtonBehavior.AccessibilityLabelProperty -> Microsoft.Maui.Controls.BindableProperty
~Microsoft.Maui.Controls.Toolbar.BackButtonAccessibilityLabel.get -> string
~Microsoft.Maui.Controls.Toolbar.BackButtonAccessibilityLabel.set -> void
static Microsoft.Maui.Controls.Toolbar.MapBackButtonAccessibilityLabel(Microsoft.Maui.Handlers.IToolbarHandler! handler, Microsoft.Maui.Controls.Toolbar! toolbar) -> void
static Microsoft.Maui.Controls.Toolbar.MapBackButtonAccessibilityLabel(Microsoft.Maui.Handlers.ToolbarHandler! handler, Microsoft.Maui.Controls.Toolbar! toolbar) -> void
Loading
Loading