Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ca7596e1ca | |||
| 007f9af3eb | |||
| da4e1d26d3 | |||
| 2ce1375ce7 | |||
| 28c384aa0d | |||
| 9c71a47d9b | |||
| 8903e4e610 | |||
| 5634de2eee | |||
| 1957ae3919 | |||
| a4f8c0528c | |||
| e4548b26bd | |||
| d540b1ddde | |||
| aaeb752911 | |||
| 966caad519 | |||
| a62c3a23dc | |||
| 7bbc3d5910 | |||
| e2afb1e22f | |||
| 8cca1178fd | |||
| a09a0e9e32 | |||
| 43c76faa20 | |||
| 5787a350ab | |||
| 9abb80de64 | |||
| 7d90458d99 | |||
| 5d5f14acd8 | |||
| bed519f0c0 | |||
| 7c47e2e20e |
@@ -27,7 +27,7 @@
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
</view>
|
||||
<blurEffect style="light"/>
|
||||
<blurEffect style="prominent"/>
|
||||
</visualEffectView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
@@ -232,7 +232,7 @@
|
||||
<constraint firstItem="Zcj-SE-gb8" firstAttribute="leading" secondItem="ED1-gT-FBj" secondAttribute="leading" id="wMb-L2-Z0W"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<blurEffect style="extraLight"/>
|
||||
<blurEffect style="prominent"/>
|
||||
</visualEffectView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
|
||||
@@ -274,12 +274,12 @@ class SearchHeaderView: UIView {
|
||||
|
||||
extension UISearchBar {
|
||||
func setSearchText(fontSize: CGFloat) {
|
||||
#if swift(>=5.1) // Xcode 11 or later
|
||||
if #available(iOS 13, *) {
|
||||
let font = searchTextField.font
|
||||
searchTextField.font = font?.withSize(fontSize)
|
||||
#else
|
||||
} else {
|
||||
let textField = value(forKey: "_searchField") as! UITextField
|
||||
textField.font = textField.font?.withSize(fontSize)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ class SampleListViewController: UIViewController {
|
||||
case showModal
|
||||
case showPanelModal
|
||||
case showMultiPanelModal
|
||||
case showPanelInSheetModal
|
||||
case showTabBar
|
||||
case showPageView
|
||||
case showPageContentView
|
||||
@@ -37,6 +38,7 @@ class SampleListViewController: UIViewController {
|
||||
case .showModal: return "Show Modal"
|
||||
case .showPanelModal: return "Show Panel Modal"
|
||||
case .showMultiPanelModal: return "Show Multi Panel Modal"
|
||||
case .showPanelInSheetModal: return "Show Panel in Sheet Modal"
|
||||
case .showTabBar: return "Show Tab Bar"
|
||||
case .showPageView: return "Show Page View"
|
||||
case .showPageContentView: return "Show Page Content View"
|
||||
@@ -56,6 +58,7 @@ class SampleListViewController: UIViewController {
|
||||
case .showDetail: return "DetailViewController"
|
||||
case .showModal: return "ModalViewController"
|
||||
case .showMultiPanelModal: return nil
|
||||
case .showPanelInSheetModal: return nil
|
||||
case .showPanelModal: return nil
|
||||
case .showTabBar: return "TabBarViewController"
|
||||
case .showPageView: return nil
|
||||
@@ -350,6 +353,20 @@ extension SampleListViewController: UITableViewDelegate {
|
||||
let fpc = MultiPanelController()
|
||||
self.present(fpc, animated: true, completion: nil)
|
||||
|
||||
case .showPanelInSheetModal:
|
||||
let fpc = FloatingPanelController()
|
||||
let contentVC = UIViewController()
|
||||
fpc.set(contentViewController: contentVC)
|
||||
fpc.delegate = self
|
||||
|
||||
fpc.surfaceView.cornerRadius = 38.5
|
||||
fpc.surfaceView.shadowHidden = false
|
||||
fpc.isRemovalInteractionEnabled = true
|
||||
|
||||
let mvc = UIViewController()
|
||||
mvc.view.backgroundColor = UIColor(displayP3Red: 2/255, green: 184/255, blue: 117/255, alpha: 1.0)
|
||||
fpc.addPanel(toParent: mvc)
|
||||
self.present(mvc, animated: true, completion: nil)
|
||||
case .showContentInset:
|
||||
let contentViewController = UIViewController()
|
||||
contentViewController.view.backgroundColor = .green
|
||||
@@ -865,8 +882,7 @@ class ModalViewController: UIViewController, FloatingPanelControllerDelegate {
|
||||
|
||||
var isNewlayout: Bool = false
|
||||
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
override func viewDidLoad() {
|
||||
// Initialize FloatingPanelController
|
||||
fpc = FloatingPanelController()
|
||||
fpc.delegate = self
|
||||
@@ -886,8 +902,8 @@ class ModalViewController: UIViewController, FloatingPanelControllerDelegate {
|
||||
fpc.addPanel(toParent: self, belowView: safeAreaView)
|
||||
}
|
||||
|
||||
override func viewWillDisappear(_ animated: Bool) {
|
||||
super.viewWillDisappear(animated)
|
||||
override func viewDidDisappear(_ animated: Bool) {
|
||||
super.viewDidDisappear(animated)
|
||||
// Remove FloatingPanel from a view
|
||||
fpc.removePanelFromParent(animated: false)
|
||||
}
|
||||
@@ -948,20 +964,15 @@ class TabBarContentViewController: UIViewController {
|
||||
}
|
||||
}
|
||||
}
|
||||
var fpc: FloatingPanelController!
|
||||
lazy var fpc = FloatingPanelController()
|
||||
var consoleVC: DebugTextViewController!
|
||||
|
||||
var threeLayout: ThreeTabBarPanelLayout!
|
||||
var tab3Mode: Tab3Mode = .changeAutoLayout
|
||||
var switcherLabel: UILabel!
|
||||
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
// Initialize FloatingPanelController
|
||||
fpc = FloatingPanelController()
|
||||
override func viewDidLoad() {
|
||||
fpc.delegate = self
|
||||
|
||||
// Initialize FloatingPanelController and add the view
|
||||
fpc.surfaceView.cornerRadius = 6.0
|
||||
fpc.surfaceView.shadowHidden = false
|
||||
|
||||
@@ -1011,12 +1022,6 @@ class TabBarContentViewController: UIViewController {
|
||||
fpc.updateLayout()
|
||||
}
|
||||
|
||||
override func viewWillDisappear(_ animated: Bool) {
|
||||
super.viewWillDisappear(animated)
|
||||
// Remove FloatingPanel from a view
|
||||
fpc.removePanelFromParent(animated: false)
|
||||
}
|
||||
|
||||
// MARK: - Action
|
||||
|
||||
@IBAction func close(sender: UIButton) {
|
||||
@@ -1350,15 +1355,26 @@ final class MultiPanelController: FloatingPanelController, FloatingPanelControll
|
||||
|
||||
private final class FirstViewLayout: FloatingPanelLayout {
|
||||
let initialPosition: FloatingPanelPosition = .full
|
||||
let supportedPositions: Set<FloatingPanelPosition> = [.full]
|
||||
let supportedPositions: Set<FloatingPanelPosition> = [.full, .half]
|
||||
func insetFor(position: FloatingPanelPosition) -> CGFloat? {
|
||||
switch position {
|
||||
case .full: return 40.0
|
||||
case .half: return 200.0
|
||||
default: return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final class FirstViewBehavior: FloatingPanelBehavior {
|
||||
func shouldProjectMomentum(_ fpc: FloatingPanelController, for proposedTargetPosition: FloatingPanelPosition) -> Bool {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
func floatingPanel(_ vc: FloatingPanelController, behaviorFor newCollection: UITraitCollection) -> FloatingPanelBehavior? {
|
||||
return FirstViewBehavior()
|
||||
}
|
||||
|
||||
func floatingPanel(_ vc: FloatingPanelController, layoutFor newCollection: UITraitCollection) -> FloatingPanelLayout? {
|
||||
return FirstViewLayout()
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Pod::Spec.new do |s|
|
||||
|
||||
s.name = "FloatingPanel"
|
||||
s.version = "1.7.3"
|
||||
s.version = "1.7.6"
|
||||
s.summary = "FloatingPanel is a clean and easy-to-use UI component of a floating panel interface."
|
||||
s.description = <<-DESC
|
||||
FloatingPanel is a clean and easy-to-use UI component for a new interface introduced in Apple Maps, Shortcuts and Stocks app.
|
||||
|
||||
@@ -371,7 +371,6 @@ open class FloatingPanelController: UIViewController {
|
||||
switch contentInsetAdjustmentBehavior {
|
||||
case .always:
|
||||
scrollView?.contentInset = adjustedContentInsets
|
||||
scrollView?.scrollIndicatorInsets = adjustedContentInsets
|
||||
default:
|
||||
break
|
||||
}
|
||||
@@ -422,9 +421,11 @@ open class FloatingPanelController: UIViewController {
|
||||
// inset's update expectedly.
|
||||
// 2. The safe area top inset can be variable on the large title navigation bar(iOS11+).
|
||||
// That's why it needs the observation to keep `adjustedContentInsets` correct.
|
||||
safeAreaInsetsObservation = self.observe(\.view.safeAreaInsets, options: [.initial, .new, .old]) { [weak self] (vc, change) in
|
||||
guard change.oldValue != change.newValue else { return }
|
||||
self?.update(safeAreaInsets: vc.layoutInsets)
|
||||
safeAreaInsetsObservation = self.view.observe(\.safeAreaInsets, options: [.initial, .new, .old]) { [weak self] (_, change) in
|
||||
// Use `self.view.safeAreaInsets` becauese `change.newValue` can be nil in particular case when
|
||||
// is reported in https://github.com/SCENEE/FloatingPanel/issues/330
|
||||
guard let `self` = self, change.oldValue != self.view.safeAreaInsets else { return }
|
||||
self.update(safeAreaInsets: self.view.safeAreaInsets)
|
||||
}
|
||||
} else {
|
||||
// KVOs for topLayoutGuide & bottomLayoutGuide are not effective.
|
||||
@@ -669,7 +670,8 @@ public extension UIViewController {
|
||||
}
|
||||
// Call dismiss(animated:completion:) to FloatingPanelController directly
|
||||
if let fpc = self as? FloatingPanelController {
|
||||
if fpc.presentingViewController != nil {
|
||||
// When a panel is presented modally and it's not a child view controller of the presented view controller.
|
||||
if fpc.presentingViewController != nil, fpc.parent == nil {
|
||||
self.fp_original_dismiss(animated: flag, completion: completion)
|
||||
} else {
|
||||
fpc.removePanelFromParent(animated: flag, completion: completion)
|
||||
|
||||
@@ -97,7 +97,7 @@ class FloatingPanelCore: NSObject, UIGestureRecognizerDelegate {
|
||||
}
|
||||
|
||||
private func move(from: FloatingPanelPosition, to: FloatingPanelPosition, animated: Bool, completion: (() -> Void)? = nil) {
|
||||
assert(layoutAdapter.isValid(to), "Can't move to '\(to)' position because it's not valid in the layout")
|
||||
assert(layoutAdapter.validPositions.contains(to), "Can't move to '\(to)' position because it's not valid in the layout")
|
||||
guard let vc = viewcontroller else {
|
||||
completion?()
|
||||
return
|
||||
@@ -221,6 +221,11 @@ class FloatingPanelCore: NSObject, UIGestureRecognizerDelegate {
|
||||
return true
|
||||
}
|
||||
}
|
||||
if #available(iOS 11.0, *),
|
||||
otherGestureRecognizer.name == "_UISheetInteractionBackgroundDismissRecognizer" {
|
||||
// The dismiss gesture of a sheet modal should not begin until the pan gesture fails.
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -271,6 +276,11 @@ class FloatingPanelCore: NSObject, UIGestureRecognizerDelegate {
|
||||
is UIRotationGestureRecognizer,
|
||||
is UIScreenEdgePanGestureRecognizer,
|
||||
is UIPinchGestureRecognizer:
|
||||
if #available(iOS 11.0, *),
|
||||
otherGestureRecognizer.name == "_UISheetInteractionBackgroundDismissRecognizer" {
|
||||
// Should begin the pan gesture without waiting the dismiss gesture of a sheet modal.
|
||||
return false
|
||||
}
|
||||
// Do not begin the pan gesture until these gestures fail
|
||||
return true
|
||||
default:
|
||||
@@ -607,16 +617,24 @@ class FloatingPanelCore: NSObject, UIGestureRecognizerDelegate {
|
||||
|
||||
endInteraction(for: targetPosition)
|
||||
|
||||
if isRemovalInteractionEnabled, isBottomState {
|
||||
let velocityVector = (distance != 0) ? CGVector(dx: 0, dy: min(velocity.y/distance, behavior.removalVelocity)) : .zero
|
||||
if isRemovalInteractionEnabled {
|
||||
let velocityVector: CGVector
|
||||
if distance == 0 {
|
||||
velocityVector = .zero
|
||||
} else {
|
||||
let dy = min(velocity.y / abs(distance), behavior.removalVelocity)
|
||||
velocityVector = CGVector(dx: 0, dy: dy)
|
||||
}
|
||||
// `velocityVector` will be replaced by just a velocity(not vector) when FloatingPanelRemovalInteraction will be added.
|
||||
if shouldStartRemovalAnimation(with: velocityVector), let vc = viewcontroller {
|
||||
vc.delegate?.floatingPanelDidEndDraggingToRemove(vc, withVelocity: velocity)
|
||||
let animationVector = CGVector(dx: abs(velocityVector.dx), dy: abs(velocityVector.dy))
|
||||
startRemovalAnimation(vc, with: animationVector) { [weak self] in
|
||||
self?.finishRemovalAnimation()
|
||||
if behavior.shouldProjectMomentum(vc, for: targetPosition) || isBottomState {
|
||||
vc.delegate?.floatingPanelDidEndDraggingToRemove(vc, withVelocity: velocity)
|
||||
let animationVector = CGVector(dx: abs(velocityVector.dx), dy: abs(velocityVector.dy))
|
||||
startRemovalAnimation(vc, with: animationVector) { [weak self] in
|
||||
self?.finishRemovalAnimation()
|
||||
}
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@@ -755,7 +773,7 @@ class FloatingPanelCore: NSObject, UIGestureRecognizerDelegate {
|
||||
|
||||
vc.delegate?.floatingPanelWillBeginDecelerating(vc)
|
||||
|
||||
let velocityVector = (distance != 0) ? CGVector(dx: 0, dy: abs(velocity.y)/distance) : .zero
|
||||
let velocityVector = (distance != 0) ? CGVector(dx: 0, dy: velocity.y / distance) : .zero
|
||||
let animator = behavior.interactionAnimator(vc, to: targetPosition, with: velocityVector)
|
||||
animator.addAnimations { [weak self] in
|
||||
guard let `self` = self, let vc = self.viewcontroller else { return }
|
||||
@@ -809,7 +827,7 @@ class FloatingPanelCore: NSObject, UIGestureRecognizerDelegate {
|
||||
private func distance(to targetPosition: FloatingPanelPosition) -> CGFloat {
|
||||
let currentY = surfaceView.frame.minY
|
||||
let targetY = layoutAdapter.positionY(for: targetPosition)
|
||||
return CGFloat(abs(currentY - targetY))
|
||||
return CGFloat(targetY - currentY)
|
||||
}
|
||||
|
||||
// Distance travelled after decelerating to zero velocity at a constant rate.
|
||||
|
||||
@@ -211,6 +211,10 @@ class FloatingPanelLayoutAdapter {
|
||||
return layout.supportedPositions
|
||||
}
|
||||
|
||||
var validPositions: Set<FloatingPanelPosition> {
|
||||
return supportedPositions.union([.hidden])
|
||||
}
|
||||
|
||||
var topMostState: FloatingPanelPosition {
|
||||
return supportedPositions.sorted(by: { $0.rawValue < $1.rawValue }).first ?? .hidden
|
||||
}
|
||||
@@ -398,8 +402,8 @@ class FloatingPanelLayoutAdapter {
|
||||
// unsatisfiable constraints
|
||||
|
||||
if self.interactiveTopConstraint == nil {
|
||||
// Actiavate `interactiveTopConstraint` for `fitToBounds` mode.
|
||||
// It goes throught this path when the pan gesture state jumps
|
||||
// Activate `interactiveTopConstraint` for `fitToBounds` mode.
|
||||
// It goes through this path when the pan gesture state jumps
|
||||
// from .begin to .end.
|
||||
startInteraction(at: state)
|
||||
}
|
||||
@@ -453,7 +457,7 @@ class FloatingPanelLayoutAdapter {
|
||||
case .fromSuperview:
|
||||
ret = topY
|
||||
}
|
||||
return max(ret, 0.0) // The top boundary is equal to the related topAnchor.
|
||||
return ret
|
||||
}()
|
||||
let bottomMostConst: CGFloat = {
|
||||
var ret: CGFloat = 0.0
|
||||
@@ -464,7 +468,7 @@ class FloatingPanelLayoutAdapter {
|
||||
case .fromSuperview:
|
||||
ret = _bottomY
|
||||
}
|
||||
return min(ret, surfaceView.superview!.bounds.height)
|
||||
return ret
|
||||
}()
|
||||
let minConst = allowsTopBuffer ? topMostConst - layout.topInteractionBuffer : topMostConst
|
||||
let maxConst = bottomMostConst + layout.bottomInteractionBuffer
|
||||
@@ -516,7 +520,7 @@ class FloatingPanelLayoutAdapter {
|
||||
|
||||
setBackdropAlpha(of: state)
|
||||
|
||||
if isValid(state) == false {
|
||||
if validPositions.contains(state) == false {
|
||||
state = layout.initialPosition
|
||||
}
|
||||
|
||||
@@ -538,10 +542,6 @@ class FloatingPanelLayoutAdapter {
|
||||
activateInteractiveLayout(of: state)
|
||||
}
|
||||
|
||||
func isValid(_ state: FloatingPanelPosition) -> Bool {
|
||||
return supportedPositions.union([.hidden]).contains(state)
|
||||
}
|
||||
|
||||
private func layoutSurfaceIfNeeded() {
|
||||
#if !TEST
|
||||
guard surfaceView.window != nil else { return }
|
||||
@@ -560,8 +560,8 @@ class FloatingPanelLayoutAdapter {
|
||||
private func checkLayoutConsistance() {
|
||||
// Verify layout configurations
|
||||
assert(supportedPositions.count > 0)
|
||||
assert(supportedPositions.contains(layout.initialPosition),
|
||||
"Does not include an initial position (\(layout.initialPosition)) in supportedPositions (\(supportedPositions))")
|
||||
assert(validPositions.contains(layout.initialPosition),
|
||||
"Does not include an initial position (\(layout.initialPosition)) in (\(validPositions))")
|
||||
|
||||
if layout is FloatingPanelIntrinsicLayout {
|
||||
assert(layout.insetFor(position: .full) == nil, "Return `nil` for full position on FloatingPanelIntrinsicLayout")
|
||||
|
||||
@@ -228,6 +228,7 @@ public class FloatingPanelSurfaceView: UIView {
|
||||
let rightConstraint = rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: containerMargins.right + contentInsets.right)
|
||||
let heightPadding = containerMargins.top + containerMargins.bottom + contentInsets.top + contentInsets.bottom
|
||||
let heightConstraint = contentView.heightAnchor.constraint(equalTo: heightAnchor, constant: -heightPadding)
|
||||
heightConstraint.priority = UILayoutPriority(999)
|
||||
NSLayoutConstraint.activate([
|
||||
topConstraint,
|
||||
leftConstraint,
|
||||
|
||||
@@ -47,8 +47,15 @@ class FloatingPanelPresentationController: UIPresentationController {
|
||||
|
||||
override func containerViewWillLayoutSubviews() {
|
||||
guard
|
||||
let fpc = presentedViewController as? FloatingPanelController
|
||||
else { fatalError() }
|
||||
let fpc = presentedViewController as? FloatingPanelController,
|
||||
/**
|
||||
This condition fixes https://github.com/SCENEE/FloatingPanel/issues/369.
|
||||
The issue is that this method is called in presenting a
|
||||
UIImagePickerViewController and then a FloatingPanelController
|
||||
view is added unnecessarily.
|
||||
*/
|
||||
fpc.presentedViewController == nil
|
||||
else { return }
|
||||
|
||||
/*
|
||||
* Layout the views managed by `FloatingPanelController` here for the
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.7.3</string>
|
||||
<string>1.7.6</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||
</dict>
|
||||
|
||||
@@ -195,6 +195,43 @@ class FloatingPanelLayoutTests: XCTestCase {
|
||||
fpc.floatingPanel.layoutAdapter.endInteraction(at: fpc.position)
|
||||
}
|
||||
|
||||
func test_updateInteractiveTopConstraintWithMinusInsets() {
|
||||
class FloatingPanelLayoutMinusInsets: FloatingPanelTestLayout {
|
||||
let initialPosition: FloatingPanelPosition = .full
|
||||
let supportedPositions: Set<FloatingPanelPosition> = [.tip, .full]
|
||||
func insetFor(position: FloatingPanelPosition) -> CGFloat? {
|
||||
switch position {
|
||||
case .full, .tip: return -200
|
||||
default: return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
let delegate = FloatingPanelTestDelegate()
|
||||
delegate.layout = FloatingPanelLayoutMinusInsets()
|
||||
fpc.delegate = delegate
|
||||
fpc.showForTest()
|
||||
fpc.floatingPanel.layoutAdapter.startInteraction(at: fpc.position)
|
||||
|
||||
let fullPos = fpc.originYOfSurface(for: .full)
|
||||
let tipPos = fpc.originYOfSurface(for: .tip)
|
||||
let current = fpc.surfaceView.frame.minY
|
||||
|
||||
var next: CGFloat
|
||||
fpc.floatingPanel.layoutAdapter.updateInteractiveTopConstraint(diff: -100.0, allowsTopBuffer: false, with: fpc.behavior)
|
||||
next = fpc.surfaceView.frame.minY
|
||||
XCTAssertEqual(next, current)
|
||||
|
||||
fpc.floatingPanel.layoutAdapter.updateInteractiveTopConstraint(diff: -100.0, allowsTopBuffer: true, with: fpc.behavior)
|
||||
next = fpc.surfaceView.frame.minY
|
||||
XCTAssertEqual(next, fullPos - fpc.layout.topInteractionBuffer)
|
||||
|
||||
fpc.floatingPanel.layoutAdapter.updateInteractiveTopConstraint(diff: tipPos - fullPos + 100.0, allowsTopBuffer: true, with: fpc.behavior)
|
||||
next = fpc.surfaceView.frame.minY
|
||||
XCTAssertEqual(next, tipPos + fpc.layout.bottomInteractionBuffer)
|
||||
|
||||
fpc.floatingPanel.layoutAdapter.endInteraction(at: fpc.position)
|
||||
}
|
||||
|
||||
func test_positionReference() {
|
||||
fpc = CustomSafeAreaFloatingPanelController()
|
||||
fpc.loadViewIfNeeded()
|
||||
|
||||
@@ -138,13 +138,6 @@ class ViewController: UIViewController, FloatingPanelControllerDelegate {
|
||||
// Add and show the views managed by the `FloatingPanelController` object to self.view.
|
||||
fpc.addPanel(toParent: self)
|
||||
}
|
||||
|
||||
override func viewWillDisappear(_ animated: Bool) {
|
||||
super.viewWillDisappear(animated)
|
||||
|
||||
// Remove the views managed by the `FloatingPanelController` object from self.view.
|
||||
fpc.removePanelFromParent()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -447,7 +440,7 @@ The feature can be used for these 2 kind panels
|
||||
You can disable the pan gesture recognizer directly
|
||||
|
||||
```swift
|
||||
fpc.panGestureRecognizer.isEnable = false
|
||||
fpc.panGestureRecognizer.isEnabled = false
|
||||
```
|
||||
|
||||
Or use this `FloatingPanelControllerDelegate` method.
|
||||
|
||||
Reference in New Issue
Block a user