I am using the UISheetPresentationController
in UIKit to present a UIViewController
with the available default detents .medium
and .large
and with a custom smaller detent (with a height of around 100-120). This sheet will be presented on top of a UIViewController
which shows a camera view/video live feed. The camera view is used to scan barcodes and only the visible area of the camera view should recognize the barcode (e.g. the camera feed below the bottom sheet should ignore any barcodes). Therefor I would need to get the currently selected height of the presented sheet to inset the recognition area of the camera view by that height. The selectedDetentIdentifier
property of the UISheetPresentationController
can be used in combination with the UISheetPresentationControllerDelegate
to get the current detent and to respond to any changes of the sheet but the main issue is now that the Detent
does not have a corresponding CGFloat value representing the real height of the sheet.
The only working solution that I was able to come up with was to use the resolvedValue
(Documentation) to get the height of the detents. The issue with this approach is that for this function you need to have a UISheetPresentationControllerDetentResolutionContext
which you can only access in the creation of a custom
detent. So what I came up with is to resolve the values for each of the detents and store it in a property that can be used to inset the underlying camera view:
if let sheet = cameraViewController.sheetPresentationController {
let mediumDetent = UISheetPresentationController.Detent.medium()
let largeDetent = UISheetPresentationController.Detent.large()
sheet.detents = [
.custom(identifier: .small) { context in
let small: CGFloat = 100
self.sizes[UISheetPresentationController.Detent.Identifier.small] = small
self.sizes[UISheetPresentationController.Detent.Identifier.medium] = mediumDetent.resolvedValue(in: context)
self.sizes[UISheetPresentationController.Detent.Identifier.large] = largeDetent.resolvedValue(in: context)
return small
},
mediumDetent,
largeDetent
]
sheet.largestUndimmedDetentIdentifier = .medium
sheet.prefersGrabberVisible = true
sheet.delegate = self
}
taskController.isModalInPresentation = true
present(taskController, animated: true, completion: completion)
I was then able to determine the height using the following code:
if let selectedDetentIdentifier = taskController.sheetPresentationController?.selectedDetentIdentifier,
let height = sizes[selectedDetentIdentifier] {
sheetHeight = height + view.safeAreaInsets.bottom // Sheet automatically adds the safeAreaInsets so we need to do that here as well.
}
But this seems more like a dirty workaround and nothing too reliable that should be used and therefor I would like to know if you have any other solutions or best practices?