Skip to content
This repository has been archived by the owner on May 1, 2024. It is now read-only.

Account for RTL on Android Tablet #15417

Merged
merged 4 commits into from
Jun 24, 2022
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
19 changes: 18 additions & 1 deletion Xamarin.Forms.Platform.Android/AppCompat/FlyoutPageContainer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -274,15 +274,32 @@ Rectangle GetBounds(bool isFlyoutPage, int left, int top, int right, int bottom)
{
//to keep some behavior we have on iPad where you can toggle and it won't do anything
bool isDefaultNoToggle = _parent.FlyoutLayoutBehavior == FlyoutLayoutBehavior.Default;
xPos = isFlyoutPage ? 0 : (_parent.IsPresented || isDefaultNoToggle ? DefaultWidthFlyout : 0);

if (_parent.FlowDirection == FlowDirection.RightToLeft)
{
double rightDp2 = Context.FromPixels(right);
xPos = isFlyoutPage ? rightDp2 - DefaultWidthFlyout : (_parent.IsPresented || isDefaultNoToggle ? 0 : rightDp2 - DefaultWidthFlyout);
}
else
{
xPos = isFlyoutPage ? 0 : (_parent.IsPresented || isDefaultNoToggle ? DefaultWidthFlyout : 0);
}

width = isFlyoutPage ? DefaultWidthFlyout : _parent.IsPresented || isDefaultNoToggle ? width - DefaultWidthFlyout : width;
}
else
{
//if we are showing the normal popover master doesn't have padding
supressPadding = isFlyoutPage;

if (_parent.FlowDirection == FlowDirection.RightToLeft && isFlyoutPage)
{
xPos = width - DefaultWidthFlyout;
}

//popover make the master smaller
width = isFlyoutPage && (Device.Info.CurrentOrientation.IsLandscape() || Device.Idiom == TargetIdiom.Tablet) ? DefaultWidthFlyout : width;

}

double padding = supressPadding ? 0 : Context.FromPixels(TopPadding);
Expand Down
71 changes: 54 additions & 17 deletions Xamarin.Forms.Platform.Android/AppCompat/FlyoutPageRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -308,31 +308,59 @@ protected override void OnLayout(bool changed, int l, int t, int r, int b)
base.OnLayout(changed, l, t, r, b);
//hack to make the split layout handle touches the full width
if (FlyoutPageController.ShouldShowSplitMode && _flyoutLayout != null)
_flyoutLayout.Right = r;
{
if (Element.FlowDirection == FlowDirection.RightToLeft)
_flyoutLayout.Left = l;
else
_flyoutLayout.Right = r;
}
}

async void DeviceInfoPropertyChanged(object sender, PropertyChangedEventArgs e)
async void UpdateFlyoutLayoutBehavior(bool requestLayout = false)
{
if (nameof(Device.Info.CurrentOrientation) == e.PropertyName)
if (!FlyoutPageController.ShouldShowSplitMode && Presented)
{
if (!FlyoutPageController.ShouldShowSplitMode && Presented)
FlyoutPageController.CanChangeIsPresented = true;
//hack : when the orientation changes and we try to close the Flyout on Android
//sometimes Android picks the width of the screen previous to the rotation
//this leaves a little of the flyout visible, the hack is to delay for 100ms closing the drawer
await Task.Delay(100);

//Renderer may have been disposed during the delay
if (_disposed)
{
FlyoutPageController.CanChangeIsPresented = true;
//hack : when the orientation changes and we try to close the Flyout on Android
//sometimes Android picks the width of the screen previous to the rotation
//this leaves a little of the flyout visible, the hack is to delay for 100ms closing the drawer
await Task.Delay(100);

//Renderer may have been disposed during the delay
if (_disposed)
{
return;
}
return;
}

CloseDrawer(_flyoutLayout);
CloseDrawer(_flyoutLayout);
}
else if (FlyoutPageController.ShouldShowSplitMode)
{
OpenDrawer(_flyoutLayout, false);
}

UpdateSplitViewLayout();

if (requestLayout)
{
_flyoutLayout?.MaybeRequestLayout();
_detailLayout?.MaybeRequestLayout();

if (Device.Idiom == TargetIdiom.Tablet && _flyoutLayout != null)
{
// This is required to add/remove the drawer button
// This basically runs the same code that runs when
// a device changes between landscape/portrait
_detailLayout.GetFirstChildOfType<NavigationPageRenderer>()?.ResetToolbar();
}
}
}

UpdateSplitViewLayout();
void DeviceInfoPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (nameof(Device.Info.CurrentOrientation) == e.PropertyName)
{
UpdateFlyoutLayoutBehavior();
}
}

Expand Down Expand Up @@ -373,7 +401,16 @@ void HandlePropertyChanged(object sender, PropertyChangedEventArgs e)
else if (e.PropertyName == VisualElement.BackgroundColorProperty.PropertyName)
UpdateBackgroundColor(Element);
else if (e.PropertyName == VisualElement.FlowDirectionProperty.PropertyName)
{
UpdateFlowDirection();

// This will move the drawer layout button to the proper side of the toolbar
_detailLayout.GetFirstChildOfType<NavigationPageRenderer>()?.UpdateToolbar();
}
else if (e.Is(FlyoutPage.FlyoutLayoutBehaviorProperty))
{
UpdateFlyoutLayoutBehavior(true);
}
}

void FlyoutPageAppearing(object sender, EventArgs e)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -736,7 +736,7 @@ void RemovePage(Page page)
});
}

void ResetToolbar()
internal void ResetToolbar()
{
AToolbar oldToolbar = _toolbar;

Expand Down Expand Up @@ -933,7 +933,7 @@ protected virtual void UpdateMenuItemIcon(Context context, IMenuItem menuItem, T
ToolbarExtensions.UpdateMenuItemIcon(context, menuItem, toolBarItem, null);
}

void UpdateToolbar()
internal void UpdateToolbar()
{
if (_disposed)
return;
Expand Down Expand Up @@ -982,6 +982,13 @@ void UpdateToolbar()
{
toggle.DrawerIndicatorEnabled = _flyoutPage.ShouldShowToolbarButton();
toggle.SyncState();

// When pivoting between split mode and flyout mode
// The DrawerArrowDrawable Progress will get out of sync and show a back button
// this forces it back to a hamburger

if (toggle.DrawerArrowDrawable != null)
toggle.DrawerArrowDrawable.Progress = 0;
}
}

Expand Down
22 changes: 22 additions & 0 deletions Xamarin.Forms.Platform.Android/Renderers/ViewGroupExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,27 @@ internal static IEnumerable<T> GetChildrenOfType<T>(this AViewGroup self) where
}
}
}

public static T GetFirstChildOfType<T>(this AViewGroup viewGroup) where T : AView
{
for (var i = 0; i < viewGroup.ChildCount; i++)
{
AView child = viewGroup.GetChildAt(i);

if (child is T typedChild)
return typedChild;

if (child is AViewGroup vg)
{
var descendant = vg.GetFirstChildOfType<T>();
if (descendant != null)
{
return descendant;
}
}
}

return null;
}
}
}
3 changes: 3 additions & 0 deletions build/steps/build-osx.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ steps:
inputs:
provProfileSecureFile: 'Xamarin Forms iOS Provisioning.mobileprovision'

- bash: rm -rf ~/.config/NuGet/NuGet.Config
displayName: 'Workaround to make build work'

- task: Bash@3
displayName: 'Build Control Gallery IPA'
inputs:
Expand Down