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?