Compare commits

..

11 Commits

Author SHA1 Message Date
Shin Yamamoto 1e6cb7b1ad Release v1.2.3 2018-12-07 16:50:08 +09:00
Shin Yamamoto 8ba4ce36a1 Merge pull request #75 from SCENEE/fix-animation-wobbling
The default interaction animator should be uninterruptible
2018-12-05 16:01:56 +09:00
Shin Yamamoto cf60b09225 Fix invalid backdrop alpha
The bug was found when I commented out `animator.startAnimation()`.
2018-12-05 14:08:31 +09:00
Shin Yamamoto 427ec45d42 Let the default interaction animator be uninterruptible
Because an interruptible animator causes a wobbling at the animation start.
when a user flick a panel quickly to move to full position nearby the position.
2018-12-05 13:56:43 +09:00
Shin Yamamoto 4db648ad25 Merge pull request #72 from SCENEE/release-v1.2.2
Release v1.2.2
2018-12-03 12:27:47 +09:00
Shin Yamamoto 0bb8342873 Release v1.2.2 2018-12-03 09:25:09 +09:00
Shin Yamamoto d4f2a88fdf Merge pull request #71 from SCENEE/fix-bugs
Fix scroll tracking bugs
2018-12-01 15:45:41 +09:00
Shin Yamamoto af45d39841 Fix panning at grabber Area 2018-12-01 12:36:47 +09:00
Shin Yamamoto 66f5b0b210 Fix an invalid content offset on height change 2018-12-01 11:08:33 +09:00
Shin Yamamoto 4a3b79f1b4 Update README 2018-11-29 13:06:27 +09:00
Shin Yamamoto 12a100def8 Merge pull request #68 from SCENEE/release-1.2.1
Release v1.2.1
2018-11-26 13:20:24 +09:00
5 changed files with 77 additions and 18 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
Pod::Spec.new do |s|
s.name = "FloatingPanel"
s.version = "1.2.1"
s.version = "1.2.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.
+20 -10
View File
@@ -245,6 +245,14 @@ class FloatingPanel: NSObject, UIGestureRecognizerDelegate, UIScrollViewDelegate
}
}
var grabberAreaFrame: CGRect {
let grabberAreaFrame = CGRect(x: surfaceView.bounds.origin.x,
y: surfaceView.bounds.origin.y,
width: surfaceView.bounds.width,
height: FloatingPanelSurfaceView.topGrabberBarHeight * 2)
return grabberAreaFrame
}
// MARK: - Gesture handling
private let offsetThreshold: CGFloat = 5.0 // Optimal value from testing
@objc func handle(panGesture: UIPanGestureRecognizer) {
@@ -266,8 +274,14 @@ class FloatingPanel: NSObject, UIGestureRecognizerDelegate, UIScrollViewDelegate
if surfaceView.frame.minY > layoutAdapter.topY {
switch state {
case .full:
// Prevent over scrolling from scroll top in moving the panel from full.
scrollView.contentOffset.y = scrollView.contentOffsetZero.y
let point = panGesture.location(in: surfaceView)
if grabberAreaFrame.contains(point) {
// Preserve the current content offset in moving from full.
scrollView.contentOffset.y = initialScrollOffset.y
} else {
// Prevent over scrolling in moving from full.
scrollView.contentOffset.y = scrollView.contentOffsetZero.y
}
case .half, .tip:
guard scrollView.isDecelerating == false else {
// Don't fix the scroll offset in animating the panel to half and tip.
@@ -299,7 +313,7 @@ class FloatingPanel: NSObject, UIGestureRecognizerDelegate, UIScrollViewDelegate
return
}
if let animator = self.animator {
if let animator = self.animator, animator.isInterruptible {
animator.stopAnimation(true)
self.animator = nil
}
@@ -323,11 +337,6 @@ class FloatingPanel: NSObject, UIGestureRecognizerDelegate, UIScrollViewDelegate
}
private func shouldScrollViewHandleTouch(_ scrollView: UIScrollView?, point: CGPoint, velocity: CGPoint) -> Bool {
let grabberBarFrame = CGRect(x: surfaceView.bounds.origin.x,
y: surfaceView.bounds.origin.y,
width: surfaceView.bounds.width,
height: FloatingPanelSurfaceView.topGrabberBarHeight * 2)
// When no scrollView, nothing to handle.
guard let scrollView = scrollView else { return false }
@@ -347,7 +356,7 @@ class FloatingPanel: NSObject, UIGestureRecognizerDelegate, UIScrollViewDelegate
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.
!grabberBarFrame.contains(point) // When point within grabber area, don't scroll.
!grabberAreaFrame.contains(point) // When point within grabber area, don't scroll.
else {
return false
}
@@ -482,6 +491,7 @@ class FloatingPanel: NSObject, UIGestureRecognizerDelegate, UIScrollViewDelegate
}
private func startAnimation(to targetPosition: FloatingPanelPosition, at distance: CGFloat, with velocity: CGPoint) {
log.debug("startAnimation", targetPosition, distance, velocity)
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)
@@ -558,7 +568,7 @@ class FloatingPanel: NSObject, UIGestureRecognizerDelegate, UIScrollViewDelegate
}
return currentY > middleY ? .tip : .half
case .half:
return translation.y >= 0 ? .tip : .full
return currentY > middleY ? .tip : .full
case .tip:
if translation.y >= 0 {
return .tip
@@ -85,7 +85,9 @@ public extension FloatingPanelBehavior {
class FloatingPanelDefaultBehavior: FloatingPanelBehavior {
func interactionAnimator(_ fpc: FloatingPanelController, to targetPosition: FloatingPanelPosition, with velocity: CGVector) -> UIViewPropertyAnimator {
let timing = timeingCurve(with: velocity)
return UIViewPropertyAnimator(duration: 0, timingParameters: timing)
let animator = UIViewPropertyAnimator(duration: 0, timingParameters: timing)
animator.isInterruptible = false
return animator
}
private func timeingCurve(with velocity: CGVector) -> UITimingCurveProvider {
@@ -198,7 +198,13 @@ public class FloatingPanelController: UIViewController, UIScrollViewDelegate, UI
}
private func update(safeAreaInsets: UIEdgeInsets) {
// preserve the current content offset
let contentOffset = scrollView?.contentOffset
floatingPanel.safeAreaInsets = safeAreaInsets
scrollView?.contentOffset = contentOffset ?? .zero
switch contentInsetAdjustmentBehavior {
case .always:
scrollView?.contentInset = adjustedContentInsets
+47 -6
View File
@@ -24,14 +24,16 @@ The new interface displays the related contents and utilities in parallel as a u
- [Carthage](#carthage)
- [Getting Started](#getting-started)
- [Usage](#usage)
- [Customize the layout of a floating panel with `FloatingPanelLayout` protocol](#customize-the-layout-of-a-floating-panel-with--floatingpanellayout-protocol)
- [Customize the layout with `FloatingPanelLayout` protocol](#customize-the-layout-with-floatingpanellayout-protocol)
- [Change the initial position and height](#change-the-initial-position-and-height)
- [Support your landscape layout](#support-your-landscape-layout)
- [Customize the behavior with `FloatingPanelBehavior` protocol](#customize-the-behavior-with-floatingpanelbehavior-protocol)
- [Modify your floating panel's interaction](#modify-your-floating-panels-interaction)
- [Use a custom grabber handle](#use-a-custom-grabber-handle)
- [Add tap gestures to the surface or backdrop views](#add-tap-gestures-to-the-surface-or-backdrop-views)
- [Create an additional floating panel for a detail](#create-an-additional-floating-panel-for-a-detail)
- [Move a position with an animation](#move-a-position-with-an-animation)
- [Make your contents correspond with a floating panel behavior](#make-your-contents-correspond-with-a-floating-panel-behavior)
- [Work your contents together with a floating panel behavior](#work-your-contents-together-with-a-floating-panel-behavior)
- [Notes](#notes)
- ['Show' or 'Show Detail' Segues from `FloatingPanelController`'s content view controller](#show-or-show-detail-segues-from-floatingpanelcontrollers-content-view-controller)
- [FloatingPanelSurfaceView's issue on iOS 10](#floatingpanelsurfaceviews-issue-on-ios-10)
@@ -119,7 +121,7 @@ class ViewController: UIViewController, FloatingPanelControllerDelegate {
## Usage
### Customize the layout of a floating panel with `FloatingPanelLayout` protocol
### Customize the layout with `FloatingPanelLayout` protocol
#### Change the initial position and height
@@ -211,6 +213,45 @@ class FloatingPanelStocksBehavior: FloatingPanelBehavior {
}
```
### Use a custom grabber handle
```swift
class ViewController: UIViewController {
...
override func viewDidLoad() {
...
let myGrabberHandleView = MyGrabberHandleView()
fpc.surfaceView.grabberHandle.isHidden = true
fpc.surfaceView.addSubview(myGrabberHandleView)
}
...
}
```
### Add tap gestures to the surface or backdrop views
```swift
class ViewController: UIViewController, FloatingPanelControllerDelegate {
...
override func viewDidLoad() {
...
surfaceTapGesture = UITapGestureRecognizer(target: self, action: #selector(handleSurface(tapGesture:)))
fpc.surfaceView.addGestureRecognizer(surfaceTapGesture)
backdropTapGesture = UITapGestureRecognizer(target: self, action: #selector(handleBackdrop(tapGesture:)))
fpc.backdropView.addGestureRecognizer(backdropTapGesture)
surfaceTapGesture.isEnabled = (fpc.position == .tip)
...
}
...
// Enable `surfaceTapGesture` only at `tip` position
func floatingPanelDidChangePosition(_ vc: FloatingPanelController) {
surfaceTapGesture.isEnabled = (vc.position == .tip)
}
}
```
### Create an additional floating panel for a detail
```swift
@@ -257,7 +298,7 @@ In the following example, I move a floating panel to full or half position while
}
```
### Make your contents correspond with a floating panel behavior
### Work your contents together with a floating panel behavior
```swift
class ViewController: UIViewController, FloatingPanelControllerDelegate {
@@ -311,9 +352,9 @@ class ViewController: UIViewController {
A `FloatingPanelController` object proxies an action for `show(_:sender)` to the master VC. That's why the master VC can handle a destination view controller of a 'Show' or 'Show Detail' segue and you can hook `show(_:sender)` to show a secondally floating panel set the destination view controller to the content.
It's a greate way to decouple between a floating panel and the content VC.
It's a great way to decouple between a floating panel and the content VC.
### FloatingPanelSurfaceView's issue on iOS 10
### FloatingPanelSurfaceView's issue on iOS 10
* On iOS 10, `FloatingPanelSurfaceView.cornerRadius` isn't not automatically masked with the top rounded corners because of UIVisualEffectView issue. See https://forums.developer.apple.com/thread/50854.
So you need to draw top rounding corners of your content. Here is an example in Examples/Maps.