Search code examples
iosswiftstoryboardbottom-sheetuisheetpresentationcontroller

UISheetPresentationController displaying differently on different phones


I created a UIStoryboardSegue to make a "Bottom Sheet segue". Our designer shared a screenshot of the app on his phone and the bottom sheet is displaying differently, despite the fact we are both on the same iOS version.

On mine and my simulator, when the bottom sheet opens, it lightens the source view and then shrinks it down a little, so it appears just barely behind the bottom sheet

enter image description here

On the same screen on the designers device, it dims the background and leaves the source view full size, showing the top of the buttons in the navigation bar

enter image description here

I've noticed the Apple maps bottom sheet behaves like the designers, no shrinking of the background view. But I can't see any settings that would affect this. How can I stop the sheet from resizing the source view on mine and function like it's supposed to?

Here's my code:

import UIKit

public class BottomSheetLargeSegue: UIStoryboardSegue {
    
    override public func perform() {
        guard let dest = destination.presentationController as? UISheetPresentationController else {
            return
        }
        
        dest.detents = [.large()]
        dest.prefersGrabberVisible = true
        dest.preferredCornerRadius = 30
        
        source.present(destination, animated: true)
    }
}

Solution

  • Found a hack to force it to never minimise the source view at least, not really what I wanted, but keeps it consistent. Supposedly, .large() is always supposed to minimize the source view, you can avoid this in iOS 16 by creating a custom detent that is just a tiny bit smaller than large like so:

    let customId = UISheetPresentationController.Detent.Identifier("large-minus-background-effect")
    let customDetent = UISheetPresentationController.Detent.custom(identifier: customId) { context in
        return context.maximumDetentValue - 0.1
    }
    dest.detents = [customDetent]
    

    And as a bonus, found a way to control the dimming on the bottom sheet overlay. There is a containerView property on the presentationController, but it is nil when trying to access it in while in the segue. If you force code to run on the main thread, after the call to present, you can access the containerView and set your own color / color animation

    e.g.

        ...
        ...
        source.present(destination, animated: true)
    
        DispatchQueue.main.async {
            dest.containerView?.backgroundColor = .white
        }