-
Notifications
You must be signed in to change notification settings - Fork 1.9k
[iOS/Mac] Fix FlyoutPage RTL FlowDirection is not working #34831
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
c4c5a40
9c820c5
b2b274b
7d0208c
5f46aa9
f4499b4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -186,9 +186,9 @@ bool shouldReceive(UIGestureRecognizer g, UITouch t) | |
|
|
||
| PackContainers(); | ||
| UpdateFlyoutPageContainers(); | ||
| UpdateFlowDirection(); | ||
|
|
||
| UpdateBackground(); | ||
|
|
||
| UpdatePanGesture(); | ||
| UpdateApplyShadow(((FlyoutPage)Element).OnThisPlatform().GetApplyShadow()); | ||
| UpdatePageSpecifics(); | ||
|
|
@@ -360,6 +360,54 @@ 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.PropertyName == VisualElement.FlowDirectionProperty.PropertyName) | ||
| { | ||
| UpdateFlowDirection(); | ||
| UpdateLeftBarButton(); | ||
| } | ||
| } | ||
|
|
||
| void UpdateFlowDirection() | ||
| { | ||
| if (Element is null) | ||
| return; | ||
|
|
||
| // Determine the semantic content attribute from the MAUI model so this works | ||
| // correctly both during initial setup (when the parent UIView's attribute may not | ||
| // yet be set) and for runtime FlowDirection changes. | ||
| var semanticAttr = IsRTL | ||
| ? UISemanticContentAttribute.ForceRightToLeft | ||
| : UISemanticContentAttribute.ForceLeftToRight; | ||
|
|
||
| // Set SemanticContentAttribute on the root view and both child-controller container | ||
| // views so that any MAUI child handlers that resolve FlowDirection.MatchParent by | ||
| // looking at their parent's platform view find the correct direction. | ||
| View.SemanticContentAttribute = semanticAttr; | ||
| _flyoutController.View.SemanticContentAttribute = semanticAttr; | ||
| _detailController.View.SemanticContentAttribute = semanticAttr; | ||
|
Collaborator
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. [minor] Null Safety — |
||
|
|
||
| // UINavigationBar is a UIKit-only view outside the MAUI hierarchy and does *not* | ||
| // inherit SemanticContentAttribute from its parent. Set it explicitly so that bar | ||
| // button items (the flyout hamburger icon) are mirrored to the correct side for RTL. | ||
| if (FlyoutPage.Detail.Handler is IPlatformViewHandler detailPlatformHandler && | ||
|
Collaborator
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. [moderate] Null Safety — |
||
| detailPlatformHandler.ViewController is UINavigationController navController) | ||
| { | ||
| navController.View.SemanticContentAttribute = semanticAttr; | ||
| navController.NavigationBar.SemanticContentAttribute = semanticAttr; | ||
| } | ||
|
|
||
| // NavigationPage is neither IContainer nor IContentView in the Core layer, so | ||
| // PropagateFlowDirection in ViewExtensions does not recurse into its pages. | ||
| // Manually re-trigger FlowDirection on each page in the navigation stack so their | ||
| // platform views (and descendants) pick up the correct direction on initial load. | ||
| if (FlyoutPage.Detail is NavigationPage detailNavPage) | ||
| { | ||
| foreach (var page in detailNavPage.Navigation.NavigationStack) | ||
| { | ||
| if (page?.Handler is IElementHandler pageHandler) | ||
| pageHandler.UpdateValue(nameof(IView.FlowDirection)); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| void LayoutChildren(bool animated) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| namespace Maui.Controls.Sample.Issues; | ||
|
|
||
| [Issue(IssueTracker.Github, 34830, "[iOS/Mac] FlyoutPage RTL FlowDirection is not working properly", PlatformAffected.iOS | PlatformAffected.macOS)] | ||
| public class Issue34830 : TestFlyoutPage | ||
| { | ||
| protected override void Init() | ||
| { | ||
| FlyoutLayoutBehavior = FlyoutLayoutBehavior.Popover; | ||
| FlowDirection = FlowDirection.RightToLeft; | ||
|
|
||
| Flyout = new ContentPage | ||
| { | ||
| Title = "Flyout", | ||
| BackgroundColor = Colors.SkyBlue, | ||
| IconImageSource = "menu_icon", | ||
| Content = new StackLayout | ||
| { | ||
| Children = | ||
| { | ||
| new Button | ||
| { | ||
| Text = "If you can see me the test has passed", | ||
| AutomationId = "CloseRootView", | ||
| Command = new Command(() => IsPresented = false) | ||
| } | ||
| }, | ||
| AutomationId = "RootLayout" | ||
| }, | ||
| Padding = new Thickness(0, 42, 0, 0) | ||
| }; | ||
|
|
||
| Detail = new NavigationPage(new ContentPage | ||
| { | ||
| Title = "Detail", | ||
| Content = new StackLayout | ||
| { | ||
| Children = | ||
| { | ||
| new Label | ||
| { | ||
| Text = "The page must be with RightToLeft FlowDirection. Hamburger icon in main page must be on the right side. There should be visible text inside the Flyout View" | ||
| }, | ||
| new Button | ||
| { | ||
| Text = "Set RightToLeft", | ||
| Command = new Command(() => FlowDirection = FlowDirection.RightToLeft), | ||
| AutomationId = "ShowRightToLeft" | ||
| }, | ||
| new Button | ||
| { | ||
| Text = "Set LeftToRight", | ||
| Command = new Command(() => FlowDirection = FlowDirection.LeftToRight), | ||
| AutomationId = "ShowLeftToRight" | ||
| }, | ||
| new Button | ||
| { | ||
| Text = "Open Flyout View", | ||
| Command = new Command(() => IsPresented = true), | ||
| AutomationId = "OpenRootView" | ||
| }, | ||
| new Label | ||
| { | ||
| Text = DeviceInfo.Idiom.ToString(), | ||
| AutomationId = "Idiom" | ||
| } | ||
| } | ||
| } | ||
| }); | ||
| } | ||
| } | ||
|
Collaborator
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. [minor] Style — File is missing a trailing newline ( |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| using NUnit.Framework; | ||
| using UITest.Appium; | ||
| using UITest.Core; | ||
|
|
||
| namespace Microsoft.Maui.TestCases.Tests.Issues; | ||
|
|
||
| public class Issue34830 : _IssuesUITest | ||
| { | ||
| public Issue34830(TestDevice device) : base(device) | ||
| { | ||
| } | ||
|
|
||
| public override string Issue => "[iOS/Mac] FlyoutPage RTL FlowDirection is not working properly"; | ||
|
|
||
| [Test, Order(1)] | ||
| [Category(UITestCategories.FlyoutPage)] | ||
| public void FlyoutPageWithRTLDirection() | ||
| { | ||
| App.WaitForElement("ShowRightToLeft"); | ||
| App.WaitForElement("OpenRootView"); | ||
| App.Tap("OpenRootView"); | ||
| VerifyScreenshot(); | ||
| } | ||
|
|
||
| [Test, Order(2)] | ||
| [Category(UITestCategories.FlyoutPage)] | ||
| public void FlyoutPageWithLTRDirection() | ||
| { | ||
| App.Tap("CloseRootView"); | ||
| App.WaitForElement("ShowLeftToRight"); | ||
| App.Tap("ShowLeftToRight"); | ||
| App.WaitForElement("OpenRootView"); | ||
| App.Tap("OpenRootView"); | ||
| VerifyScreenshot(); | ||
| } | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.