Better detect IsCollapsed state/changes on master (#8181)
This commit is contained in:
Родитель
2f02371116
Коммит
1ecdf97d2f
|
@ -49,7 +49,8 @@ namespace Xamarin.Forms.Controls.Issues
|
|||
public DetailsPage(MasterDetailPage masterDetailPage)
|
||||
{
|
||||
MDP = masterDetailPage;
|
||||
lblThings = new Label();
|
||||
lblThings = new Label() { HorizontalTextAlignment = TextAlignment.Center, AutomationId = "CurrentMasterBehavior" };
|
||||
|
||||
Content = new StackLayout()
|
||||
{
|
||||
Children =
|
||||
|
@ -58,7 +59,8 @@ namespace Xamarin.Forms.Controls.Issues
|
|||
new Button()
|
||||
{
|
||||
Text = "Click to rotate through MasterBehavior settings and test each one",
|
||||
Command = new Command(OnChangeMasterBehavior)
|
||||
Command = new Command(OnChangeMasterBehavior),
|
||||
AutomationId = "ChangeMasterBehavior"
|
||||
},
|
||||
new Button()
|
||||
{
|
||||
|
@ -75,7 +77,8 @@ namespace Xamarin.Forms.Controls.Issues
|
|||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
},
|
||||
new Label(){ HorizontalTextAlignment = TextAlignment.Center, Text = "Close Master" }
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -113,6 +116,39 @@ namespace Xamarin.Forms.Controls.Issues
|
|||
RunningApp.WaitForElement("Master Visible");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SplitOnLandscapeFailsToDetectClose()
|
||||
{
|
||||
if (!RunningApp.IsTablet())
|
||||
return;
|
||||
|
||||
while(RunningApp.WaitForElement("CurrentMasterBehavior")[0].ReadText() != MasterBehavior.SplitOnLandscape.ToString())
|
||||
{
|
||||
RunningApp.Tap("ChangeMasterBehavior");
|
||||
|
||||
if(RunningApp.Query("Master Visible").Length > 0)
|
||||
RunningApp.Tap("Close Master");
|
||||
}
|
||||
|
||||
RunningApp.Tap("Master");
|
||||
RunningApp.WaitForElement("Master Visible");
|
||||
RunningApp.Tap("Close Master");
|
||||
|
||||
RunningApp.SetOrientationLandscape();
|
||||
RunningApp.SetOrientationPortrait();
|
||||
RunningApp.SetOrientationLandscape();
|
||||
RunningApp.SetOrientationPortrait();
|
||||
|
||||
if (RunningApp.Query("Master Visible").Length > 0)
|
||||
RunningApp.Tap("Close Master");
|
||||
|
||||
RunningApp.Tap("Master");
|
||||
RunningApp.WaitForElement("Master Visible");
|
||||
RunningApp.Tap("Close Master");
|
||||
RunningApp.Tap("Master");
|
||||
RunningApp.WaitForElement("Master Visible");
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public override void TearDown()
|
||||
{
|
||||
|
|
|
@ -16,23 +16,98 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
|
||||
internal class EventedViewController : ChildViewController
|
||||
{
|
||||
public override void ViewWillDisappear(bool animated)
|
||||
{
|
||||
base.ViewWillDisappear(animated);
|
||||
MasterView _masterView;
|
||||
|
||||
WillDisappear?.Invoke(this, EventArgs.Empty);
|
||||
event EventHandler _didAppear;
|
||||
event EventHandler _willDisappear;
|
||||
|
||||
public EventedViewController()
|
||||
{
|
||||
_masterView = new MasterView();
|
||||
}
|
||||
|
||||
|
||||
public event EventHandler DidAppear
|
||||
{
|
||||
add
|
||||
{
|
||||
_masterView.DidAppear += value;
|
||||
_didAppear += value;
|
||||
}
|
||||
remove
|
||||
{
|
||||
_masterView.DidAppear -= value;
|
||||
_didAppear -= value;
|
||||
}
|
||||
}
|
||||
|
||||
public event EventHandler WillDisappear
|
||||
{
|
||||
add
|
||||
{
|
||||
_masterView.WillDisappear += value;
|
||||
_willDisappear += value;
|
||||
}
|
||||
remove
|
||||
{
|
||||
_masterView.WillDisappear -= value;
|
||||
_willDisappear -= value;
|
||||
}
|
||||
}
|
||||
|
||||
public override void ViewDidAppear(bool animated)
|
||||
{
|
||||
base.ViewDidAppear(animated);
|
||||
|
||||
DidAppear?.Invoke(this, EventArgs.Empty);
|
||||
_didAppear?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
public event EventHandler DidAppear;
|
||||
public override void ViewWillDisappear(bool animated)
|
||||
{
|
||||
base.ViewWillDisappear(animated);
|
||||
_willDisappear?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
public event EventHandler WillDisappear;
|
||||
public override void ViewDidDisappear(bool animated)
|
||||
{
|
||||
base.ViewDidDisappear(animated);
|
||||
_willDisappear?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
public override void LoadView()
|
||||
{
|
||||
View = _masterView;
|
||||
}
|
||||
|
||||
public class MasterView : UIView
|
||||
{
|
||||
public bool IsCollapsed => Center.X <= 0;
|
||||
bool _previousIsCollapsed = true;
|
||||
|
||||
public event EventHandler DidAppear;
|
||||
public event EventHandler WillDisappear;
|
||||
|
||||
// this only gets called on iOS12 everytime it's collapsed or expanded
|
||||
// I haven't found an override on iOS13 that gets called but it doesn't seem
|
||||
// to matter because the DidAppear and WillDisappear seem more consistent on iOS 13
|
||||
public override void LayoutSubviews()
|
||||
{
|
||||
base.LayoutSubviews();
|
||||
UpdateCollapsedSetting();
|
||||
}
|
||||
|
||||
void UpdateCollapsedSetting()
|
||||
{
|
||||
if (_previousIsCollapsed != IsCollapsed)
|
||||
{
|
||||
_previousIsCollapsed = IsCollapsed;
|
||||
|
||||
if (IsCollapsed)
|
||||
WillDisappear?.Invoke(this, EventArgs.Empty);
|
||||
else
|
||||
DidAppear?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class TabletMasterDetailRenderer : UISplitViewController, IVisualElementRenderer, IEffectControlProvider
|
||||
|
@ -45,11 +120,14 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
nfloat _masterWidth = 0;
|
||||
EventedViewController _masterController;
|
||||
MasterDetailPage _masterDetailPage;
|
||||
bool _masterVisible;
|
||||
VisualElementTracker _tracker;
|
||||
CGSize _previousSize = CGSize.Empty;
|
||||
CGSize _previousViewDidLayoutSize = CGSize.Empty;
|
||||
UISplitViewControllerDisplayMode _previousDisplayMode = UISplitViewControllerDisplayMode.Automatic;
|
||||
|
||||
Page PageController => Element as Page;
|
||||
Element ElementController => Element as Element;
|
||||
bool IsMasterVisible => !(_masterController?.View as EventedViewController.MasterView).IsCollapsed;
|
||||
|
||||
protected MasterDetailPage MasterDetailPage => _masterDetailPage ?? (_masterDetailPage = (MasterDetailPage)Element);
|
||||
|
||||
|
@ -91,7 +169,7 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
|
||||
if (_masterController != null)
|
||||
{
|
||||
_masterController.DidAppear -= MasterControllerWillAppear;
|
||||
_masterController.DidAppear -= MasterControllerDidAppear;
|
||||
_masterController.WillDisappear -= MasterControllerWillDisappear;
|
||||
}
|
||||
|
||||
|
@ -127,7 +205,7 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
|
||||
UpdateControllers();
|
||||
|
||||
_masterController.DidAppear += MasterControllerWillAppear;
|
||||
_masterController.DidAppear += MasterControllerDidAppear;
|
||||
_masterController.WillDisappear += MasterControllerWillDisappear;
|
||||
|
||||
PresentsWithGesture = MasterDetailPage.IsGestureEnabled;
|
||||
|
@ -162,6 +240,7 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
PageController?.SendDisappearing();
|
||||
}
|
||||
|
||||
|
||||
public override void ViewDidLayoutSubviews()
|
||||
{
|
||||
base.ViewDidLayoutSubviews();
|
||||
|
@ -203,6 +282,28 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
if (!detailsBounds.IsEmpty)
|
||||
MasterDetailPage.DetailBounds = new Rectangle(0, 0, detailsBounds.Width, detailsBounds.Height);
|
||||
}
|
||||
|
||||
if (_previousViewDidLayoutSize == CGSize.Empty)
|
||||
_previousViewDidLayoutSize = View.Bounds.Size;
|
||||
|
||||
// Is this being called from a rotation
|
||||
if (_previousViewDidLayoutSize != View.Bounds.Size)
|
||||
{
|
||||
_previousViewDidLayoutSize = View.Bounds.Size;
|
||||
|
||||
// make sure IsPresented matches state of Master View
|
||||
if (MasterDetailPage.CanChangeIsPresented && MasterDetailPage.IsPresented != IsMasterVisible)
|
||||
ElementController.SetValueFromRenderer(MasterDetailPage.IsPresentedProperty, IsMasterVisible);
|
||||
}
|
||||
|
||||
if(_previousDisplayMode != PreferredDisplayMode)
|
||||
{
|
||||
_previousDisplayMode = PreferredDisplayMode;
|
||||
|
||||
// make sure IsPresented matches state of Master View
|
||||
if (MasterDetailPage.CanChangeIsPresented && MasterDetailPage.IsPresented != IsMasterVisible)
|
||||
ElementController.SetValueFromRenderer(MasterDetailPage.IsPresentedProperty, IsMasterVisible);
|
||||
}
|
||||
}
|
||||
|
||||
public override void ViewDidLoad()
|
||||
|
@ -224,6 +325,8 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
return;
|
||||
|
||||
bool isPortrait = newBounds.Height > newBounds.Width;
|
||||
var previous = PreferredDisplayMode;
|
||||
|
||||
switch (masterDetailPage.MasterBehavior)
|
||||
{
|
||||
case MasterBehavior.Split:
|
||||
|
@ -243,18 +346,18 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
break;
|
||||
}
|
||||
|
||||
if (previous == PreferredDisplayMode)
|
||||
return;
|
||||
|
||||
if (!MasterDetailPage.ShouldShowSplitMode)
|
||||
MasterDetailPage.CanChangeIsPresented = true;
|
||||
|
||||
MasterDetailPage.UpdateMasterBehavior();
|
||||
|
||||
if(MasterDetailPage.CanChangeIsPresented && !MasterDetailPage.ShouldShowSplitMode)
|
||||
ElementController.SetValueFromRenderer(MasterDetailPage.IsPresentedProperty, false);
|
||||
}
|
||||
|
||||
public override void ViewWillDisappear(bool animated)
|
||||
{
|
||||
if (_masterVisible && !MasterDetailPage.ShouldShowSplitMode)
|
||||
if (IsMasterVisible && !MasterDetailPage.ShouldShowSplitMode)
|
||||
PerformButtonSelector();
|
||||
|
||||
base.ViewWillDisappear(animated);
|
||||
|
@ -271,7 +374,7 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
// I tested this code on iOS9+ and it's never called
|
||||
if (!Forms.IsiOS9OrNewer)
|
||||
{
|
||||
if (!MasterDetailPage.ShouldShowSplitMode && _masterVisible)
|
||||
if (!MasterDetailPage.ShouldShowSplitMode && IsMasterVisible)
|
||||
{
|
||||
MasterDetailPage.CanChangeIsPresented = true;
|
||||
PreferredDisplayMode = UISplitViewControllerDisplayMode.PrimaryHidden;
|
||||
|
@ -362,20 +465,23 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
public override void ViewWillTransitionToSize(CGSize toSize, IUIViewControllerTransitionCoordinator coordinator)
|
||||
{
|
||||
base.ViewWillTransitionToSize(toSize, coordinator);
|
||||
UpdateMasterBehavior(toSize);
|
||||
|
||||
if (_previousSize != toSize)
|
||||
{
|
||||
_previousSize = toSize;
|
||||
UpdateMasterBehavior(toSize);
|
||||
}
|
||||
}
|
||||
|
||||
void MasterControllerWillAppear(object sender, EventArgs e)
|
||||
void MasterControllerDidAppear(object sender, EventArgs e)
|
||||
{
|
||||
_masterVisible = true;
|
||||
if (MasterDetailPage.CanChangeIsPresented)
|
||||
if (MasterDetailPage.CanChangeIsPresented && IsMasterVisible)
|
||||
ElementController.SetValueFromRenderer(MasterDetailPage.IsPresentedProperty, true);
|
||||
}
|
||||
|
||||
void MasterControllerWillDisappear(object sender, EventArgs e)
|
||||
{
|
||||
_masterVisible = false;
|
||||
if (MasterDetailPage.CanChangeIsPresented)
|
||||
if (MasterDetailPage.CanChangeIsPresented && !IsMasterVisible)
|
||||
ElementController.SetValueFromRenderer(MasterDetailPage.IsPresentedProperty, false);
|
||||
}
|
||||
|
||||
|
@ -386,7 +492,7 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
|
||||
void ToggleMaster()
|
||||
{
|
||||
if (_masterVisible == MasterDetailPage.IsPresented || MasterDetailPage.ShouldShowSplitMode)
|
||||
if (IsMasterVisible == MasterDetailPage.IsPresented || MasterDetailPage.ShouldShowSplitMode)
|
||||
return;
|
||||
|
||||
PerformButtonSelector();
|
||||
|
|
Загрузка…
Ссылка в новой задаче