Compare commits

..

12 Commits

Author SHA1 Message Date
Federico Zanetello f909cd4101 ignore .swiftpm/ folder (#324) 2020-02-29 13:20:50 +09:00
Federico Zanetello 8c24aa3fc9 fix api typo (#325)
fixes floatingPanel(_ vc: FloatingPanelController, contentOffsetForPinning) name
2020-02-29 13:18:09 +09:00
Shin Yamamoto 7531d80f1c Merge pull request #323 from SCENEE/release-1.7.3
Release 1.7.3
2020-02-29 10:40:38 +09:00
Shin Yamamoto c4c1906cae Release 1.7.3 2020-02-28 21:00:44 +09:00
Shin Yamamoto 4f717c5840 update github issue template 2020-02-28 21:00:40 +09:00
Shin Yamamoto fbd83ef500 fix a run script error 2020-02-26 22:53:44 +09:00
Shin Yamamoto 2a91145366 Fix breaking content offset of the tracked scroll view (#315)
* Convert the tracked scroll view frame to the surface coordinate space
2020-02-26 22:49:51 +09:00
Shin Yamamoto f5d72aa0a5 Add failure requirements for multiple panels (#322)
* add multi panel sample
2020-02-26 22:47:52 +09:00
Shin Yamamoto 65f67c98f4 Add floatingPanel(_:contentOffsetForPinning:) delegate method (#314)
* add floatingPanel(_:contentOffsetForPinning:)
* add 'Show NavigationController' sample
* fix the initial content offset in a navigation bar with  a large text
    The content offset preservation should be applied only when
    `FloatingPanelController.contentInsetAdjustmentBehavior` is `.always`.
    This is because the library user loses control of the initial offset.
2020-02-24 11:16:10 +09:00
Shin Yamamoto 1f79c2573f Merge pull request #316 from jacksonjude/master
Minor README.md typo
2020-02-15 10:32:03 +09:00
jacksonjude bc840dde46 Minor README.md typo 2020-02-08 22:36:50 -08:00
Shin Yamamoto 57ed039857 Merge pull request #312 from SCENEE/release-1.7.2
Release 1.7.2
2020-01-30 09:29:00 +09:00
11 changed files with 203 additions and 57 deletions
+18 -5
View File
@@ -2,7 +2,7 @@
>
> Please remove this line and everything above it before submitting.
### Short description
### Description
### Expected behavior
@@ -12,16 +12,29 @@
**Code example that reproduces the issue**
**How do you display panel(s)?**
* Add as child view controllers
* Present modally
**How many panels do you displays?**
* 1
* 2+
### Environment
**Library version**
**Installation method**
- [ ] CocoaPods
- [ ] Carthage
- [ ] Git submodules
* CocoaPods
* Carthage
* Swift Package Manager
**iOS version(s)**
**Xcode version**
+3
View File
@@ -30,6 +30,9 @@ xcuserdata/
*.dSYM.zip
*.dSYM
## Swift Package Manager Specific
.swiftpm/
## Playgrounds
timeline.xctimeline
playground.xcworkspace
@@ -294,7 +294,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/usr/libexec/PlistBuddy -c \"Set :CFBundleVersion $(git rev-parse --abbrev-ref HEAD)($(git rev-parse --short HEAD))\" $SRCROOT/$INFOPLIST_FILE\n";
shellScript = "/usr/libexec/PlistBuddy -c \"Set :CFBundleVersion $(git rev-parse --abbrev-ref HEAD)($(git rev-parse --short HEAD))\" \"$SRCROOT/$INFOPLIST_FILE\"\n";
};
/* End PBXShellScriptBuildPhase section */
@@ -1,11 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="RoN-h0-uBD">
<device id="retina5_9" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="15705" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="RoN-h0-uBD">
<device id="retina5_9" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14490.49"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15706"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
@@ -13,7 +11,7 @@
<!--Navigation Controller-->
<scene sceneID="Cjh-iX-VQw">
<objects>
<navigationController id="RoN-h0-uBD" sceneMemberID="viewController">
<navigationController storyboardIdentifier="RootNavigationController" id="RoN-h0-uBD" sceneMemberID="viewController">
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" largeTitles="YES" id="hNW-5m-Omi">
<rect key="frame" x="0.0" y="44" width="375" height="96"/>
<autoresizingMask key="autoresizingMask"/>
+112 -19
View File
@@ -18,6 +18,7 @@ class SampleListViewController: UIViewController {
case showDetail
case showModal
case showPanelModal
case showMultiPanelModal
case showTabBar
case showPageView
case showPageContentView
@@ -26,6 +27,7 @@ class SampleListViewController: UIViewController {
case showIntrinsicView
case showContentInset
case showContainerMargins
case showNavigationController
var name: String {
switch self {
@@ -34,6 +36,7 @@ class SampleListViewController: UIViewController {
case .showDetail: return "Show Detail Panel"
case .showModal: return "Show Modal"
case .showPanelModal: return "Show Panel Modal"
case .showMultiPanelModal: return "Show Multi Panel Modal"
case .showTabBar: return "Show Tab Bar"
case .showPageView: return "Show Page View"
case .showPageContentView: return "Show Page Content View"
@@ -42,6 +45,7 @@ class SampleListViewController: UIViewController {
case .showIntrinsicView: return "Show Intrinsic View"
case .showContentInset: return "Show with ContentInset"
case .showContainerMargins: return "Show with ContainerMargins"
case .showNavigationController: return "Show Navigation Controller"
}
}
@@ -51,6 +55,7 @@ class SampleListViewController: UIViewController {
case .trackingTextView: return "ConsoleViewController"
case .showDetail: return "DetailViewController"
case .showModal: return "ModalViewController"
case .showMultiPanelModal: return nil
case .showPanelModal: return nil
case .showTabBar: return "TabBarViewController"
case .showPageView: return nil
@@ -60,6 +65,7 @@ class SampleListViewController: UIViewController {
case .showIntrinsicView: return "IntrinsicViewController"
case .showContentInset: return nil
case .showContainerMargins: return nil
case .showNavigationController: return "RootNavigationController"
}
}
}
@@ -80,6 +86,7 @@ class SampleListViewController: UIViewController {
tableView.dataSource = self
tableView.delegate = self
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
automaticallyAdjustsScrollViewInsets = false
let searchController = UISearchController(searchResultsController: nil)
if #available(iOS 11.0, *) {
@@ -92,11 +99,14 @@ class SampleListViewController: UIViewController {
let contentVC = DebugTableViewController()
addMainPanel(with: contentVC)
var insets = UIEdgeInsets.zero
insets.bottom += 69.0
tableView.contentInset = insets
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if #available(iOS 11.0, *) {
if let observation = navigationController?.navigationBar.observe(\.prefersLargeTitles, changeHandler: { (bar, _) in
self.tableView.reloadData()
@@ -116,15 +126,13 @@ class SampleListViewController: UIViewController {
let oldMainPanelVC = mainPanelVC
// Initialize FloatingPanelController
mainPanelVC = FloatingPanelController()
mainPanelVC.delegate = self
mainPanelVC.contentInsetAdjustmentBehavior = .always
// Initialize FloatingPanelController and add the view
mainPanelVC.surfaceView.cornerRadius = 6.0
mainPanelVC.surfaceView.shadowHidden = false
// Set a content view controller
mainPanelVC.set(contentViewController: contentVC)
// Enable tap-to-hide and removal interaction
@@ -143,6 +151,8 @@ class SampleListViewController: UIViewController {
let backdropTapGesture = UITapGestureRecognizer(target: self, action: #selector(handleBackdrop(tapGesture:)))
mainPanelVC.backdropView.addGestureRecognizer(backdropTapGesture)
case .showNavigationController:
mainPanelVC.contentInsetAdjustmentBehavior = .never
default:
break
}
@@ -160,6 +170,11 @@ class SampleListViewController: UIViewController {
mainPanelVC.track(scrollView: contentVC.tableView)
case let contentVC as NestedScrollViewController:
mainPanelVC.track(scrollView: contentVC.scrollView)
case let navVC as UINavigationController:
if let rootVC = (navVC.topViewController as? SampleListViewController) {
rootVC.loadViewIfNeeded()
mainPanelVC.track(scrollView: rootVC.tableView)
}
default:
break
}
@@ -331,6 +346,10 @@ extension SampleListViewController: UITableViewDelegate {
self.present(fpc, animated: true, completion: nil)
case .showMultiPanelModal:
let fpc = MultiPanelController()
self.present(fpc, animated: true, completion: nil)
case .showContentInset:
let contentViewController = UIViewController()
contentViewController.view.backgroundColor = .green
@@ -368,6 +387,14 @@ extension SampleListViewController: UITableViewDelegate {
}
extension SampleListViewController: FloatingPanelControllerDelegate {
func floatingPanel(_ vc: FloatingPanelController, contentOffsetForPinning trackedScrollView: UIScrollView) -> CGPoint {
if currentMenu == .showNavigationController, #available(iOSApplicationExtension 11.0, *) {
// 148.0 is the SafeArea's top value for a navigation bar with a large title.
return CGPoint(x: 0.0, y: 0.0 - trackedScrollView.contentInset.top - 148.0)
}
return CGPoint(x: 0.0, y: 0.0 - trackedScrollView.contentInset.top)
}
func floatingPanel(_ vc: FloatingPanelController, layoutFor newCollection: UITraitCollection) -> FloatingPanelLayout? {
if vc == settingsPanelVC {
return IntrinsicPanelLayout()
@@ -636,7 +663,8 @@ class InspectableViewController: UIViewController {
}
class DebugTableViewController: InspectableViewController {
weak var tableView: UITableView!
lazy var tableView = UITableView(frame: .zero, style: .plain)
lazy var buttonStackView = UIStackView()
var items: [String] = []
var itemHeight: CGFloat = 66.0
@@ -650,8 +678,6 @@ class DebugTableViewController: InspectableViewController {
override func viewDidLoad() {
super.viewDidLoad()
let tableView = UITableView(frame: .zero,
style: .plain)
view.addSubview(tableView)
tableView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
@@ -662,18 +688,17 @@ class DebugTableViewController: InspectableViewController {
])
tableView.dataSource = self
tableView.delegate = self
self.tableView = tableView
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
let stackView = UIStackView()
view.addSubview(stackView)
stackView.axis = .vertical
stackView.distribution = .fillEqually
stackView.alignment = .trailing
stackView.spacing = 10.0
stackView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(buttonStackView)
buttonStackView.axis = .vertical
buttonStackView.distribution = .fillEqually
buttonStackView.alignment = .trailing
buttonStackView.spacing = 10.0
buttonStackView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
stackView.topAnchor.constraint(equalTo: view.topAnchor, constant: 22.0),
stackView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -22.0),
buttonStackView.topAnchor.constraint(equalTo: view.topAnchor, constant: 22.0),
buttonStackView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -22.0),
])
for menu in Menu.allCases {
@@ -689,13 +714,12 @@ class DebugTableViewController: InspectableViewController {
button.addTarget(self, action: #selector(reorderItems), for: .touchUpInside)
reorderButton = button
}
stackView.addArrangedSubview(button)
buttonStackView.addArrangedSubview(button)
}
for i in 0...100 {
items.append("Items \(i)")
}
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
}
@objc func animateScroll() {
@@ -1270,3 +1294,72 @@ class SettingsViewController: InspectableViewController {
navigationController?.navigationBar.isTranslucent = sender.isOn
}
}
// MARK -: Multi Panel
import WebKit
final class MultiPanelController: FloatingPanelController, FloatingPanelControllerDelegate {
private final class FirstPanelContentViewController: UIViewController {
lazy var webView: WKWebView = WKWebView()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(webView)
webView.frame = view.bounds
webView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
webView.load(URLRequest(url: URL(string: "https://www.apple.com")!))
let vc = MultiSecondPanelController()
vc.setUpContent()
vc.addPanel(toParent: self)
}
}
private final class MultiSecondPanelController: FloatingPanelController {
private final class SecondPanelContentViewController: DebugTableViewController {}
func setUpContent() {
contentInsetAdjustmentBehavior = .never
let vc = SecondPanelContentViewController()
vc.loadViewIfNeeded()
vc.title = "Second Panel"
vc.buttonStackView.isHidden = true
let navigationController = UINavigationController(rootViewController: vc)
navigationController.navigationBar.barTintColor = .white
navigationController.navigationBar.titleTextAttributes = [
.foregroundColor: UIColor.black
]
set(contentViewController: navigationController)
self.track(scrollView: vc.tableView)
surfaceView.containerMargins = .init(top: 24.0, left: 0.0, bottom: layoutInsets.bottom, right: 0.0)
}
}
override func viewDidLoad() {
super.viewDidLoad()
delegate = self
isRemovalInteractionEnabled = true
let vc = FirstPanelContentViewController()
set(contentViewController: vc)
track(scrollView: vc.webView.scrollView)
}
private final class FirstViewLayout: FloatingPanelLayout {
let initialPosition: FloatingPanelPosition = .full
let supportedPositions: Set<FloatingPanelPosition> = [.full]
func insetFor(position: FloatingPanelPosition) -> CGFloat? {
switch position {
case .full: return 40.0
default: return nil
}
}
}
func floatingPanel(_ vc: FloatingPanelController, layoutFor newCollection: UITraitCollection) -> FloatingPanelLayout? {
return FirstViewLayout()
}
}
+1 -1
View File
@@ -1,7 +1,7 @@
Pod::Spec.new do |s|
s.name = "FloatingPanel"
s.version = "1.7.2"
s.version = "1.7.3"
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.
@@ -37,6 +37,15 @@ public protocol FloatingPanelControllerDelegate: class {
///
/// By default, any tap and long gesture recognizers are allowed to recognize gestures simultaneously.
func floatingPanel(_ vc: FloatingPanelController, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool
/// Asks the delegate for a content offset of the tracked scroll view to be pinned when a floating panel moves
///
/// If you do not implement this method, the controller uses a value of the content offset plus the content insets
/// of the tracked scroll view. Your implementation of this method can return a value for a navigation bar with a large
/// title, for example.
///
/// This method will not be called if the controller doesn't track any scroll view.
func floatingPanel(_ vc: FloatingPanelController, contentOffsetForPinning trackedScrollView: UIScrollView) -> CGPoint
}
public extension FloatingPanelControllerDelegate {
@@ -62,6 +71,9 @@ public extension FloatingPanelControllerDelegate {
func floatingPanel(_ vc: FloatingPanelController, shouldRecognizeSimultaneouslyWith gestureRecognizer: UIGestureRecognizer) -> Bool {
return false
}
func floatingPanel(_ vc: FloatingPanelController, contentOffsetForPinning trackedScrollView: UIScrollView) -> CGPoint {
return CGPoint(x: 0.0, y: 0.0 - trackedScrollView.contentInset.top)
}
}
@@ -381,13 +393,18 @@ open class FloatingPanelController: UIViewController {
private func activateLayout() {
floatingPanel.layoutAdapter.prepareLayout(in: self)
// preserve the current content offset
let contentOffset = scrollView?.contentOffset
// preserve the current content offset if contentInsetAdjustmentBehavior is `.always`
var contentOffset: CGPoint?
if contentInsetAdjustmentBehavior == .always {
contentOffset = scrollView?.contentOffset
}
floatingPanel.layoutAdapter.updateHeight()
floatingPanel.layoutAdapter.activateLayout(of: floatingPanel.state)
scrollView?.contentOffset = contentOffset ?? .zero
if let contentOffset = contentOffset {
scrollView?.contentOffset = contentOffset
}
}
// MARK: - Container view controller interface
+37 -14
View File
@@ -191,6 +191,9 @@ class FloatingPanelCore: NSObject, UIGestureRecognizerDelegate {
}
switch otherGestureRecognizer {
case is FloatingPanelPanGestureRecognizer:
// All visiable panels' pan gesture should be recognized simultaneously.
return true
case is UIPanGestureRecognizer,
is UISwipeGestureRecognizer,
is UIRotationGestureRecognizer,
@@ -210,8 +213,14 @@ class FloatingPanelCore: NSObject, UIGestureRecognizerDelegate {
}
public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldBeRequiredToFailBy otherGestureRecognizer: UIGestureRecognizer) -> Bool {
guard gestureRecognizer == panGestureRecognizer else { return false }
/* log.debug("shouldBeRequiredToFailBy", otherGestureRecognizer) */
if otherGestureRecognizer is FloatingPanelPanGestureRecognizer {
// If this panel is the farthest descendant of visiable panels,
// its ancestors' pan gesture must wait for its pan gesture to fail
if let view = otherGestureRecognizer.view, surfaceView.isDescendant(of: view) {
return true
}
}
return false
}
@@ -237,8 +246,7 @@ class FloatingPanelCore: NSObject, UIGestureRecognizerDelegate {
if grabberAreaFrame.contains(gestureRecognizer.location(in: gestureRecognizer.view)) {
return false
}
let offset = scrollView.contentOffset.y - scrollView.contentOffsetZero.y
return allowScrollPanGesture(at: CGPoint(x: 0.0, y: offset))
return allowScrollPanGesture(for: scrollView)
default:
return false
}
@@ -251,6 +259,13 @@ class FloatingPanelCore: NSObject, UIGestureRecognizerDelegate {
}
switch otherGestureRecognizer {
case is FloatingPanelPanGestureRecognizer:
// If this panel is the farthest descendant of visiable panels,
// its pan gesture does not require its ancestors' pan gesture to fail
if let view = otherGestureRecognizer.view, surfaceView.isDescendant(of: view) {
return false
}
return true
case is UIPanGestureRecognizer,
is UISwipeGestureRecognizer,
is UIRotationGestureRecognizer,
@@ -293,14 +308,13 @@ class FloatingPanelCore: NSObject, UIGestureRecognizerDelegate {
let surfaceMinY = surfaceView.presentationFrame.minY
let adapterTopY = layoutAdapter.topY
let belowTop = surfaceMinY > (adapterTopY + (1.0 / surfaceView.traitCollection.displayScale))
let offset = scrollView.contentOffset.y - scrollView.contentOffsetZero.y
log.debug("scroll gesture(\(state):\(panGesture.state)) --",
"belowTop = \(belowTop),",
"interactionInProgress = \(interactionInProgress),",
"scroll offset = \(offset),",
"scroll offset = \(scrollView.contentOffset.y),",
"location = \(location.y), velocity = \(velocity.y)")
let offset = scrollView.contentOffset.y - contentOrigin(of: scrollView).y
if belowTop {
// Scroll offset pinning
@@ -343,11 +357,11 @@ class FloatingPanelCore: NSObject, UIGestureRecognizerDelegate {
} else {
if state == layoutAdapter.topMostState {
// Hide a scroll indicator just before starting an interaction by swiping a panel down.
if velocity.y > 0, !allowScrollPanGesture(at: CGPoint(x: 0.0, y: offset)) {
if velocity.y > 0, !allowScrollPanGesture(for: scrollView) {
lockScrollView()
}
// Show a scroll indicator when an animation is interrupted at the top and content is scrolled up
if velocity.y < 0, allowScrollPanGesture(at: CGPoint(x: 0.0, y: offset)) {
if velocity.y < 0, allowScrollPanGesture(for: scrollView) {
unlockScrollView()
}
@@ -450,14 +464,15 @@ class FloatingPanelCore: NSObject, UIGestureRecognizerDelegate {
return true
}
let scrollViewFrame = scrollView.convert(scrollView.bounds, to: surfaceView)
guard
scrollView.frame.contains(initialLocation), // When initialLocation not in scrollView, don't scroll.
scrollViewFrame.contains(initialLocation), // When initialLocation not in scrollView, don't scroll.
!grabberAreaFrame.contains(point) // When point within grabber area, don't scroll.
else {
return false
}
let offset = scrollView.contentOffset.y - scrollView.contentOffsetZero.y
let offset = scrollView.contentOffset.y - contentOrigin(of: scrollView).y
// The zero offset must be excluded because the offset is usually zero
// after a panel moves from half/tip to full.
if offset > 0.0 {
@@ -683,12 +698,12 @@ class FloatingPanelCore: NSObject, UIGestureRecognizerDelegate {
initialFrame = surfaceView.frame
if state == layoutAdapter.topMostState, let scrollView = scrollView {
if grabberAreaFrame.contains(location) || scrollView.isTracking == false {
if grabberAreaFrame.contains(location) {
initialScrollOffset = scrollView.contentOffset
} else {
initialScrollOffset = scrollView.contentOffsetZero
initialScrollOffset = contentOrigin(of: scrollView)
// Fit the surface bounds to a scroll offset content by startInteraction(at:offset:)
let scrollOffsetY = (scrollView.contentOffset.y - scrollView.contentOffsetZero.y)
let scrollOffsetY = (scrollView.contentOffset.y - contentOrigin(of: scrollView).y)
if scrollOffsetY < 0 {
offset = CGPoint(x: -scrollView.contentOffset.x, y: -scrollOffsetY)
}
@@ -889,7 +904,15 @@ class FloatingPanelCore: NSObject, UIGestureRecognizerDelegate {
scrollView?.setContentOffset(contentOffset, animated: false)
}
private func allowScrollPanGesture(at contentOffset: CGPoint) -> Bool {
private func contentOrigin(of scrollView: UIScrollView) -> CGPoint {
if let vc = viewcontroller, let origin = vc.delegate?.floatingPanel(vc, contentOffsetForPinning: scrollView) {
return origin
}
return CGPoint(x: 0.0, y: 0.0 - scrollView.contentInset.top)
}
private func allowScrollPanGesture(for scrollView: UIScrollView) -> Bool {
let contentOffset = scrollView.contentOffset - contentOrigin(of: scrollView)
if state == layoutAdapter.topMostState {
return contentOffset.y <= -30.0 || contentOffset.y > 0
}
+1 -1
View File
@@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.7.2</string>
<string>1.7.3</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
</dict>
+4 -5
View File
@@ -114,9 +114,6 @@ extension UIGestureRecognizerState: CustomDebugStringConvertible {
#endif
extension UIScrollView {
var contentOffsetZero: CGPoint {
return CGPoint(x: 0.0, y: 0.0 - contentInset.top)
}
var isLocked: Bool {
return !showsVerticalScrollIndicator && !bounces && isDirectionalLockEnabled
}
@@ -133,8 +130,10 @@ extension UISpringTimingParameters {
extension CGPoint {
static var nan: CGPoint {
return CGPoint(x: CGFloat.nan,
y: CGFloat.nan)
return CGPoint(x: CGFloat.nan, y: CGFloat.nan)
}
static func - (left: CGPoint, right: CGPoint) -> CGPoint {
return CGPoint(x: left.x - right.x, y: left.y - right.y)
}
}
+2 -2
View File
@@ -36,7 +36,7 @@ The new interface displays the related contents and utilities in parallel as a u
- [Change the initial position and height](#change-the-initial-position-and-height)
- [Support your landscape layout](#support-your-landscape-layout)
- [Use Intrinsic height layout](#use-intrinsic-height-layout)
- [Specify position insets from the frame of `FloatingPanelContrller.view`, not the SafeArea](#specify-position-insets-from-the-frame-of-floatingpanelcontrllerview-not-the-safearea)
- [Specify position insets from the frame of `FloatingPanelController.view`, not the SafeArea](#specify-position-insets-from-the-frame-of-floatingpanelcontrollerview-not-the-safearea)
- [Customize the behavior with `FloatingPanelBehavior` protocol](#customize-the-behavior-with-floatingpanelbehavior-protocol)
- [Modify your floating panel's interaction](#modify-your-floating-panels-interaction)
- [Activate the rubber-band effect on the top/bottom edges](#activate-the-rubber-band-effect-on-the-topbottom-edges)
@@ -338,7 +338,7 @@ class RemovablePanelLayout: FloatingPanelIntrinsicLayout {
}
```
#### Specify position insets from the frame of `FloatingPanelContrller.view`, not the SafeArea
#### Specify position insets from the frame of `FloatingPanelController.view`, not the SafeArea
There are 2 ways. One is returning `.fromSuperview` for `FloatingPanelLayout.positionReference` in your layout.