From 7a1cbf99d4b35d913b31843fd4ac0910415a2e81 Mon Sep 17 00:00:00 2001 From: Shin Yamamoto Date: Fri, 28 Jun 2019 20:23:10 +0900 Subject: [PATCH 1/2] Rename setUpLayout to activateLayout --- Framework/Sources/FloatingPanelController.swift | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Framework/Sources/FloatingPanelController.swift b/Framework/Sources/FloatingPanelController.swift index 97d0871..4497523 100644 --- a/Framework/Sources/FloatingPanelController.swift +++ b/Framework/Sources/FloatingPanelController.swift @@ -221,7 +221,7 @@ open class FloatingPanelController: UIViewController, UIScrollViewDelegate, UIGe // Change layout for a new trait collection reloadLayout(for: newCollection) - setUpLayout() + activateLayout() floatingPanel.behavior = fetchBehavior(for: newCollection) } @@ -257,7 +257,7 @@ open class FloatingPanelController: UIViewController, UIScrollViewDelegate, UIGe // Prevent an infinite loop on iOS 10: setUpLayout() -> viewDidLayoutSubviews() -> setUpLayout() preSafeAreaInsets = safeAreaInsets - setUpLayout() + activateLayout() switch contentInsetAdjustmentBehavior { case .always: @@ -282,7 +282,7 @@ open class FloatingPanelController: UIViewController, UIScrollViewDelegate, UIGe } } - private func setUpLayout() { + private func activateLayout() { // preserve the current content offset let contentOffset = scrollView?.contentOffset @@ -298,7 +298,7 @@ open class FloatingPanelController: UIViewController, UIScrollViewDelegate, UIGe public func show(animated: Bool = false, completion: (() -> Void)? = nil) { // Must apply the current layout here reloadLayout(for: traitCollection) - setUpLayout() + activateLayout() if #available(iOS 11.0, *) { // Must track the safeAreaInsets of `self.view` to update the layout. @@ -513,7 +513,7 @@ open class FloatingPanelController: UIViewController, UIScrollViewDelegate, UIGe /// animation block. public func updateLayout() { reloadLayout(for: traitCollection) - setUpLayout() + activateLayout() } /// Returns the y-coordinate of the point at the origin of the surface view. From c10186e50a5de26b88d72ea08827c2a18ebe0edb Mon Sep 17 00:00:00 2001 From: Shin Yamamoto Date: Sat, 29 Jun 2019 07:41:27 +0900 Subject: [PATCH 2/2] Prevent an unexpected layout update on iOS13 On iOS13, UITraitCollection.userInterfaceStyle can be changed from .light to .dark when an app transitions to the background. --- .../Sources/FloatingPanelController.swift | 22 +++++++++++-------- Framework/Sources/UIExtensions.swift | 9 ++++++++ .../Tests/FloatingPanelControllerTests.swift | 19 +++++++++++++++- 3 files changed, 40 insertions(+), 10 deletions(-) diff --git a/Framework/Sources/FloatingPanelController.swift b/Framework/Sources/FloatingPanelController.swift index 4497523..5154cbb 100644 --- a/Framework/Sources/FloatingPanelController.swift +++ b/Framework/Sources/FloatingPanelController.swift @@ -196,7 +196,7 @@ open class FloatingPanelController: UIViewController, UIScrollViewDelegate, UIGe self.view = view as UIView } - open override func viewDidLayoutSubviews() { + open override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() if #available(iOS 11.0, *) {} else { @@ -207,7 +207,7 @@ open class FloatingPanelController: UIViewController, UIScrollViewDelegate, UIGe } } - open override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { + open override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { super.viewWillTransition(to: size, with: coordinator) if view.translatesAutoresizingMaskIntoConstraints { @@ -216,14 +216,9 @@ open class FloatingPanelController: UIViewController, UIScrollViewDelegate, UIGe } } - open override func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator) { + open override func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator) { super.willTransition(to: newCollection, with: coordinator) - - // Change layout for a new trait collection - reloadLayout(for: newCollection) - activateLayout() - - floatingPanel.behavior = fetchBehavior(for: newCollection) + self.prepare(for: newCollection) } open override func viewWillDisappear(_ animated: Bool) { @@ -231,6 +226,15 @@ open class FloatingPanelController: UIViewController, UIScrollViewDelegate, UIGe safeAreaInsetsObservation = nil } + // MARK:- Internals + func prepare(for newCollection: UITraitCollection) { + guard newCollection.shouldUpdateLayout(from: traitCollection) else { return } + // Change a layout & behavior for a new trait collection + reloadLayout(for: newCollection) + activateLayout() + floatingPanel.behavior = fetchBehavior(for: newCollection) + } + // MARK:- Privates private func fetchLayout(for traitCollection: UITraitCollection) -> FloatingPanelLayout { diff --git a/Framework/Sources/UIExtensions.swift b/Framework/Sources/UIExtensions.swift index afa0a4b..a33139b 100644 --- a/Framework/Sources/UIExtensions.swift +++ b/Framework/Sources/UIExtensions.swift @@ -124,3 +124,12 @@ extension CGPoint { y: CGFloat.nan) } } + +extension UITraitCollection { + func shouldUpdateLayout(from previous: UITraitCollection) -> Bool { + return previous.horizontalSizeClass != horizontalSizeClass + || previous.verticalSizeClass != verticalSizeClass + || previous.preferredContentSizeCategory != preferredContentSizeCategory + || previous.layoutDirection != layoutDirection + } +} diff --git a/Framework/Tests/FloatingPanelControllerTests.swift b/Framework/Tests/FloatingPanelControllerTests.swift index adf800a..9758b95 100644 --- a/Framework/Tests/FloatingPanelControllerTests.swift +++ b/Framework/Tests/FloatingPanelControllerTests.swift @@ -28,7 +28,6 @@ class FloatingPanelControllerTests: XCTestCase { func test_addPanel() { guard let rootVC = UIApplication.shared.keyWindow?.rootViewController else { fatalError() } - let fpc = FloatingPanelController() fpc.addPanel(toParent: rootVC) @@ -39,6 +38,24 @@ class FloatingPanelControllerTests: XCTestCase { waitRunLoop(secs: 1.0) XCTAssert(fpc.surfaceView.frame.minY == (fpc.view.bounds.height - fpc.layoutInsets.bottom) - fpc.layout.insetFor(position: .tip)!) } + + @available(iOS 12.0, *) + func test_updateLayout_willTransition() { + class MyDelegate: FloatingPanelControllerDelegate { + func floatingPanel(_ vc: FloatingPanelController, layoutFor newCollection: UITraitCollection) -> FloatingPanelLayout? { + if newCollection.userInterfaceStyle == .dark { + XCTFail() + } + return nil + } + } + let myDelegate = MyDelegate() + let fpc = FloatingPanelController(delegate: myDelegate) + let traitCollection = UITraitCollection(traitsFrom: [fpc.traitCollection, + UITraitCollection(userInterfaceStyle: .dark)]) + XCTAssertEqual(traitCollection.userInterfaceStyle, .dark) + fpc.prepare(for: traitCollection) + } } func waitRunLoop(secs: TimeInterval = 0) {