diff --git a/Sources/Controller.swift b/Sources/Controller.swift index b2042534..45bedaa7 100644 --- a/Sources/Controller.swift +++ b/Sources/Controller.swift @@ -551,7 +551,7 @@ open class FloatingPanelController: UIViewController { addChild(vc) let surfaceView = floatingPanel.surfaceView - surfaceView.set(contentView: vc.view) + surfaceView.set(contentView: vc.view, mode: contentMode) vc.didMove(toParent: self) } diff --git a/Sources/SurfaceView.swift b/Sources/SurfaceView.swift index 8d16816f..d546aa7a 100644 --- a/Sources/SurfaceView.swift +++ b/Sources/SurfaceView.swift @@ -408,12 +408,11 @@ public class SurfaceView: UIView { containerView.layer.borderWidth = appearance.borderWidth } - func set(contentView: UIView) { + func set(contentView: UIView, mode: FloatingPanelController.ContentMode) { containerView.addSubview(contentView) self.contentView = contentView /* contentView.frame = bounds */ // MUST NOT: Because the top safe area inset of a content VC will be incorrect. contentView.translatesAutoresizingMaskIntoConstraints = false - let topConstraint = contentView.topAnchor.constraint(equalTo: topAnchor, constant: containerMargins.top + contentPadding.top) let leftConstraint = contentView.leftAnchor.constraint(equalTo: leftAnchor, constant: containerMargins.left + contentPadding.left) let rightConstraint = rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: containerMargins.right + contentPadding.right) @@ -424,9 +423,15 @@ public class SurfaceView: UIView { rightConstraint, bottomConstraint, ].map { - $0.priority = .required - 1; + switch mode { + case .static: + $0.priority = .required + // The reason why this priority is set to .required - 1 is #359, which fixed #294. + case .fitToBounds: + $0.priority = .required - 1 + } $0.identifier = "FloatingPanel-surface-content" - return $0; + return $0 }) self.contentViewTopConstraint = topConstraint self.contentViewLeftConstraint = leftConstraint diff --git a/Tests/SurfaceViewTests.swift b/Tests/SurfaceViewTests.swift index a86028bb..cd4e5511 100644 --- a/Tests/SurfaceViewTests.swift +++ b/Tests/SurfaceViewTests.swift @@ -48,35 +48,37 @@ class SurfaceViewTests: XCTestCase { } func test_surfaceView_contentView() { - XCTContext.runActivity(named: "Bottom sheet") { _ in + for (position, mode, line) in [ + (.top, .static, #line), + (.top, .fitToBounds, #line), + (.bottom, .static, #line), + (.bottom, .fitToBounds, #line), + ] as [(FloatingPanelPosition, FloatingPanelController.ContentMode, UInt)] { let surface = SurfaceView(frame: CGRect(x: 0.0, y: 0.0, width: 320.0, height: 480.0)) + surface.position = position surface.layoutIfNeeded() let contentView = UIView() - surface.set(contentView: contentView) + surface.set(contentView: contentView, mode: mode) let height = surface.bounds.height * 2 surface.containerOverflow = height surface.setNeedsLayout() surface.layoutIfNeeded() - XCTAssertEqual(surface.contentView?.frame ?? .zero, surface.bounds) - } - - XCTContext.runActivity(named: "Top sheet") { _ in - let surface = SurfaceView(frame: CGRect(x: 0.0, y: 0.0, width: 320.0, height: 480.0)) - surface.position = .top - surface.layoutIfNeeded() - let contentView = UIView() - surface.set(contentView: contentView) - - let height = surface.bounds.height * 2 - surface.containerOverflow = height - surface.setNeedsLayout() - surface.layoutIfNeeded() - XCTAssertEqual(surface.containerView.frame, CGRect(x: 0.0, y: -height, width: 320.0, height: 480.0 * 3)) - XCTAssertEqual(surface.convert(surface.contentView?.frame ?? .zero, from: surface.containerView), - surface.bounds) + switch position { + case .top: + XCTAssertEqual(surface.containerView.frame, + CGRect(x: 0.0, y: -height, width: 320.0, height: 480.0 * 3), + line: line) + XCTAssertEqual(surface.convert(surface.contentView?.frame ?? .zero, from: surface.containerView), + surface.bounds, + line: line) + case .bottom: + XCTAssertEqual(surface.contentView?.frame ?? .zero, surface.bounds, line: line) + default: + break + } } } @@ -140,46 +142,45 @@ class SurfaceViewTests: XCTestCase { } func test_surfaceView_contentInsets() { - XCTContext.runActivity(named: "Top sheet") { _ in + for (position, mode, line) in [ + (.top, .static, #line), + (.top, .fitToBounds, #line), + (.bottom, .static, #line), + (.bottom, .fitToBounds, #line), + ] as [(FloatingPanelPosition, FloatingPanelController.ContentMode, UInt)] { let surface = SurfaceView(frame: CGRect(x: 0.0, y: 0.0, width: 320.0, height: 480.0)) - surface.position = .top + surface.position = position let contentView = UIView() - surface.set(contentView: contentView) + surface.set(contentView: contentView, mode: mode) surface.layoutIfNeeded() - XCTAssertEqual(surface.contentView?.frame ?? .zero, surface.bounds) + XCTAssertEqual(surface.contentView?.frame ?? .zero, surface.bounds, line: line) surface.contentPadding = UIEdgeInsets(top: 16.0, left: 16.0, bottom: 16.0, right: 16.0) surface.setNeedsLayout() surface.layoutIfNeeded() - XCTAssertEqual(surface.contentView?.frame ?? .zero, surface.bounds.inset(by: surface.contentPadding)) + XCTAssertEqual(surface.contentView?.frame ?? .zero, surface.bounds.inset(by: surface.contentPadding), line: line) } - XCTContext.runActivity(named: "Bottom sheet") { _ in + } + + func test_surfaceView_containerMargins_and_contentInsets() { + for (mode, line) in [ + (.static, #line), + (.fitToBounds, #line), + ] as [(FloatingPanelController.ContentMode, UInt)] { let surface = SurfaceView(frame: CGRect(x: 0.0, y: 0.0, width: 320.0, height: 480.0)) let contentView = UIView() - surface.set(contentView: contentView) + surface.set(contentView: contentView, mode: mode) surface.layoutIfNeeded() - XCTAssertEqual(surface.contentView?.frame ?? .zero, surface.bounds) + XCTAssertEqual(surface.contentView?.frame ?? .zero, surface.bounds, line: line) + surface.containerMargins = UIEdgeInsets(top: 16.0, left: 16.0, bottom: 16.0, right: 16.0) surface.contentPadding = UIEdgeInsets(top: 16.0, left: 16.0, bottom: 16.0, right: 16.0) surface.setNeedsLayout() surface.layoutIfNeeded() - XCTAssertEqual(surface.contentView?.frame ?? .zero, surface.bounds.inset(by: surface.contentPadding)) + XCTAssertEqual(surface.containerView.frame, surface.bounds.inset(by: surface.containerMargins), line: line) + XCTAssertEqual(surface.contentView?.frame ?? .zero, surface.containerView.bounds.inset(by: surface.contentPadding), line: line) } } - func test_surfaceView_containerMargins_and_contentInsets() { - let surface = SurfaceView(frame: CGRect(x: 0.0, y: 0.0, width: 320.0, height: 480.0)) - let contentView = UIView() - surface.set(contentView: contentView) - surface.layoutIfNeeded() - XCTAssertEqual(surface.contentView?.frame ?? .zero, surface.bounds) - surface.containerMargins = UIEdgeInsets(top: 16.0, left: 16.0, bottom: 16.0, right: 16.0) - surface.contentPadding = UIEdgeInsets(top: 16.0, left: 16.0, bottom: 16.0, right: 16.0) - surface.setNeedsLayout() - surface.layoutIfNeeded() - XCTAssertEqual(surface.containerView.frame, surface.bounds.inset(by: surface.containerMargins)) - XCTAssertEqual(surface.contentView?.frame ?? .zero, surface.containerView.bounds.inset(by: surface.contentPadding)) - } - - func test_surfaceView_cornderRaduis() { + func test_surfaceView_cornerRadius() { let surface = SurfaceView(frame: CGRect(x: 0.0, y: 0.0, width: 320.0, height: 480.0)) XCTAssert(surface.containerView.layer.cornerRadius == 0.0) XCTAssert(surface.containerView.layer.masksToBounds == false)