The panel(surface view) could stop b/w anchors if the pan gesture doesn't
pass through `.changed` state after an interruptible animator is interrupted.
The possible reason is the constraints have never changed since the last animation
is committed so that `surfaceView.superview!.layoutIfNeeded()` doesn't trigger
a layout update by the constraint-based layout system in
`FloatingPanelLayoutAdapter.activateLayout(of:)`.
Thus the inserted code changes a panel interactive constraint by the least
positive number. It allows the constraint-based layout system to update the
surface layout expectedly.
If the decelerating animation is interrupted and
floatingPanelShouldBeginDragging delegate method returns false,
floatingPanelDidEndDecelerating delegate method will not be called
after calling floatingPanelWillBeginDecelerating method.
A panel have to run an animation after the interruption and also
floatingPanelDidEndDecelerating(_:) delegate should be called always
after calling floatingPanelWillBeginDecelerating method.
Therefore floatingPanelShouldBeginDragging delegate method shouldn't be
called in the panel decelerating.
According to 5c0ed4c commit, `floatingPanel.isDecelerating` is needed
only on iOS 10. The flag causes a problem of the safe area update with
the parent view controller containing a large title navigation bar.
And then the large title navigation bar has been introduced since iOS 11.
So the guard condition should be working only for iOS 10.
The previous condition disturb the quick redirect action of a panel
around the top most position. However removing the condition causes a
buggy behavior by an interruption over the top buffer.
After the consideration, I decided to allow an interruption under the
top interaction buffer.
`2ef096b` commit isn't correct. `self.animator` must be set to nil on
the animation interruption, or the interruption occurs repeatedly. To
unlock the scroll correctly, an unlock operation needs to be added in
the scroll pan gesture's callback.
Fix 2 cases on an animation interruption
1. A user interrupts a panel animation below the top Y.
- On the case, a scroll indicator must not appear.
2. A user interrupts a pane animation and soon swipes it up to scroll a
content in a tracking scroll view.
- On the case, a scroll indicator must appear.
NOTE: A UIViewPropertyAnimator which isn't interruptible doesn't stop
the animation even if `self.animator` is set to nil. As a result, the
completion block is called after an interruption and a panel is moving
a bit like going against a user's dragging.
According to the behavior, the scroll unlock wasn't be able to work
expectedly if `self.animator` was set to nil on the interruption and then
I allow a delay until a scroll view is unlocked on the animation completion.
FloatingPanel.{fitToBounds,settle}(scrollView:) don't work because the
surface frame isn't updated expectedly by AutoLayout. Instead of that,
I update FloatingPanelLayoutAdapter.startInteraction(at:) to fit a
surface frame to a scroll offset content.
* Refactor FloatingPanel.targetPosition()
* Add test_targetPosition tests
* Fix bottomY
* Call shouldProjectMomentum(_:for:) only when a projection occurs on next
or pre segment. It means the delegate method not called for redirection.
* Improve all projection