Better detect IsCollapsed state/changes on master (#8181)

This commit is contained in:
Shane Neuville 2019-10-28 18:42:11 -06:00 коммит произвёл Samantha Houts
Родитель 2f02371116
Коммит 1ecdf97d2f
2 изменённых файлов: 168 добавлений и 26 удалений

Просмотреть файл

@ -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();