scenee / FloatingPanel

A clean and easy-to-use floating panel UI component for iOS
MIT License
5.58k stars 507 forks source link

Not provided any delegate method for tracking scroll offset of panel. #210

Open pramodmore opened 5 years ago

pramodmore commented 5 years ago

Please fill out this template appropriately when filing a bug report.

Please remove this line and everything above it before submitting.

Short description

Expected behavior

Actual behavior

Steps to reproduce

Code example that reproduces the issue

Environment

Library version

Installation method

iOS version(s)

Xcode version

scenee commented 5 years ago

You're able to use FloatingPanelControllerDelegate.floatingPanelDidMove()! https://github.com/SCENEE/FloatingPanel/blob/master/Framework/Sources/FloatingPanelController.swift#L20

Mattijah commented 5 years ago

@SCENEE It seems like the floatingPanelDidMove is only called when the panel is dragged by the user's finger. In case when the transition is finished by the animation and/or hide(animated:) gets called, the panel's position is not reported. At least not in v1.6.1. Is this a bug? Shouldn't it work the same way scrollViewDidScroll: does?

scenee commented 5 years ago

In case when the transition is finished by the animation and/or hide(animated:) gets called, the panel's position is not reported. At least not in v1.6.1. Is this a bug?

Does that mean floatingPanelDidChangePosition() is not called in the case? Could you please try v1.6.4?

Mattijah commented 5 years ago

Sorry, I'm using the latest version which is v1.6.4, I made mistake above. Yes, it is not called. It's only called when you move the panel with a finger. As soon as you lift your finger and the panel starts animating the floatingPanelDidMove is not called. Same about calling hide. floatingPanelDidMove will not get called.

Edit: floatingPanelDidChangePosition is called, but I need the exact Y point of the panel. The position is reported at the end of transition only.

scenee commented 5 years ago

I got it. The floatingPanelDidMove behavior is as expected for now(See also here). If you would like to move(synchronize) view items with move animation of a panel, you can…

  1. Add an animation block in a UIViewPropertuAnimator object for each animation(add, remove, move etc).
  2. Add the item change in floatingPanelDidChangePosition because the delegate method is called in animation block of an animator.

But if they aren't enough for you, could you please tell me about use cases? I would like to consider the spec towards v2.0.

Mattijah commented 5 years ago

Thank you for your reply @SCENEE

I will have a look at the 2 possible solutions that you mentioned, but I'm not sure if this is going to be as straightforward. What I need, is to sync my view with the movement of the panel, but only to certain Y position. Then, when the panel is coming back I need to sync it again (reverse) the view from that specific Y position. The best thing would just be if the floatingPanelDidMove would work the same way UIScrollView.scrollViewDidScroll: does.

For now I managed to solve this problem by workaround where I pin an additional UIView to the top of the surfaceView and bottom of the super view. The view also has height set to lessThanOrEqualTo, so it will not get bigger than I need to be (it will stop at that specific y). Then I'm syncing my view based on that with autolayout constraints... 😅

Edit: Mentioned solutions would probably only work in combination with the floatingPanelDidMove since I need to track manual dragging too. I think this will just add to the complexity...

scenee commented 5 years ago

I'm sorry to be late for my reply. The above solution is expected by the library. It's caused by the different mechanism between UIScrollView and FloatingPanelController. The former doesn't use animations, but the later uses them. I agree that it's easier to sync view items with a panel only by floatingPanelDidMove:. But it needs a migration from animation based behavior to non-animation based one. The migration requires a big change of FloatingPanel APIs. So I would like to add this feature into my backlog for v2.0 or later.

marcheimendinger commented 4 years ago

Any news on this ? I'm looking to update a Google Maps map padding when a panel is present. So I need it to be updated when :

I get a good result for the closing part with floatingPanelDidChangePosition and when the user swipes it with floatingPanelDidMove but I'm still struggling for the opening part (see #329) and also at the moment when the user moves it a little bit, releases his finger and the panel comes back to its original position. There I'm not able to track this part of the movement. Apparently floatingPanelDidMove is only triggered when a user has his finger on the panel. I can get the end of the panel animation with floatingPanelDidEndDecelerating but as said before there is a short part I'm missing (between the finger release and the end of the decelerating).

All of this would be simpler with a "real" floatingPanelDidMove triggered at every moment when the panel moves, either from a user interaction or an animation.

Any thoughts to solve my issues ?

scenee commented 4 years ago

Yes, it's a floatingPanelDidMove naming issue. It's actually floatingPanelDidDrag. FloatingPanel has the almost same delegate methods as UIScrollView, but the implementation is different. Actually floatingPanelDidChangePosition is always called in an animation block which is committed to move a panel to the next position. Therefore, you can't track the panel frame, but you can synchronize the map padding with the panel movement easily by changing the map padding in floatingPanelDidChangePosition as below.

    func floatingPanelDidChangePosition(_ vc: FloatingPanelController) {
        UIView.animateKeyframes(withDuration: 0.0, delay: 0.0, options: [.calculationModeCubic]) {
            UIView.addKeyframe(withRelativeStartTime: 0.0, relativeDuration: 1.0) {
                // Update Map padding
            }
        }
    }

NOTE: UIView.animateKeyframes lets the animation cubic to prevent the map padding bouncing.