Compare commits

..

5 Commits

Author SHA1 Message Date
Shin Yamamoto 27a2d81a71 Version 2.6.6 2023-08-11 14:17:09 +09:00
Shin Yamamoto 85ed3a6ce3 Fix scroll tracking issues of the scroll view with a positive scroll inset
These issues arose in 'Show Navigation Controller' sample of Samples app.

1. The scrollView's contentOffset always becomes (0, 0) instead of (0, -44),
   which is normal if there is a UINavigationBar.

2. The scrollView's contentOffset sometimes becomes (0, 0) after moving
   a panel quickly like picking.

Case 1 is caused by 7511ce5 commit.
Case 2 is caused by a workaround added at 81fd85e commit.

I tested this library from iOS 11 to iOS 16, and then I confirmed this
workaround doesn't need anymore.

Related to #602, #603.
2023-08-11 13:52:54 +09:00
Shin Yamamoto b34f1093de Version 2.6.5 2023-07-26 18:29:23 +09:00
Shin Yamamoto de1dbe70de Fix a method name for the method convention 2023-07-25 22:47:20 +09:00
Shin Yamamoto c593c646ca Fix a scroll tracking problem caused by a floating point error in LayoutAdapter.offsetFromMostExpandedAnchor
This problem arose after 6611ec8 commit. The root cause is linked to
this condition: `0 == layoutAdapter.offsetFromMostExpandedAnchor` at
line 589 in the method `Core.shouldScrollViewHandleTouch(_:point:velocity:)`.

If the value of `layoutAdapter.offsetFromMostExpandedAnchor` has a
floating point error, the condition evaluates to false. As a result,
the panel moves even when the tracking scroll view is intended to
scroll.

This problem may not occur if there is no floating point error.
2023-07-25 22:13:30 +09:00
7 changed files with 20 additions and 31 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
Pod::Spec.new do |s|
s.name = "FloatingPanel"
s.version = "2.6.4"
s.version = "2.6.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.
+1 -1
View File
@@ -9,7 +9,7 @@
FloatingPanel is a simple and easy-to-use UI component designed for a user interface featured in Apple Maps, Shortcuts and Stocks app.
The user interface displays related content and utilities alongside the main content.
Please see also [the API reference](https://floatingpanel.github.io/2.6.4/documentation/floatingpanel/) for more details.
Please see also [the API reference](https://floatingpanel.github.io/2.6.6/documentation/floatingpanel/) for more details.
![Maps](https://github.com/SCENEE/FloatingPanel/blob/master/assets/maps.gif)
![Stocks](https://github.com/SCENEE/FloatingPanel/blob/master/assets/stocks.gif)
+11 -24
View File
@@ -128,7 +128,7 @@ class Core: NSObject, UIGestureRecognizerDelegate {
if animated {
let updateScrollView: () -> Void = { [weak self] in
guard let self = self else { return }
if self.state == self.layoutAdapter.mostExpandedState, abs(self.layoutAdapter.offsetFromMostExpandedAnchor) <= 1.0 {
if self.state == self.layoutAdapter.mostExpandedState, 0 == self.layoutAdapter.offsetFromMostExpandedAnchor {
self.unlockScrollView()
} else {
self.lockScrollView()
@@ -393,7 +393,7 @@ class Core: NSObject, UIGestureRecognizerDelegate {
let velocity = value(of: panGesture.velocity(in: panGesture.view))
let location = panGesture.location(in: surfaceView)
let insideMostExpandedAnchor = 0 > layoutAdapter.offsetFromMostExpandedAnchor + (1.0 / surfaceView.fp_displayScale)
let insideMostExpandedAnchor = 0 > layoutAdapter.offsetFromMostExpandedAnchor
os_log(msg, log: devLog, type: .debug, """
scroll gesture(\(state):\(panGesture.state)) -- \
@@ -557,7 +557,7 @@ class Core: NSObject, UIGestureRecognizerDelegate {
// A user can stop a panel at the nearest Y of a target position so this fine-tunes
// the a small gap between the presentation layer frame and model layer frame
// to unlock scroll view properly at finishAnimation(at:)
if abs(layoutAdapter.offsetFromMostExpandedAnchor) <= 1.0 {
if 0 == layoutAdapter.offsetFromMostExpandedAnchor {
layoutAdapter.surfaceLocation = layoutAdapter.surfaceLocation(for: layoutAdapter.mostExpandedState)
}
animator.finishAnimation(at: .current)
@@ -716,12 +716,15 @@ class Core: NSObject, UIGestureRecognizerDelegate {
return
}
stopScrollDeceleration = (0 > layoutAdapter.offsetFromMostExpandedAnchor + (1.0 / surfaceView.fp_displayScale)) // Projecting the dragging to the scroll dragging or not
// Determine whether the panel's dragging should be projected onto the scroll content scrolling
stopScrollDeceleration = 0 > layoutAdapter.offsetFromMostExpandedAnchor
if stopScrollDeceleration {
os_log(msg, log: devLog, type: .debug, "panningEnd -- will stop scrolling at initialScrollOffset = \(initialScrollOffset)")
DispatchQueue.main.async { [weak self] in
guard let self = self else { return }
self.stopScrolling(at: self.initialScrollOffset)
os_log(msg, log: devLog, type: .debug, "panningEnd -- did stop scrolling at initialScrollOffset = \(self.initialScrollOffset)")
}
}
@@ -764,19 +767,7 @@ class Core: NSObject, UIGestureRecognizerDelegate {
vc.delegate?.floatingPanelDidEndDragging?(vc, willAttract: true)
}
// Workaround: Disable a tracking scroll to prevent bouncing a scroll content in a panel animating
let isScrollEnabled = scrollView?.isScrollEnabled
if let scrollView = scrollView, targetPosition != layoutAdapter.mostExpandedState {
scrollView.isScrollEnabled = false
}
startAttraction(to: targetPosition, with: velocity)
// Workaround: Reset `self.scrollView.isScrollEnabled`
if let scrollView = scrollView, targetPosition != layoutAdapter.mostExpandedState,
let isScrollEnabled = isScrollEnabled {
scrollView.isScrollEnabled = isScrollEnabled
}
}
// MARK: - Behavior
@@ -812,7 +803,7 @@ class Core: NSObject, UIGestureRecognizerDelegate {
initialScrollOffset = scrollView.contentOffset
} else {
let pinningOffset = contentOffsetForPinning(of: scrollView)
// `initialScrollOffset` must be reset to the pinning offset because the value of `scrollView.contentOffset`,
// for instance, is a value in [-30, 0) on a bottom positioned panel with `allowScrollPanGesture(of:condition:)`.
// If it's not reset, the following logic to shift the surface frame will not work and then the scroll
@@ -938,7 +929,7 @@ class Core: NSObject, UIGestureRecognizerDelegate {
surface location = \(layoutAdapter.surfaceLocation) \
edge most position = \(layoutAdapter.surfaceLocation(for: layoutAdapter.mostExpandedState))
""")
if finished, state == layoutAdapter.mostExpandedState, abs(layoutAdapter.offsetFromMostExpandedAnchor) <= 1.0 {
if finished, state == layoutAdapter.mostExpandedState, 0 == layoutAdapter.offsetFromMostExpandedAnchor {
unlockScrollView()
} else if finished, shouldLooselyLockScrollView {
unlockScrollView()
@@ -1089,11 +1080,7 @@ class Core: NSObject, UIGestureRecognizerDelegate {
// Must use setContentOffset(_:animated) to force-stop deceleration
guard let scrollView = scrollView else { return }
var offset = scrollView.contentOffset
if contentOffset.y >= 0 {
setValue(contentOffset, to: &offset)
} else {
offset = CGPoint(x: 0, y: 0)
}
setValue(contentOffset, to: &offset)
scrollView.setContentOffset(offset, animated: false)
}
+1 -1
View File
@@ -10,7 +10,7 @@ extension CGFloat {
return (self * displayScale).rounded(.toNearestOrAwayFromZero) / displayScale
}
func isEqual(to: CGFloat, on displayScale: CGFloat) -> Bool {
return self.rounded(by: displayScale) == to.rounded(by: displayScale)
return rounded(by: displayScale) == to.rounded(by: displayScale)
}
}
+1 -1
View File
@@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>2.6.4</string>
<string>2.6.6</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
</dict>
+4 -2
View File
@@ -266,12 +266,14 @@ class LayoutAdapter {
}
var offsetFromMostExpandedAnchor: CGFloat {
let offset: CGFloat
switch position {
case .top, .left:
return edgePosition(surfaceView.presentationFrame) - position(for: mostExpandedState)
offset = edgePosition(surfaceView.presentationFrame) - position(for: mostExpandedState)
case .bottom, .right:
return position(for: mostExpandedState) - edgePosition(surfaceView.presentationFrame)
offset = position(for: mostExpandedState) - edgePosition(surfaceView.presentationFrame)
}
return offset.rounded(by: surfaceView.fp_displayScale)
}
private var hiddenAnchor: FloatingPanelLayoutAnchoring {
+1 -1
View File
@@ -7,7 +7,7 @@ class CoreTests: XCTestCase {
override func setUp() {}
override func tearDown() {}
func test_scrolllock() {
func test_scrollLock() {
let fpc = FloatingPanelController()
let contentVC1 = UITableViewController(nibName: nil, bundle: nil)