babylonhealth / DrawerKit

DrawerKit lets an UIViewController modally present another UIViewController in a manner similar to the way Apple's Maps app works.
https://github.com/Babylonpartners
MIT License
781 stars 44 forks source link

Method to Disable Collapsed / Dismissed Presented View Controller #53

Open mattbarker016 opened 6 years ago

mattbarker016 commented 6 years ago

TL;DR: How can I make the collapse presented view controller persist on screen, and not dismiss / fly off the screen for good?

Fork: https://github.com/mattbarker016/DrawerKit

Description: I replaced or changed nearly all instances of DrawerState.collapsed to act like .partiallyExpanded. This makes the the drawer toggle between two states, keeping a persistent view no matter what (I also had to use configuration.lowerMarkGap = 100000000. Ideally, I'd like to be able to adjust the .collapsed presented view controller so I can get some of the cool transition and partiallyExpanded physics and functionality, but I haven't found a way yet. Please let me know how I could do this, or if this is a feature to be added!

Code Changed: https://github.com/mattbarker016/DrawerKit/commit/53ef319dc54cd25083d5e262be4876767eccce19

wltrup commented 6 years ago

It feels wrong to me to have a view controller that you can present but cannot dismiss. Nonetheless, if you still want to achieve that effect, then...

I replaced or changed nearly all instances of DrawerState.collapsed to act like .partiallyExpanded.

...is absolutely the wrong thing to do.

Instead, you should add a configuration option similar to DrawerConfiguration.supportsPartialExpansion, say, DrawerConfiguration.supportsCollapsing (with a default value of true to match the current behaviour) and then carefully look at the (few) places where the drawer is dismissed and change the code to dismiss it to the partially expanded state instead of dismissing it to the collapsed state. You then wouldn't have to change anything else, such as DrawerConfiguration.lowerMarkGap.

More generally, however, if all you want is a 2-state drawer, you might as well start from scratch and use the custom view controller transition API (more specifically, the custom presentation API) to implement it.

wltrup commented 6 years ago

It's been pointed out to me that the search controller in Apple's Maps app has the behaviour you're talking about (not dismissible) so it's a valid user case. We don't have plans to add that feature to DrawerKit in the short term, though that could change, but I've made a recommendation in my previous reply as to how you could safely implement that in your fork of DrawerKit. Please reach out again if you have further questions and thank you for your interest in our open-source work.

andersio commented 6 years ago

DrawerKit is currently built for the modal presentation API, which has semantics that doesn't make sense when the drawer is always kept on screen as @wltrup has mentioned.

A potential solution is to make a container VC which shares only the partial and fully expansion transitions with the DrawerKit presentation controller.

mattbarker016 commented 6 years ago

@wltrup I know it was by far not the best solution, it was just a temporary hack in the early hours of the morning. I also realized that the presenting view controller can't be interacted with while the drawer is present, which is something I need.

I was trying to refactor the drawer in our current project here. Ideally, I'd just like to get the sweet physics / animations of DrawerKit. I'm a bit overwhelmed by all the files included in the pod. Would someone be able to point out which files include the pan gesture and animating code?

messages image 2760746132
wltrup commented 6 years ago

Hi @mattbarker016,

the presenting view controller can't be interacted with while the drawer is present, which is something I need

That is a major limitation of DrawerKit at the moment and one which can't easily be fixed. If interacting with the presenting VC is something you absolutely need, then you might want to consider creating your own custom drawer presentation. I suspect you'd have to use a view animation (the presenting VC owns the view whose content is being presented) or use VC containment rather than custom VC presentation. (On a separate note, I am considering re-working the guts of DrawerKit to use VC containment, so stay tuned)

The view animation approach is very easy to implement but is not very flexible. The VC containment is flexible but, in a way, it's reinventing the wheel, which is why I opted to implement DrawerKit using the custom presentation APIs. The downside is that the container VC it provides consumes touch events outside the drawer area and that's why you can't interact with the presenting VC. It might be possible to get around that by messing with the responder chain but I'm not completely sure at the moment how that would work. That is one of the reasons why I'm considering re-implementing DrawerKit to use VC containment.

As for the large number of files, my intention was to have a separate file for each group of related functionality. So, for instance, the bare bones of custom presentation is on Internal API/PresentationController.swift, all its setup is in Internal API/PresentationController+Setup, all its animation code is in Internal API/PresentationController+Animation, all the gesture recogniser handling is in Internal API/PresentationController+Gestures, and so on.

I hope this reply helps you to make a decision. If you can wait, there's a good chance I may have a better and more flexible implementation of DrawerKit early in 2018.

mattbarker016 commented 6 years ago

As for interacting with the view behind the presented view controller, I know this pod implements a way to pass through touches.

gloparco commented 6 years ago

The iOS Maps use case is what I was pursuing when stumbling on DrawerKit. I think being able to interact with the presenter view and not being able to dismiss the presented view would be great additions to the library.

To echo what others have said, the animations in this library are fantastic - far better than Pulley (the other alternative). If we could somehow merge the two, we would have the ideal solution! :-)

TJSartain commented 6 years ago

Apologies if I missed any references to this but I'm wondering if I can disable the full expansion. Sometimes I only have a few "lines" of elements to present so the full screen isn't really the best look.

wltrup commented 6 years ago

Hello @TJSartain, and thanks for your interest in DrawerKit.

Unfortunately, you can't disable the full expansion. It's an open issue to support the expansion of drawers that don't have enough content to fill the entire screen but I haven't got around to implementing that yet.

An alternative that might work for you, however, is to take advantage of

    /// Whether the drawer expands to cover the entire screen, the entire screen minus
    /// the status bar, or the entire screen minus a custom gap. The default is to cover
    /// the full screen.
    public var fullExpansionBehaviour: FullExpansionBehaviour

If you provide a gap here, the drawer will fully expand only so much. It's a bit of a hack since you have to "manually" set a gap but it should work in most situations like that which you described.