diff --git a/src/Controls/src/Core/Compatibility/Handlers/FlyoutPage/iOS/PhoneFlyoutPageRenderer.cs b/src/Controls/src/Core/Compatibility/Handlers/FlyoutPage/iOS/PhoneFlyoutPageRenderer.cs index 8cf5c209b799..93dd364c7413 100644 --- a/src/Controls/src/Core/Compatibility/Handlers/FlyoutPage/iOS/PhoneFlyoutPageRenderer.cs +++ b/src/Controls/src/Core/Compatibility/Handlers/FlyoutPage/iOS/PhoneFlyoutPageRenderer.cs @@ -155,7 +155,7 @@ void SetInitialPresented() else UpdatePresented(((FlyoutPage)Element).IsPresented); - UpdateLeftBarButton(); + UpdateBarButton(); } public override void ViewWillLayoutSubviews() @@ -219,7 +219,7 @@ public override void ViewWillTransitionToSize(CoreGraphics.CGSize toSize, IUIVie UpdatePresented(false); } - UpdateLeftBarButton(); + UpdateBarButton(); } void UpdatePresented(bool newValue, bool animated = false) @@ -349,7 +349,7 @@ void EmptyContainers() void HandleFlyoutPropertyChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == Page.IconImageSourceProperty.PropertyName || e.PropertyName == Page.TitleProperty.PropertyName) - UpdateLeftBarButton(); + UpdateBarButton(); } void HandlePropertyChanged(object sender, PropertyChangedEventArgs e) @@ -369,6 +369,8 @@ void HandlePropertyChanged(object sender, PropertyChangedEventArgs e) else if (e.PropertyName == PlatformConfiguration.iOSSpecific.Page.PrefersHomeIndicatorAutoHiddenProperty.PropertyName || e.PropertyName == PlatformConfiguration.iOSSpecific.Page.PrefersStatusBarHiddenProperty.PropertyName) UpdatePageSpecifics(); + else if (e.Is(VisualElement.FlowDirectionProperty)) + UpdateBarButton(); } void LayoutChildren(bool animated) @@ -559,7 +561,7 @@ void UpdateFlyoutPageContainers() UpdatePageSpecifics(); } - void UpdateLeftBarButton() + void UpdateBarButton() { var FlyoutPage = Element as FlyoutPage; if (!(FlyoutPage?.Detail is NavigationPage)) @@ -571,7 +573,7 @@ void UpdateLeftBarButton() UIViewController firstPage = detailRenderer?.ViewControllers.FirstOrDefault(); if (firstPage != null) - NavigationRenderer.SetFlyoutLeftBarButton(firstPage, FlyoutPage); + NavigationRenderer.SetFlyoutBarButton(firstPage, FlyoutPage, IsRTL); } void UpdateApplyShadow(bool value) diff --git a/src/Controls/src/Core/Compatibility/Handlers/NavigationPage/iOS/NavigationRenderer.cs b/src/Controls/src/Core/Compatibility/Handlers/NavigationPage/iOS/NavigationRenderer.cs index 30a2f4cb9494..730c61cd8bc0 100644 --- a/src/Controls/src/Core/Compatibility/Handlers/NavigationPage/iOS/NavigationRenderer.cs +++ b/src/Controls/src/Core/Compatibility/Handlers/NavigationPage/iOS/NavigationRenderer.cs @@ -922,23 +922,30 @@ bool DidPopItem(UINavigationBar _, UINavigationItem __) return true; } - internal static void SetFlyoutLeftBarButton(UIViewController containerController, FlyoutPage FlyoutPage) + internal static void SetFlyoutBarButton(UIViewController containerController, FlyoutPage FlyoutPage, bool isRTL) { + if (isRTL) + containerController.NavigationItem.LeftBarButtonItem = null; + else + containerController.NavigationItem.RightBarButtonItem = null; + if (!FlyoutPage.ShouldShowToolbarButton()) { containerController.NavigationItem.LeftBarButtonItem = null; + containerController.NavigationItem.RightBarButtonItem = null; return; } - FlyoutPage.Flyout.IconImageSource.LoadImage(FlyoutPage.FindMauiContext(), result => { var icon = result?.Value; + UIBarButtonItem uIBarButtonItem = null; + if (icon != null) { try { - containerController.NavigationItem.LeftBarButtonItem = new UIBarButtonItem(icon, UIBarButtonItemStyle.Plain, OnItemTapped); + uIBarButtonItem = new UIBarButtonItem(icon, UIBarButtonItemStyle.Plain, OnItemTapped); } catch (Exception) { @@ -946,16 +953,22 @@ internal static void SetFlyoutLeftBarButton(UIViewController containerController } } - if (icon == null || containerController.NavigationItem.LeftBarButtonItem == null) + if (icon == null || uIBarButtonItem == null) { - containerController.NavigationItem.LeftBarButtonItem = new UIBarButtonItem(FlyoutPage.Flyout.Title, UIBarButtonItemStyle.Plain, OnItemTapped); + uIBarButtonItem = new UIBarButtonItem(FlyoutPage.Flyout.Title, UIBarButtonItemStyle.Plain, OnItemTapped); } if (FlyoutPage != null && !string.IsNullOrEmpty(FlyoutPage.AutomationId)) - SetAutomationId(containerController.NavigationItem.LeftBarButtonItem, $"btn_{FlyoutPage.AutomationId}"); + SetAutomationId(uIBarButtonItem, $"btn_{FlyoutPage.AutomationId}"); + + uIBarButtonItem.SetAccessibilityHint(FlyoutPage); + uIBarButtonItem.SetAccessibilityLabel(FlyoutPage); + + if (isRTL) + containerController.NavigationItem.RightBarButtonItem = uIBarButtonItem; + else + containerController.NavigationItem.LeftBarButtonItem = uIBarButtonItem; - containerController.NavigationItem.LeftBarButtonItem.SetAccessibilityHint(FlyoutPage); - containerController.NavigationItem.LeftBarButtonItem.SetAccessibilityLabel(FlyoutPage); }); void OnItemTapped(object sender, EventArgs e) @@ -1481,7 +1494,7 @@ internal void UpdateLeftBarButtonItem(Page pageBeingRemoved = null) return; } - SetFlyoutLeftBarButton(this, n._parentFlyoutPage); + SetFlyoutBarButton(this, n._parentFlyoutPage, isRTL: false); } diff --git a/src/Controls/tests/TestCases.Android.Tests/snapshots/android/FlyoutIconShouldBeCorrectlyPositioned.png b/src/Controls/tests/TestCases.Android.Tests/snapshots/android/FlyoutIconShouldBeCorrectlyPositioned.png new file mode 100644 index 000000000000..63fadbb6136c Binary files /dev/null and b/src/Controls/tests/TestCases.Android.Tests/snapshots/android/FlyoutIconShouldBeCorrectlyPositioned.png differ diff --git a/src/Controls/tests/TestCases.HostApp/Issues/Issue26726.cs b/src/Controls/tests/TestCases.HostApp/Issues/Issue26726.cs new file mode 100644 index 000000000000..a1032be7e03c --- /dev/null +++ b/src/Controls/tests/TestCases.HostApp/Issues/Issue26726.cs @@ -0,0 +1,28 @@ +namespace Maui.Controls.Sample.Issues +{ + + [Issue(IssueTracker.Github, 26726, "Flyout Icon Positioned Incorrectly in RTL mode", PlatformAffected.iOS)] + class Issue26726 : FlyoutPage + { + public Issue26726() + { + Flyout = new ContentPage { Title = "Flyout" }; + Detail = new NavigationPage(new ContentPage + { + Title = "Detail", + Content = new StackLayout + { + Children = { + new Button + { + Text = "Set RightToLeft", + Command = new Command(() => FlowDirection = FlowDirection.RightToLeft), + AutomationId = "ShowRightToLeft" + } + } + } + }); + } + + } +} diff --git a/src/Controls/tests/TestCases.Mac.Tests/snapshots/mac/FlyoutIconShouldBeCorrectlyPositioned.png b/src/Controls/tests/TestCases.Mac.Tests/snapshots/mac/FlyoutIconShouldBeCorrectlyPositioned.png new file mode 100644 index 000000000000..6a57edb5f9e0 Binary files /dev/null and b/src/Controls/tests/TestCases.Mac.Tests/snapshots/mac/FlyoutIconShouldBeCorrectlyPositioned.png differ diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue26726.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue26726.cs new file mode 100644 index 000000000000..f5372abff194 --- /dev/null +++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue26726.cs @@ -0,0 +1,22 @@ +using NUnit.Framework; +using UITest.Appium; +using UITest.Core; + +namespace Microsoft.Maui.TestCases.Tests.Issues +{ + public class Issue26726 : _IssuesUITest + { + public override string Issue => "Flyout Icon Positioned Incorrectly in RTL mode"; + + public Issue26726(TestDevice testDevice) : base(testDevice) { } + + [Test] + [Category(UITestCategories.FlyoutPage)] + public void FlyoutIconShouldBeCorrectlyPositioned() + { + App.WaitForElement("ShowRightToLeft"); + App.Click("ShowRightToLeft"); + VerifyScreenshot(); + } + } +} \ No newline at end of file diff --git a/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/FlyoutIconShouldBeCorrectlyPositioned.png b/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/FlyoutIconShouldBeCorrectlyPositioned.png new file mode 100644 index 000000000000..45dd52d3f5eb Binary files /dev/null and b/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/FlyoutIconShouldBeCorrectlyPositioned.png differ diff --git a/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/FlyoutIconShouldBeCorrectlyPositioned.png b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/FlyoutIconShouldBeCorrectlyPositioned.png new file mode 100644 index 000000000000..777f95e807c7 Binary files /dev/null and b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/FlyoutIconShouldBeCorrectlyPositioned.png differ