Skip to content

Commit 67d5fca

Browse files
committed
- push up latest flyout page updates for iOS
1 parent 405c612 commit 67d5fca

File tree

1 file changed

+92
-46
lines changed

1 file changed

+92
-46
lines changed

ShanedlerSamples/Library/Workarounds/CustomPhoneFlyoutPageRendererPopOver.cs

Lines changed: 92 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,36 @@ public class CustomPhoneFlyoutPageRendererPopOver : UIViewController, IPlatformV
3434
bool _applyShadow;
3535

3636
bool _intialLayoutFinished;
37+
bool? _flyoutOverlapsDetailsInPopoverMode;
3738

3839
Page Page => Element as Page;
3940
IFlyoutPageController FlyoutPageController => FlyoutPage;
4041
IMauiContext _mauiContext;
4142
IMauiContext MauiContext => _mauiContext;
42-
bool IsPad => UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Pad;
4343

4444
public static IPropertyMapper<FlyoutPage, CustomPhoneFlyoutPageRendererPopOver> Mapper = new PropertyMapper<FlyoutPage, CustomPhoneFlyoutPageRendererPopOver>(ViewHandler.ViewMapper);
4545
public static CommandMapper<FlyoutPage, CustomPhoneFlyoutPageRendererPopOver> CommandMapper = new CommandMapper<FlyoutPage, CustomPhoneFlyoutPageRendererPopOver>(ViewHandler.ViewCommandMapper);
46+
// Forms used a UISplitViewController for iPad and a custom implementation for iPhone.
47+
// With MAUI, we switched to using this same handler for both iPad/iPhone to simplify
48+
// the amount of code we needed to maintain. The UISplitViewController implementation was also
49+
// problematic and would break frequently between iOS upgrades.
50+
// At a later point, this implementation will get merged with the shell implementation so we have
51+
// to maintain even less code.
52+
public bool FlyoutOverlapsDetailsInPopoverMode
53+
{
54+
get
55+
{
56+
return _flyoutOverlapsDetailsInPopoverMode ??
57+
UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Pad;
58+
}
59+
set
60+
{
61+
_flyoutOverlapsDetailsInPopoverMode = value;
62+
}
63+
}
64+
65+
bool IsRTL => (Element as IVisualElementController)?.EffectiveFlowDirection.IsRightToLeft() == true;
66+
4667
ViewHandlerDelegator<FlyoutPage> _viewHandlerWrapper;
4768

4869
[Preserve(Conditional = true)]
@@ -170,7 +191,7 @@ bool shouldReceive(UIGestureRecognizer g, UITouch t)
170191
UpdatePresented(false, true);
171192
});
172193

173-
if (IsPad)
194+
if (FlyoutOverlapsDetailsInPopoverMode)
174195
_tapGesture.ShouldReceiveTouch = shouldReceive;
175196

176197
_clickOffView.AddGestureRecognizer(_tapGesture);
@@ -188,7 +209,7 @@ public override void ViewWillTransitionToSize(CoreGraphics.CGSize toSize, IUIVie
188209
{
189210
base.ViewWillTransitionToSize(toSize, coordinator);
190211

191-
if (IsPad)
212+
if (FlyoutOverlapsDetailsInPopoverMode)
192213
{
193214
if (FlyoutPageController.ShouldShowSplitMode)
194215
UpdatePresented(true);
@@ -269,7 +290,7 @@ protected virtual void OnElementChanged(VisualElementChangedEventArgs e)
269290

270291
void UpdateClickOffView()
271292
{
272-
if (IsPad && FlyoutPageController.ShouldShowSplitMode)
293+
if (FlyoutOverlapsDetailsInPopoverMode && FlyoutPageController.ShouldShowSplitMode)
273294
{
274295
RemoveClickOffView();
275296
return;
@@ -292,14 +313,18 @@ void AddClickOffView()
292313

293314
void UpdateClickOffViewFrame()
294315
{
295-
if (IsPad)
316+
if (FlyoutOverlapsDetailsInPopoverMode)
296317
{
297318
var detailsFrame = _detailController.View.Frame;
298319
var flyoutWidth = _flyoutController.View.Frame.Width;
320+
var clickOffX = _flyoutController.View.Frame.Width;
321+
322+
if (IsRTL)
323+
clickOffX = 0;
299324

300325
_clickOffView.Frame =
301326
new CoreGraphics.CGRect(
302-
_flyoutController.View.Frame.Width,
327+
clickOffX,
303328
detailsFrame.Y,
304329
detailsFrame.Width - flyoutWidth,
305330
detailsFrame.Height);
@@ -352,7 +377,7 @@ void LayoutChildren(bool animated)
352377
var flyoutFrame = frame;
353378
nfloat opacity = 1;
354379

355-
if (IsPad)
380+
if (FlyoutOverlapsDetailsInPopoverMode)
356381
flyoutFrame.Width = 320;
357382
else
358383
flyoutFrame.Width = (int)(Math.Min(flyoutFrame.Width, flyoutFrame.Height) * 0.8);
@@ -363,75 +388,89 @@ void LayoutChildren(bool animated)
363388

364389
var detailView = detailRenderer.ViewController.View;
365390

366-
var isRTL = (Element as IVisualElementController)?.EffectiveFlowDirection.IsRightToLeft() == true;
367-
if (isRTL)
391+
if (IsRTL && !FlyoutOverlapsDetailsInPopoverMode)
368392
{
369393
flyoutFrame.X = (int)(flyoutFrame.Width * .25);
370394
}
371395

372-
var target = frame;
396+
var detailsFrame = frame;
373397
if (Presented)
374398
{
375-
if (!IsPad || FlyoutPageController.ShouldShowSplitMode)
376-
target.X += flyoutFrame.Width;
399+
if (!FlyoutOverlapsDetailsInPopoverMode || FlyoutPageController.ShouldShowSplitMode)
400+
{
401+
if (IsRTL && FlyoutPageController.ShouldShowSplitMode)
402+
detailsFrame.X = 0;
403+
else
404+
detailsFrame.X += flyoutFrame.Width;
405+
}
377406

378-
if (IsPad && FlyoutPageController.ShouldShowSplitMode)
379-
target.Width -= flyoutFrame.Width;
407+
if (FlyoutOverlapsDetailsInPopoverMode && FlyoutPageController.ShouldShowSplitMode)
408+
{
409+
detailsFrame.Width -= flyoutFrame.Width;
410+
}
380411

381412
if (_applyShadow)
413+
{
382414
opacity = 0.5f;
415+
}
383416
}
384417

385-
if (isRTL)
418+
if (IsRTL && !FlyoutOverlapsDetailsInPopoverMode)
386419
{
387-
target.X = target.X * -1;
420+
detailsFrame.X = detailsFrame.X * -1;
388421
}
389422

390-
if (animated && !IsPad)
423+
if (animated && !FlyoutOverlapsDetailsInPopoverMode)
391424
{
392-
if (!IsPad)
425+
if (!FlyoutOverlapsDetailsInPopoverMode)
393426
{
394427
UIView.Animate(0.250, 0, UIViewAnimationOptions.CurveEaseOut, () =>
395428
{
396429
var view = _detailController.View;
397-
view.Frame = target;
430+
view.Frame = detailsFrame;
398431
detailView.Layer.Opacity = (float)opacity;
399432
}, () => { });
400433
}
401434
}
402435
else
403436
{
404-
_detailController.View.Frame = target;
437+
_detailController.View.Frame = detailsFrame;
405438
detailView.Layer.Opacity = (float)opacity;
406439
}
407440

408-
if (IsPad)
441+
if (FlyoutOverlapsDetailsInPopoverMode)
409442
{
410443
if (!Presented)
411444
{
412-
flyoutFrame.X -= flyoutFrame.Width;
445+
if (!IsRTL)
446+
flyoutFrame.X -= flyoutFrame.Width;
447+
else
448+
flyoutFrame.X = frame.Width;
413449
}
414-
415-
if (animated)
450+
else if (IsRTL)
416451
{
417-
UIView.Animate(0.250, 0, UIViewAnimationOptions.CurveEaseOut, () =>
418-
{
419-
_flyoutController.View.Frame = flyoutFrame;
420-
detailView.Layer.Opacity = (float)opacity;
421-
}, () => { });
452+
if (FlyoutPageController.ShouldShowSplitMode)
453+
flyoutFrame.X = detailsFrame.Width;
454+
else
455+
flyoutFrame.X = frame.Width - flyoutFrame.Width;
422456
}
423-
else
457+
}
458+
459+
if (animated && FlyoutOverlapsDetailsInPopoverMode)
460+
{
461+
UIView.Animate(0.250, 0, UIViewAnimationOptions.CurveEaseOut, () =>
424462
{
425463
_flyoutController.View.Frame = flyoutFrame;
426-
}
464+
detailView.Layer.Opacity = (float)opacity;
465+
}, () => { });
466+
}
467+
else
468+
{
469+
_flyoutController.View.Frame = flyoutFrame;
427470
}
428471

429472
FlyoutPageController.FlyoutBounds = new Rect(flyoutFrame.X, 0, flyoutFrame.Width, flyoutFrame.Height);
430-
431-
if (IsPad)
432-
FlyoutPageController.DetailBounds = new Rect(target.X, 0, frame.Width, frame.Height);
433-
else
434-
FlyoutPageController.DetailBounds = new Rect(0, 0, frame.Width, frame.Height);
473+
FlyoutPageController.DetailBounds = new Rect(detailsFrame.X, 0, frame.Width, frame.Height);
435474

436475
if (Presented)
437476
UpdateClickOffViewFrame();
@@ -441,7 +480,7 @@ void PackContainers()
441480
{
442481
_detailController.View.BackgroundColor = new UIColor(1, 1, 1, 1);
443482

444-
if (!IsPad)
483+
if (!FlyoutOverlapsDetailsInPopoverMode)
445484
{
446485
View.AddSubview(_flyoutController.View);
447486
View.AddSubview(_detailController.View);
@@ -601,17 +640,15 @@ bool shouldReceive(UIGestureRecognizer g, UITouch t)
601640
var center = new PointF();
602641
_panGesture = new UIPanGestureRecognizer(g =>
603642
{
604-
var isRTL = (Element as IVisualElementController)?.EffectiveFlowDirection.IsRightToLeft() == true;
605-
606-
int directionModifier = isRTL ? -1 : 1;
643+
int directionModifier = IsRTL ? -1 : 1;
607644

608645
switch (g.State)
609646
{
610647
case UIGestureRecognizerState.Began:
611648
center = g.LocationInView(g.View);
612649
break;
613650
case UIGestureRecognizerState.Changed:
614-
if (!IsPad)
651+
if (!FlyoutOverlapsDetailsInPopoverMode)
615652
{
616653
var currentPosition = g.LocationInView(g.View);
617654
var motion = currentPosition.X - center.X;
@@ -650,7 +687,11 @@ bool shouldReceive(UIGestureRecognizer g, UITouch t)
650687
else
651688
targetFrame.X = (nfloat)Math.Min(0, Math.Max(0, motion) - flyoutWidth);
652689

653-
targetFrame.X = targetFrame.X * directionModifier;
690+
if (IsRTL)
691+
{
692+
targetFrame.X = (float)Element.Bounds.Width - (flyoutWidth + targetFrame.X);
693+
}
694+
654695
if (_applyShadow)
655696
{
656697
var openProgress = targetFrame.X / flyoutWidth;
@@ -663,7 +704,7 @@ bool shouldReceive(UIGestureRecognizer g, UITouch t)
663704
break;
664705
case UIGestureRecognizerState.Ended:
665706

666-
if (!IsPad)
707+
if (!FlyoutOverlapsDetailsInPopoverMode)
667708
{
668709
var detailFrame = _detailController.View.Frame;
669710
var flyoutFrame = _flyoutController.View.Frame;
@@ -685,18 +726,23 @@ bool shouldReceive(UIGestureRecognizer g, UITouch t)
685726
else
686727
{
687728
var flyoutFrame = _flyoutController.View.Frame;
688-
var progress = flyoutFrame.Width + flyoutFrame.X;
729+
var flyoutOffsetX = flyoutFrame.X + flyoutFrame.Width;
730+
731+
if (IsRTL)
732+
{
733+
flyoutOffsetX = (float)Element.Bounds.Width - flyoutFrame.X;
734+
}
689735

690736
if (Presented)
691737
{
692-
if (flyoutFrame.X * directionModifier < flyoutFrame.Width * .75)
738+
if (flyoutOffsetX < flyoutFrame.Width * .75)
693739
UpdatePresented(false);
694740
else
695741
LayoutChildren(true);
696742
}
697743
else
698744
{
699-
if ((flyoutFrame.X + flyoutFrame.Width) * directionModifier > flyoutFrame.Width * .25)
745+
if (flyoutOffsetX > flyoutFrame.Width * .25)
700746
UpdatePresented(true);
701747
else
702748
LayoutChildren(true);

0 commit comments

Comments
 (0)