Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save luthviar/80cdff75529f5359d48eb33b5b894936 to your computer and use it in GitHub Desktop.

Select an option

Save luthviar/80cdff75529f5359d48eb33b5b894936 to your computer and use it in GitHub Desktop.
Create a Bottom Sheet SwiftUI View and present from UIKit UIViewController
class ViewController: UIViewController, BottomSheetPeopleDetectedInputDelegate {
private var overlayView: UIView?
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
let showButton = UIButton(type: .system)
showButton.setTitle("Show Bottom Sheet", for: .normal)
showButton.addTarget(self, action: #selector(showBottomSheet), for: .touchUpInside)
showButton.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(showButton)
NSLayoutConstraint.activate([
showButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
showButton.centerYAnchor.constraint(equalTo: view.centerYAnchor)
])
}
@objc func showBottomSheet() {
let bottomSheetView = BottomSheetPeopleDetectedInputView(delegate: self)
let hostingController = UIHostingController(rootView: bottomSheetView)
let targetSize = hostingController.view.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)
hostingController.preferredContentSize = targetSize
// Set the corner radius for the hosting controller's view
hostingController.view.layer.cornerRadius = 16
hostingController.view.layer.masksToBounds = true
if let sheet = hostingController.sheetPresentationController {
sheet.detents = [.custom(resolver: { _ in (targetSize.height + 80) })]
//sheet.detents = [.medium()]
sheet.prefersGrabberVisible = true
}
present(hostingController, animated: true, completion: nil)
// Add the gray overlay
// let overlay = UIView(frame: self.view.bounds)
// overlay.backgroundColor = UIColor.black.withAlphaComponent(0.5)
// view.addSubview(overlay)
// self.overlayView = overlay
//
// let bottomSheetView = BottomSheetPeopleDetectedInputView(delegate: self)
// let hostingController = UIHostingController(rootView: bottomSheetView)
//
// // Set the corner radius for the hosting controller's view
// hostingController.view.layer.cornerRadius = 16
// hostingController.view.layer.masksToBounds = true
//
// // Calculate the height of the bottom sheet based on the content
// let targetSize = hostingController.view.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)
//
// // Set up modal presentation style
// hostingController.modalPresentationStyle = .overCurrentContext
// hostingController.view.backgroundColor = .clear
//
// // Present the view controller
// present(hostingController, animated: true) {
// // Adjust the frame to appear as a bottom sheet
// hostingController.view.frame = CGRect(
// x: 0,
// y: (self.view.frame.height - targetSize.height) - 80,
// width: self.view.frame.width,
// height: targetSize.height + 80
// )
// }
}
func didSubmitText(_ text: String) {
// Handle the text received from the BottomSheetView
print("Received text: \(text)")
}
func dismissSheet() {
dismiss(animated: true) {
// Remove the overlay with animation when dismissing the bottom sheet
UIView.animate(withDuration: 0.3, animations: {
self.overlayView?.alpha = 0.0
}) { _ in
self.overlayView?.removeFromSuperview()
self.overlayView = nil
}
}
}
}
import SwiftUI
struct BottomSheetPeopleDetectedInputView: View {
@State private var detectedPeopleCount: Int = 1
weak var delegate: BottomSheetPeopleDetectedInputDelegate?
init(delegate: BottomSheetPeopleDetectedInputDelegate? = nil) {
self.delegate = delegate
}
var body: some View {
VStack(spacing: 20) {
// MARK: A small drag handle at the top if needed
// RoundedRectangle(cornerRadius: 3)
// .frame(width: 40, height: 5)
// .foregroundColor(Color.gray.opacity(0.5))
// .padding(.top, 8)
Text("Orang Terdeteksi")
.font(.system(size: 16, weight: .bold)) // Body/Large/Bold
.padding(.top, 8)
.padding(.bottom, 32)
VStack(alignment: .leading) {
Text("Atur jumlah orang yang harus ada di area deteksi")
.font(.system(size: 12, weight: .regular)) // Body/Small/Regular
.foregroundColor(.gray)
.multilineTextAlignment(.leading)
.padding(.bottom, 2.5)
HStack {
// Minus button
Button(action: {
if detectedPeopleCount > 0 {
detectedPeopleCount -= 1
}
}) {
Image(systemName: "minus")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 20, height: 20)
.foregroundColor(.blue)
}
Spacer()
// Displaying the count in the center
TextField("", value: $detectedPeopleCount, formatter: NumberFormatter())
.font(.title2)
.multilineTextAlignment(.center)
.keyboardType(.numberPad)
.frame(width: 60, height: 70)
Spacer()
// Plus button
Button(action: {
detectedPeopleCount += 1
}) {
Image(systemName: "plus")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 20, height: 20)
.foregroundColor(.blue)
}
}
.padding(.horizontal, 16)
//.padding(.vertical, 35)
.background(Color.white) // White background
.cornerRadius(8)
.overlay(
RoundedRectangle(cornerRadius: 8)
.stroke(.gray, lineWidth: 1)
)
}
.padding(.horizontal, 16)
.padding(.bottom, 26)
// Apply button
Button(action: {
// Action for button
delegate?.didSubmitText("\(detectedPeopleCount)")
delegate?.dismissSheet()
}) {
Text("Terapkan")
.font(.system(size: 16, weight: .bold))
.foregroundColor(.white)
.frame(maxWidth: .infinity)
.padding()
.background(Color.blue)
.cornerRadius(10)
}
.cornerRadius(.infinity)
.padding(.horizontal, 16)
.padding(.bottom, 20)
}
.padding()
.background(Color.white)
.cornerRadius(20)
.frame(maxWidth: .infinity, alignment: .bottom)
}
}
protocol BottomSheetPeopleDetectedInputDelegate: AnyObject {
func didSubmitText(_ text: String)
func dismissSheet()
}
@shkfaiz
Copy link

shkfaiz commented Aug 15, 2024

I have used layoutFittingExpandedSize instead of layoutFittingCompressedSize now it works like a charm

@hustlzp
Copy link

hustlzp commented Sep 3, 2025

I have used layoutFittingExpandedSize instead of layoutFittingCompressedSize now it works like a charm

👍🏻

@luthviar
Copy link
Author

luthviar commented Sep 3, 2025

wow thanks for the suggestion @shkfaiz @hustlzp

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment