applidium / OverlayContainer

Non-intrusive iOS UI library to implement overlay based interfaces
https://gaetanzanella.github.io/2018-12-17/replicating-apple-maps-overlay
Other
1.15k stars 94 forks source link

Bottom of Rigid layout panel moves above bottom of screen when dragging, is there a way to stop this? #28

Closed Kohdepitcher closed 5 years ago

Kohdepitcher commented 5 years ago

Hello, really liking the library so far as it feels more responsive than other libraries and feels like apple’s own floating panel.

I just have a quick question about the ridged style. Is there a way to stop the bottom of the overlay container from moving higher than the bottom of the screen as the user drags. I’ve tried using the flexible style for my layout but the overlay controller squishes my stack view.

Pretty much just wanting to know if there’s a way to pin the bottom of the rigid overlay controller to the bottom of the screen.

gaetanzanella commented 5 years ago

Hi @Kohdepitcher, thanks for the feedback.

You can add a view controller to cover the gap:

class CoverViewController: UIViewController {
    private let coverView = UIView() // view pinned to the bottom of the VC.view with a height constraint

    func moveCover(toHeight height: CGFloat) {
        // height constraint changed
    }
}

overlayContainer.viewControllers = [
    BackgroundViewController(),
    CoverViewController(),
    OverlayViewController()
]

// OverlayContainerViewControllerDelegate

func overlayContainerViewController(_ containerViewController: OverlayContainerViewController,
                                    didDragOverlay overlayViewController: UIViewController,
                                    toHeight height: CGFloat,
                                    availableSpace: CGFloat) {
    (containerViewController[1] as? CoverViewController)?.moveCover(toHeight: height)
}

func overlayContainerViewController(_ containerViewController: OverlayContainerViewController,
                                    didEndDraggingOverlay overlayViewController: UIViewController,
                                    transitionCoordinator: OverlayContainerTransitionCoordinator) {
    transitionCoordinator.animate(alongsideTransition: { context in
        (containerViewController[1] as? CoverViewController)?.moveCover(toHeight: height)
    }, completion: nil)
}

Or wrap your overlay VC inside a view controller which keeps its wrapped child height constant and use the flexible style.

I agree. These solutions are not great. I think a new style .expendableHeight would be better. I will take a look at it or feel free to contribute 🙂.

Kohdepitcher commented 5 years ago

Hey little quick update, Im not sure exactly how frameworks work as Ive never played with the code in them. If you make a change in the ADOverlayContainer and then build the example project, does that change flow into the example app. If it does, I only modified a single bit of code and the panel sticks to the bottom of the screen regardless of flexible height or rigid style.

In OverlayContainerViewController, change the following line: overlayContainerView.pinToSuperview(edges: [.left, .top, .right]) to: overlayContainerView.pinToSuperview(edges: [.left, .top, .right, .bottom]) By attaching the container view to all sides of the screen, it seems to attach to the bottom of the screen correctly and bounces back to the max height when dragging higher than the max height just like Apple's own drawer panels

I don't know if it helps at all?

gaetanzanella commented 5 years ago

That's not that simple. There are two views: translation view & container view. Container view contains the overlay, the other one moves alongside the translation. The style defines how the container is embedded inside the translation view.

I think you should use greater than & bottom constraints for the new style to work correctly.

Kohdepitcher commented 5 years ago

Yeah you are right. My little hot fix only works if the view controller inside the overall controller has a scroll view of some sort. It worked fine in your sample project but as soon as I tried the same thing in my own project the panel still lifted above the bottom of the screen. Im guessing that why it works for a scroll view based VC is that it can show more content when dragging up further than the max height where as my VC hasn't got a backing scrollview so it can't show anything else thus putting a gap between the bottom of the screen and the bottom of my VC.

I did experiment by wrapping my VC in a scroll view to see if that would work with what I suggested and it sticks to the bottom of the screen when dragging further than the max point but then the content in the scroll view scrolls which I don't want it to.

I'll play with it some more and see if I can come up with something else.

gaetanzanella commented 5 years ago

Here is the new style https://github.com/applidium/ADOverlayContainer/tree/feature/expandableHeight. Could you try it ? :)

Kohdepitcher commented 5 years ago

Well the expandable height almost works. The VC in the overlay controller is attached to the bottom of the screen but the bottom of the VC is below the screen.

expandable height type IMG_1850

and what it should look like at full height, this was captured using the rigid style IMG_1849

I think the navigation bar may be offsetting the bottom constraint some how? I can drag higher than the max height and see the bottom of the VC.

gaetanzanella commented 5 years ago

Just to be sure, in the two screenshots, the overlay is at the highest notch and the only difference is the overlay container's style ?

Kohdepitcher commented 5 years ago

Yeah the only difference is the style

gaetanzanella commented 5 years ago

Mh, weird. Could you send me a sample code or something to reproduce the error?

gaetanzanella commented 5 years ago

@Kohdepitcher do you pin the overlay's view relatively to the safe area ? You should not, see https://github.com/applidium/ADOverlayContainer#safe-area

Kohdepitcher commented 5 years ago

Hey sorry for taking so long to get back, I tried the update in a fresh project and it does work. https://drive.google.com/drive/folders/1TIp7_ea9tB6ctbTf0sXl0ZDQc6ESsTyD?usp=sharing

And I only used the pin to superview extension that you wrote to pin the overlay controller to the view controller's super view.

Only thing I noticed that the stack view grows in height as the panel is dragged further than the max height when I think instead the bottom constraint should grow instead keeping the stack view the same size which would look better. Also noticed that if you pull up fast enough the spring animation will make the bottom of the panel go higher than bottom of the screen which just looks a little weird.

gaetanzanella commented 5 years ago

I will take a look. Thanks @Kohdepitcher!