diff --git a/Sources/Core.swift b/Sources/Core.swift index f486529d..728d0b20 100644 --- a/Sources/Core.swift +++ b/Sources/Core.swift @@ -209,6 +209,9 @@ class Core: NSObject, UIGestureRecognizerDelegate { contentOffset = scrollView?.contentOffset } + if layoutAdapter.validStates.contains(state) == false { + state = layoutAdapter.initialState + } layoutAdapter.updateStaticConstraint() layoutAdapter.activateLayout(for: state, forceLayout: forceLayout) @@ -725,7 +728,6 @@ class Core: NSObject, UIGestureRecognizerDelegate { } guard shouldAttract(to: target) else { - self.state = target self.updateLayout(to: target) self.unlockScrollView() // The `floatingPanelDidEndDragging(_:willAttract:)` must be called after the state property changes. diff --git a/Sources/Layout.swift b/Sources/Layout.swift index 4aa84f2e..2118e4c6 100644 --- a/Sources/Layout.swift +++ b/Sources/Layout.swift @@ -782,12 +782,6 @@ class LayoutAdapter { NSLayoutConstraint.activate(constraint: self.fitToBoundsConstraint) } - var state = state - - if validStates.contains(state) == false { - state = layout.initialState - } - // Recalculate the intrinsic size of a content view. This is because // UIView.systemLayoutSizeFitting() returns a different size between an // on-screen and off-screen view which includes diff --git a/Tests/ControllerTests.swift b/Tests/ControllerTests.swift index 117fde91..462991cc 100644 --- a/Tests/ControllerTests.swift +++ b/Tests/ControllerTests.swift @@ -334,6 +334,36 @@ class ControllerTests: XCTestCase { fpc.move(to: .tip, animated: false) XCTAssertEqual(fpc.surfaceView.frame.height, fpc.view.bounds.height - fpc.surfaceLocation(for: .tip).y) } + + func test_switching_layout() { + final class FirstLayout: FloatingPanelLayout { + let position: FloatingPanelPosition = .bottom + let initialState: FloatingPanelState = .half + let anchors: [FloatingPanelState : FloatingPanelLayoutAnchoring] = [ + .full: FloatingPanelLayoutAnchor(absoluteInset: 16.0, edge: .top, referenceGuide: .safeArea), + .half: FloatingPanelLayoutAnchor(absoluteInset: 262, edge: .top, referenceGuide: .safeArea), + .tip: FloatingPanelLayoutAnchor(absoluteInset: 44.0, edge: .bottom, referenceGuide: .safeArea) + ] + } + final class SecondLayout: FloatingPanelLayout { + let position: FloatingPanelPosition = .bottom + let initialState: FloatingPanelState = .half + let anchors: [FloatingPanelState : FloatingPanelLayoutAnchoring] = [ + .half: FloatingPanelLayoutAnchor(absoluteInset: 262, edge: .top, referenceGuide: .safeArea) + ] + } + let fpc = FloatingPanelController() + fpc.layout = FirstLayout() + fpc.showForTest() + + fpc.move(to: .tip, animated: false) + + // Switch to another layout + fpc.layout = SecondLayout() + fpc.invalidateLayout() + + XCTAssertEqual(fpc.state, .half) + } } private class MyZombieViewController: UIViewController, FloatingPanelLayout, FloatingPanelBehavior, FloatingPanelControllerDelegate {