Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 47971f607a | |||
| 03a4d342a3 | |||
| 4f5abfefec | |||
| e1ee3c06e8 | |||
| 17ba704472 | |||
| e5391fa1f4 | |||
| c0647017b5 | |||
| 3686bb4b44 | |||
| 76c8ca4b20 | |||
| c53e64027b | |||
| 281504c9c6 |
@@ -409,6 +409,15 @@ class DebugTableViewController: UIViewController, UITableViewDataSource, UITable
|
||||
cell.textLabel?.text = items[indexPath.row]
|
||||
return cell
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
|
||||
return [
|
||||
UITableViewRowAction(style: .destructive, title: "Delete", handler: { (action, path) in
|
||||
self.items.remove(at: path.row)
|
||||
tableView.deleteRows(at: [path], with: .automatic)
|
||||
}),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
class DetailViewController: UIViewController {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Pod::Spec.new do |s|
|
||||
|
||||
s.name = "FloatingPanel"
|
||||
s.version = "1.2.0"
|
||||
s.version = "1.2.1"
|
||||
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.
|
||||
|
||||
@@ -33,7 +33,10 @@ class FloatingPanel: NSObject, UIGestureRecognizerDelegate, UIScrollViewDelegate
|
||||
|
||||
unowned let viewcontroller: FloatingPanelController
|
||||
|
||||
private(set) var state: FloatingPanelPosition = .tip
|
||||
private(set) var state: FloatingPanelPosition = .tip {
|
||||
didSet { viewcontroller.delegate?.floatingPanelDidChangePosition(viewcontroller) }
|
||||
}
|
||||
|
||||
private var isBottomState: Bool {
|
||||
let remains = layoutAdapter.layout.supportedPositions.filter { $0.rawValue > state.rawValue }
|
||||
return remains.count == 0
|
||||
@@ -175,7 +178,9 @@ class FloatingPanel: NSObject, UIGestureRecognizerDelegate, UIScrollViewDelegate
|
||||
|
||||
/* log.debug("shouldRecognizeSimultaneouslyWith", otherGestureRecognizer) */
|
||||
|
||||
return otherGestureRecognizer == scrollView?.panGestureRecognizer
|
||||
// all gestures of the tracking scroll view should be recognized in parallel
|
||||
// and handle them in self.handle(panGesture:)
|
||||
return scrollView?.gestureRecognizers?.contains(otherGestureRecognizer) ?? false
|
||||
}
|
||||
|
||||
public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldBeRequiredToFailBy otherGestureRecognizer: UIGestureRecognizer) -> Bool {
|
||||
@@ -183,28 +188,45 @@ class FloatingPanel: NSObject, UIGestureRecognizerDelegate, UIScrollViewDelegate
|
||||
|
||||
/* log.debug("shouldBeRequiredToFailBy", otherGestureRecognizer) */
|
||||
|
||||
// Do not begin any gestures excluding the tracking scrollView's pan gesture
|
||||
// until the pan gesture fails
|
||||
if otherGestureRecognizer == scrollView?.panGestureRecognizer {
|
||||
// The tracking scroll view's gestures should begin without waiting for the pan gesture failure.
|
||||
// `scrollView.gestureRecognizers` can contains the following gestures
|
||||
// * UIScrollViewDelayedTouchesBeganGestureRecognizer
|
||||
// * UIScrollViewPanGestureRecognizer (scrollView.panGestureRecognizer)
|
||||
// * _UIDragAutoScrollGestureRecognizer
|
||||
// * _UISwipeActionPanGestureRecognizer
|
||||
// * UISwipeDismissalGestureRecognizer
|
||||
if let scrollView = scrollView,
|
||||
let scrollGestureRecognizers = scrollView.gestureRecognizers,
|
||||
scrollGestureRecognizers.contains(otherGestureRecognizer) {
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
|
||||
// Long press gesture should begin without waiting for the pan gesture failure.
|
||||
if otherGestureRecognizer is UILongPressGestureRecognizer {
|
||||
return false
|
||||
}
|
||||
|
||||
// Do not begin any other gestures until the pan gesture fails.
|
||||
return true
|
||||
}
|
||||
|
||||
public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRequireFailureOf otherGestureRecognizer: UIGestureRecognizer) -> Bool {
|
||||
guard gestureRecognizer == panGesture else { return false }
|
||||
|
||||
/* log.debug("shouldRequireFailureOf", otherGestureRecognizer) */
|
||||
log.debug("shouldRequireFailureOf", otherGestureRecognizer)
|
||||
|
||||
// Do not begin the pan gesture until any other gestures fail except for
|
||||
// the tracking scrollView's pan gesture and other gestures.
|
||||
// Should begin the pan gesture without waiting for the tracking scroll view's gestures.
|
||||
// `scrollView.gestureRecognizers` can contains the following gestures
|
||||
// * UIScrollViewDelayedTouchesBeganGestureRecognizer
|
||||
// * UIScrollViewPanGestureRecognizer (scrollView.panGestureRecognizer)
|
||||
// * _UIDragAutoScrollGestureRecognizer
|
||||
// * _UISwipeActionPanGestureRecognizer
|
||||
// * UISwipeDismissalGestureRecognizer
|
||||
if let scrollView = scrollView {
|
||||
if scrollView.panGestureRecognizer == otherGestureRecognizer {
|
||||
return false
|
||||
}
|
||||
// For short scroll contents
|
||||
if scrollView.gestureRecognizers?.contains(otherGestureRecognizer) ?? false {
|
||||
// On short contents scroll, `_UISwipeActionPanGestureRecognizer` blocks
|
||||
// the panel's pan gesture if not returns false
|
||||
if let scrollGestureRecognizers = scrollView.gestureRecognizers,
|
||||
scrollGestureRecognizers.contains(otherGestureRecognizer) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -215,8 +237,10 @@ class FloatingPanel: NSObject, UIGestureRecognizerDelegate, UIScrollViewDelegate
|
||||
is UIRotationGestureRecognizer,
|
||||
is UIScreenEdgePanGestureRecognizer,
|
||||
is UIPinchGestureRecognizer:
|
||||
// Do not begin the pan gesture until these gestures fail
|
||||
return true
|
||||
default:
|
||||
// Should begin the pan gesture witout waiting tap/long press gestures fail
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -275,6 +299,11 @@ class FloatingPanel: NSObject, UIGestureRecognizerDelegate, UIScrollViewDelegate
|
||||
return
|
||||
}
|
||||
|
||||
if let animator = self.animator {
|
||||
animator.stopAnimation(true)
|
||||
self.animator = nil
|
||||
}
|
||||
|
||||
switch panGesture.state {
|
||||
case .began:
|
||||
panningBegan()
|
||||
@@ -299,8 +328,22 @@ class FloatingPanel: NSObject, UIGestureRecognizerDelegate, UIScrollViewDelegate
|
||||
width: surfaceView.bounds.width,
|
||||
height: FloatingPanelSurfaceView.topGrabberBarHeight * 2)
|
||||
|
||||
// When no scrollView, nothing to handle.
|
||||
guard let scrollView = scrollView else { return false }
|
||||
|
||||
// For _UISwipeActionPanGestureRecognizer
|
||||
if let scrollGestureRecognizers = scrollView.gestureRecognizers {
|
||||
for gesture in scrollGestureRecognizers {
|
||||
guard gesture.state == .began || gesture.state == .changed
|
||||
else { continue }
|
||||
|
||||
if gesture != scrollView.panGestureRecognizer {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
guard
|
||||
let scrollView = scrollView, // When no scrollView, nothing to handle.
|
||||
state == .full, // When not .full, don't scroll.
|
||||
interactionInProgress == false, // When interaction already in progress, don't scroll.
|
||||
scrollView.frame.contains(point), // When point not in scrollView, don't scroll.
|
||||
@@ -442,7 +485,6 @@ class FloatingPanel: NSObject, UIGestureRecognizerDelegate, UIScrollViewDelegate
|
||||
let targetY = layoutAdapter.positionY(for: targetPosition)
|
||||
let velocityVector = (distance != 0) ? CGVector(dx: 0, dy: max(min(velocity.y/distance, 30.0), -30.0)) : .zero
|
||||
let animator = behavior.interactionAnimator(self.viewcontroller, to: targetPosition, with: velocityVector)
|
||||
animator.isInterruptible = false // To prevent a backdrop color's punk
|
||||
animator.addAnimations { [weak self] in
|
||||
guard let self = self else { return }
|
||||
if self.state == targetPosition {
|
||||
|
||||
@@ -12,6 +12,8 @@ public protocol FloatingPanelControllerDelegate: class {
|
||||
// if it returns nil, FloatingPanelController uses the default behavior
|
||||
func floatingPanel(_ vc: FloatingPanelController, behaviorFor newCollection: UITraitCollection) -> FloatingPanelBehavior?
|
||||
|
||||
func floatingPanelDidChangePosition(_ vc: FloatingPanelController) // changed the settled position in the model layer
|
||||
|
||||
func floatingPanelDidMove(_ vc: FloatingPanelController) // any offset changes
|
||||
|
||||
// called on start of dragging (may require some time and or distance to move)
|
||||
@@ -34,6 +36,7 @@ public extension FloatingPanelControllerDelegate {
|
||||
func floatingPanel(_ vc: FloatingPanelController, behaviorFor newCollection: UITraitCollection) -> FloatingPanelBehavior? {
|
||||
return nil
|
||||
}
|
||||
func floatingPanelDidChangePosition(_ vc: FloatingPanelController) {}
|
||||
func floatingPanelDidMove(_ vc: FloatingPanelController) {}
|
||||
func floatingPanelWillBeginDragging(_ vc: FloatingPanelController) {}
|
||||
func floatingPanelDidEndDragging(_ vc: FloatingPanelController, withVelocity velocity: CGPoint, targetPosition: FloatingPanelPosition) {}
|
||||
@@ -289,6 +292,7 @@ public class FloatingPanelController: UIViewController, UIScrollViewDelegate, UI
|
||||
|
||||
self.willMove(toParent: nil)
|
||||
self.view.removeFromSuperview()
|
||||
self.backdropView.removeFromSuperview()
|
||||
self.removeFromParent()
|
||||
completion?()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user