Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b7a7e0d4ad | |||
| dc7f6d58f9 | |||
| a2a10bd0d3 | |||
| b54c8ee6ee | |||
| 08d275690a | |||
| 1c307f751e | |||
| 6f06a0f7fc | |||
| a095ace30e | |||
| a486f61f5f | |||
| 14e0abc240 | |||
| 32203c48bd | |||
| 9d6024f603 | |||
| a4dd4e48e7 | |||
| e6f7456a0f | |||
| fca79c9b0c | |||
| 4ad7f11e93 | |||
| 31faeaada3 |
+17
-7
@@ -5,10 +5,10 @@ branches:
|
||||
- next
|
||||
cache:
|
||||
directories:
|
||||
- build
|
||||
- vendor
|
||||
- /usr/local/Homebrew
|
||||
- $HOME/Library/Caches/Homebrew
|
||||
before_cache:
|
||||
- brew cleanup
|
||||
env:
|
||||
global:
|
||||
- LANG=en_US.UTF-8
|
||||
@@ -16,7 +16,17 @@ env:
|
||||
skip_cleanup: true
|
||||
jobs:
|
||||
include:
|
||||
- stage: carthage
|
||||
- stage: Build framework(swift 4.1)
|
||||
osx_image: xcode9.4
|
||||
script:
|
||||
- xcodebuild -scheme FloatingPanel clean build
|
||||
|
||||
- stage: Build framework(swift 4.2)
|
||||
osx_image: xcode10
|
||||
script:
|
||||
- xcodebuild -scheme FloatingPanel clean build
|
||||
|
||||
- stage: Carthage
|
||||
osx_image: xcode10
|
||||
before_install:
|
||||
- brew update
|
||||
@@ -24,22 +34,22 @@ jobs:
|
||||
script:
|
||||
- carthage build --no-skip-current
|
||||
|
||||
- stage: podspec
|
||||
- stage: Podspec
|
||||
osx_image: xcode10
|
||||
script:
|
||||
- pod spec lint
|
||||
|
||||
- stage: check Maps example
|
||||
- stage: Build maps example
|
||||
osx_image: xcode10
|
||||
script:
|
||||
- xcodebuild -scheme Maps -sdk iphonesimulator clean build
|
||||
|
||||
- stage: check Stocks example
|
||||
- stage: Build stocks example
|
||||
osx_image: xcode10
|
||||
script:
|
||||
- xcodebuild -scheme Stocks -sdk iphonesimulator clean build
|
||||
|
||||
- stage: check Samples example
|
||||
- stage: Build samples example
|
||||
osx_image: xcode10
|
||||
script:
|
||||
- xcodebuild -scheme Samples -sdk iphonesimulator clean build
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Pod::Spec.new do |s|
|
||||
|
||||
s.name = "FloatingPanel"
|
||||
s.version = "1.3.1"
|
||||
s.version = "1.3.2"
|
||||
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.
|
||||
@@ -13,7 +13,7 @@ The new interface displays the related contents and utilities in parallel as a u
|
||||
s.platform = :ios, "10.0"
|
||||
s.source = { :git => "https://github.com/SCENEE/FloatingPanel.git", :tag => "v#{s.version}" }
|
||||
s.source_files = "Framework/Sources/*.swift"
|
||||
s.swift_version = "4.2"
|
||||
s.swift_version = "4.0"
|
||||
s.pod_target_xcconfig = { 'SWIFT_WHOLE_MODULE_OPTIMIZATION' => 'YES', 'APPLICATION_EXTENSION_API_ONLY' => 'YES' }
|
||||
|
||||
s.framework = "UIKit"
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
54352E9821A521CA00CBCA08 /* FloatingPanelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54352E9721A521CA00CBCA08 /* FloatingPanelView.swift */; };
|
||||
54352E9621A51A2500CBCA08 /* FloatingPanelTransitioning.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54352E9521A51A2500CBCA08 /* FloatingPanelTransitioning.swift */; };
|
||||
54352E9821A521CA00CBCA08 /* FloatingPanelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54352E9721A521CA00CBCA08 /* FloatingPanelView.swift */; };
|
||||
5450EEE421646DF500135936 /* FloatingPanelBehavior.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5450EEE321646DF500135936 /* FloatingPanelBehavior.swift */; };
|
||||
545DB9CB2151169500CA77B8 /* FloatingPanel.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 545DB9C12151169500CA77B8 /* FloatingPanel.framework */; };
|
||||
545DB9D02151169500CA77B8 /* ViewTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 545DB9CF2151169500CA77B8 /* ViewTests.swift */; };
|
||||
@@ -34,8 +34,8 @@
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
54352E9721A521CA00CBCA08 /* FloatingPanelView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FloatingPanelView.swift; sourceTree = "<group>"; };
|
||||
54352E9521A51A2500CBCA08 /* FloatingPanelTransitioning.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FloatingPanelTransitioning.swift; sourceTree = "<group>"; };
|
||||
54352E9721A521CA00CBCA08 /* FloatingPanelView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FloatingPanelView.swift; sourceTree = "<group>"; };
|
||||
5450EEE321646DF500135936 /* FloatingPanelBehavior.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FloatingPanelBehavior.swift; sourceTree = "<group>"; };
|
||||
545DB9C12151169500CA77B8 /* FloatingPanel.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = FloatingPanel.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
545DB9C42151169500CA77B8 /* FloatingPanelController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FloatingPanelController.h; sourceTree = "<group>"; };
|
||||
@@ -406,7 +406,7 @@
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 4.2;
|
||||
SWIFT_VERSION = 4.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
@@ -432,7 +432,7 @@
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.scenee.FloatingPanel;
|
||||
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_VERSION = 4.2;
|
||||
SWIFT_VERSION = 4.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Release;
|
||||
|
||||
@@ -101,7 +101,7 @@ class FloatingPanel: NSObject, UIGestureRecognizerDelegate, UIScrollViewDelegate
|
||||
}
|
||||
|
||||
animator.addAnimations { [weak self] in
|
||||
guard let self = self else { return }
|
||||
guard let `self` = self else { return }
|
||||
|
||||
self.updateLayout(to: to)
|
||||
self.state = to
|
||||
@@ -360,6 +360,12 @@ class FloatingPanel: NSObject, UIGestureRecognizerDelegate, UIScrollViewDelegate
|
||||
|
||||
private func panningEnd(with translation: CGPoint, velocity: CGPoint) {
|
||||
log.debug("panningEnd")
|
||||
|
||||
guard state != .hidden else {
|
||||
log.debug("Already hidden")
|
||||
return
|
||||
}
|
||||
|
||||
if interactionInProgress == false {
|
||||
initialFrame = surfaceView.frame
|
||||
}
|
||||
@@ -381,9 +387,9 @@ class FloatingPanel: NSObject, UIGestureRecognizerDelegate, UIScrollViewDelegate
|
||||
|
||||
viewcontroller.delegate?.floatingPanelDidEndDraggingToRemove(viewcontroller, withVelocity: velocity)
|
||||
self.startRemovalAnimation(with: velocityVector) { [weak self] in
|
||||
guard let self = self else { return }
|
||||
guard let `self` = self else { return }
|
||||
self.viewcontroller.dismiss(animated: false, completion: { [weak self] in
|
||||
guard let self = self else { return }
|
||||
guard let `self` = self else { return }
|
||||
self.viewcontroller.delegate?.floatingPanelDidEndRemove(self.viewcontroller)
|
||||
})
|
||||
}
|
||||
@@ -436,16 +442,20 @@ class FloatingPanel: NSObject, UIGestureRecognizerDelegate, UIScrollViewDelegate
|
||||
|
||||
viewcontroller.delegate?.floatingPanelWillBeginDragging(viewcontroller)
|
||||
|
||||
viewcontroller.contentViewController?.view?.constraints.forEach({ (const) in
|
||||
switch viewcontroller.contentViewController?.layoutGuide.bottomAnchor {
|
||||
case const.firstAnchor:
|
||||
(const.secondItem as? UIView)?.disableAutoLayout()
|
||||
case const.secondAnchor:
|
||||
(const.firstItem as? UIView)?.disableAutoLayout()
|
||||
default:
|
||||
break
|
||||
}
|
||||
})
|
||||
if state == .full {
|
||||
viewcontroller.contentViewController?.view?.constraints.forEach({ (const) in
|
||||
switch viewcontroller.contentViewController?.layoutGuide.bottomAnchor {
|
||||
case const.firstAnchor:
|
||||
(const.secondItem as? UIView)?.disableAutoLayout()
|
||||
const.isActive = false
|
||||
case const.secondAnchor:
|
||||
(const.firstItem as? UIView)?.disableAutoLayout()
|
||||
const.isActive = false
|
||||
default:
|
||||
break
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
interactionInProgress = true
|
||||
}
|
||||
@@ -459,16 +469,20 @@ class FloatingPanel: NSObject, UIGestureRecognizerDelegate, UIScrollViewDelegate
|
||||
lockScrollView()
|
||||
}
|
||||
|
||||
viewcontroller.contentViewController?.view?.constraints.forEach({ (const) in
|
||||
switch viewcontroller.contentViewController?.layoutGuide.bottomAnchor {
|
||||
case const.firstAnchor:
|
||||
(const.secondItem as? UIView)?.enableAutoLayout()
|
||||
case const.secondAnchor:
|
||||
(const.firstItem as? UIView)?.enableAutoLayout()
|
||||
default:
|
||||
break
|
||||
}
|
||||
})
|
||||
if state == .full {
|
||||
viewcontroller.contentViewController?.view?.constraints.forEach({ (const) in
|
||||
switch viewcontroller.contentViewController?.layoutGuide.bottomAnchor {
|
||||
case const.firstAnchor:
|
||||
(const.secondItem as? UIView)?.enableAutoLayout()
|
||||
const.isActive = true
|
||||
case const.secondAnchor:
|
||||
(const.firstItem as? UIView)?.enableAutoLayout()
|
||||
const.isActive = true
|
||||
default:
|
||||
break
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private func getCurrentY(from rect: CGRect, with translation: CGPoint) -> CGFloat {
|
||||
@@ -497,7 +511,7 @@ class FloatingPanel: NSObject, UIGestureRecognizerDelegate, UIScrollViewDelegate
|
||||
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.addAnimations { [weak self] in
|
||||
guard let self = self else { return }
|
||||
guard let `self` = self else { return }
|
||||
if self.state == targetPosition {
|
||||
self.surfaceView.frame.origin.y = targetY
|
||||
self.layoutAdapter.setBackdropAlpha(of: targetPosition)
|
||||
@@ -507,7 +521,7 @@ class FloatingPanel: NSObject, UIGestureRecognizerDelegate, UIScrollViewDelegate
|
||||
self.state = targetPosition
|
||||
}
|
||||
animator.addCompletion { [weak self] pos in
|
||||
guard let self = self else { return }
|
||||
guard let `self` = self else { return }
|
||||
guard
|
||||
self.interactionInProgress == false,
|
||||
animator == self.animator,
|
||||
@@ -616,7 +630,7 @@ class FloatingPanel: NSObject, UIGestureRecognizerDelegate, UIScrollViewDelegate
|
||||
// Distance travelled after decelerating to zero velocity at a constant rate.
|
||||
// Refer to the slides p176 of [Designing Fluid Interfaces](https://developer.apple.com/videos/play/wwdc2018/803/)
|
||||
private func project(initialVelocity: CGFloat) -> CGFloat {
|
||||
let decelerationRate = UIScrollView.DecelerationRate.normal.rawValue
|
||||
let decelerationRate = UIScrollViewDecelerationRateNormal
|
||||
return (initialVelocity / 1000.0) * decelerationRate / (1.0 - decelerationRate)
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +51,8 @@ public extension FloatingPanelControllerDelegate {
|
||||
func floatingPanel(_ vc: FloatingPanelController, shouldRecognizeSimultaneouslyWith gestureRecognizer: UIGestureRecognizer) -> Bool { return false }
|
||||
}
|
||||
|
||||
public enum FloatingPanelPosition: Int, CaseIterable {
|
||||
|
||||
public enum FloatingPanelPosition: Int {
|
||||
case full
|
||||
case half
|
||||
case tip
|
||||
@@ -69,7 +70,11 @@ public class FloatingPanelController: UIViewController, UIScrollViewDelegate, UI
|
||||
}
|
||||
|
||||
/// The delegate of the floating panel controller object.
|
||||
public weak var delegate: FloatingPanelControllerDelegate?
|
||||
public weak var delegate: FloatingPanelControllerDelegate?{
|
||||
didSet{
|
||||
didUpdateDelegate()
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the surface view managed by the controller object. It's the same as `self.view`.
|
||||
public var surfaceView: FloatingPanelSurfaceView! {
|
||||
@@ -133,14 +138,15 @@ public class FloatingPanelController: UIViewController, UIScrollViewDelegate, UI
|
||||
private var safeAreaInsetsObservation: NSKeyValueObservation?
|
||||
private let modalTransition = FloatingPanelModalTransition()
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
required public init?(coder aDecoder: NSCoder) {
|
||||
super.init(coder: aDecoder)
|
||||
setUp()
|
||||
}
|
||||
|
||||
/// Initialize a newly created floating panel controller.
|
||||
public init() {
|
||||
public init(delegate: FloatingPanelControllerDelegate? = nil) {
|
||||
super.init(nibName: nil, bundle: nil)
|
||||
self.delegate = delegate
|
||||
setUp()
|
||||
}
|
||||
|
||||
@@ -155,6 +161,11 @@ public class FloatingPanelController: UIViewController, UIScrollViewDelegate, UI
|
||||
behavior: fetchBehavior(for: self.traitCollection))
|
||||
}
|
||||
|
||||
private func didUpdateDelegate(){
|
||||
floatingPanel.layoutAdapter.layout = fetchLayout(for: traitCollection)
|
||||
floatingPanel.behavior = fetchBehavior(for: self.traitCollection)
|
||||
}
|
||||
|
||||
// MARK:- Overrides
|
||||
|
||||
/// Creates the view that the controller manages.
|
||||
@@ -269,7 +280,7 @@ public class FloatingPanelController: UIViewController, UIScrollViewDelegate, UI
|
||||
// 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) { [weak self] (vc, chaneg) in
|
||||
guard let self = self else { return }
|
||||
guard let `self` = self else { return }
|
||||
self.update(safeAreaInsets: vc.layoutInsets)
|
||||
}
|
||||
} else {
|
||||
@@ -312,7 +323,8 @@ public class FloatingPanelController: UIViewController, UIScrollViewDelegate, UI
|
||||
parent.view.addSubview(self.view)
|
||||
}
|
||||
|
||||
parent.addChild(self)
|
||||
parent.addChildViewController(self)
|
||||
|
||||
|
||||
view.frame = parent.view.bounds // Needed for a correct safe area configuration
|
||||
view.translatesAutoresizingMaskIntoConstraints = false
|
||||
@@ -324,8 +336,8 @@ public class FloatingPanelController: UIViewController, UIScrollViewDelegate, UI
|
||||
])
|
||||
|
||||
show(animated: animated) { [weak self] in
|
||||
guard let self = self else { return }
|
||||
self.didMove(toParent: parent)
|
||||
guard let `self` = self else { return }
|
||||
self.didMove(toParentViewController: self)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -340,10 +352,10 @@ public class FloatingPanelController: UIViewController, UIScrollViewDelegate, UI
|
||||
}
|
||||
|
||||
hide(animated: animated) { [weak self] in
|
||||
guard let self = self else { return }
|
||||
self.willMove(toParent: nil)
|
||||
guard let `self` = self else { return }
|
||||
self.willMove(toParentViewController: nil)
|
||||
self.view.removeFromSuperview()
|
||||
self.removeFromParent()
|
||||
self.removeFromParentViewController()
|
||||
completion?()
|
||||
}
|
||||
}
|
||||
@@ -361,16 +373,16 @@ public class FloatingPanelController: UIViewController, UIScrollViewDelegate, UI
|
||||
/// Sets the view controller responsible for the content portion of the floating panel..
|
||||
public func set(contentViewController: UIViewController?) {
|
||||
if let vc = _contentViewController {
|
||||
vc.willMove(toParent: nil)
|
||||
vc.willMove(toParentViewController: nil)
|
||||
vc.view.removeFromSuperview()
|
||||
vc.removeFromParent()
|
||||
vc.removeFromParentViewController()
|
||||
}
|
||||
|
||||
if let vc = contentViewController {
|
||||
addChild(vc)
|
||||
addChildViewController(vc)
|
||||
let surfaceView = floatingPanel.surfaceView
|
||||
surfaceView.add(contentView: vc.view)
|
||||
vc.didMove(toParent: self)
|
||||
vc.didMove(toParentViewController: self)
|
||||
}
|
||||
|
||||
_contentViewController = contentViewController
|
||||
@@ -408,7 +420,7 @@ public class FloatingPanelController: UIViewController, UIScrollViewDelegate, UI
|
||||
if #available(iOS 11.0, *) {
|
||||
scrollView.contentInsetAdjustmentBehavior = .never
|
||||
} else {
|
||||
children.forEach { (vc) in
|
||||
childViewControllers.forEach { (vc) in
|
||||
vc.automaticallyAdjustsScrollViewInsets = false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,7 +226,7 @@ class FloatingPanelLayoutAdapter {
|
||||
}
|
||||
|
||||
func updateIntrinsicHeight() {
|
||||
let fittingSize = UIView.layoutFittingCompressedSize
|
||||
let fittingSize = UILayoutFittingCompressedSize
|
||||
var intrinsicHeight = surfaceView.contentView?.systemLayoutSizeFitting(fittingSize).height ?? 0.0
|
||||
var safeAreaBottom: CGFloat = 0.0
|
||||
if #available(iOS 11.0, *) {
|
||||
|
||||
@@ -70,7 +70,7 @@ public class FloatingPanelSurfaceView: UIView {
|
||||
render()
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
required public init?(coder aDecoder: NSCoder) {
|
||||
super.init(coder: aDecoder)
|
||||
render()
|
||||
}
|
||||
|
||||
@@ -49,6 +49,10 @@ class FloatingPanelPresentationController: UIPresentationController {
|
||||
let fpView = fpc.view
|
||||
else { fatalError() }
|
||||
|
||||
/*
|
||||
* Layout the views managed by `FloatingPanelController` here for the
|
||||
* sake of the presentation and disimissal modally from the controller.
|
||||
*/
|
||||
containerView.addSubview(fpView)
|
||||
fpView.frame = containerView.bounds
|
||||
fpView.translatesAutoresizingMaskIntoConstraints = false
|
||||
@@ -59,6 +63,10 @@ class FloatingPanelPresentationController: UIPresentationController {
|
||||
fpView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor, constant: 0.0),
|
||||
])
|
||||
|
||||
// Forward touch events to the presenting view controller
|
||||
(fpView as? FloatingPanelPassThroughView)?.eventForwardingView = presentingViewController.view
|
||||
|
||||
// Set tap-to-dimiss in the backdrop view
|
||||
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleBackdrop(tapGesture:)))
|
||||
fpc.backdropView.addGestureRecognizer(tapGesture)
|
||||
}
|
||||
@@ -83,6 +91,9 @@ class FloatingPanelModalPresentTransition: NSObject, UIViewControllerAnimatedTra
|
||||
let fpc = transitionContext.viewController(forKey: .to) as? FloatingPanelController
|
||||
else { fatalError() }
|
||||
|
||||
// Must set the container's bounds to the floating panel view
|
||||
fpc.view?.frame = transitionContext.containerView.bounds
|
||||
|
||||
fpc.show(animated: true) {
|
||||
transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
|
||||
}
|
||||
|
||||
@@ -6,13 +6,14 @@
|
||||
import UIKit
|
||||
|
||||
class FloatingPanelPassThroughView: UIView {
|
||||
public weak var eventForwardingView: UIView?
|
||||
public override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
||||
let view = super.hitTest(point, with: event)
|
||||
switch view {
|
||||
case is FloatingPanelPassThroughView:
|
||||
return nil
|
||||
let hitView = super.hitTest(point, with: event)
|
||||
switch hitView {
|
||||
case self:
|
||||
return eventForwardingView?.hitTest(self.convert(point, to: eventForwardingView), with: event)
|
||||
default:
|
||||
return view
|
||||
return hitView
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ public class GrabberHandleView: UIView {
|
||||
public static let barColor = UIColor(displayP3Red: 0.76, green: 0.77, blue: 0.76, alpha: 1.0)
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
required public init?(coder aDecoder: NSCoder) {
|
||||
super.init(coder: aDecoder)
|
||||
render()
|
||||
}
|
||||
|
||||
@@ -73,7 +73,8 @@ extension UIView {
|
||||
}
|
||||
}
|
||||
|
||||
extension UIGestureRecognizer.State: CustomDebugStringConvertible {
|
||||
|
||||
extension UIGestureRecognizerState: CustomDebugStringConvertible {
|
||||
public var debugDescription: String {
|
||||
switch self {
|
||||
case .began: return "Began"
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
[](https://cocoapods.org/pods/FloatingPanel)
|
||||
[](https://github.com/Carthage/Carthage)
|
||||
[](https://cocoapods.org/pods/FloatingPanel)
|
||||
[](https://swift.org/)
|
||||
[](https://swift.org/)
|
||||
|
||||
# FloatingPanel
|
||||
|
||||
Reference in New Issue
Block a user