Dunfey · Hotel WWDC as data, est. 1983
Front desk everything
Years
Topics

2021 SwiftUI & UI Frameworks

WWDC21 · 12 min · SwiftUI & UI Frameworks

Customize and resize sheets in UIKit

Discover how you can create a layered and customized sheet experience in UIKit. We’ll explore how you can build a non-modal experience in your app to allow interaction with content both in a sheet and behind the sheet at the same time. We’ll also take you through sheet size customization, revealing or hiding grabber controls, and adapting between popovers and customized sheets in your app. To get the most out of this session, we recommend watching the Presentations portion of “Modernizing Your UI for iOS 13” from WWDC19 beginning at 9:45.

Watch at developer.apple.com ↗

Transcript all transcripts

Code shown on screen · 15 snippets

Get a sheet swift · at 0:01 ↗
if let sheet = viewController.sheetPresentationController {
    // Customize the sheet
}
present(viewController, animated: true)
Detents (large only) swift · at 0:02 ↗
if let sheet = picker.sheetPresentationController {
    sheet.detents = [.large()]
}
present(picker, animated: true)
Detents (medium and large) swift · at 0:03 ↗
if let sheet = picker.sheetPresentationController {
    sheet.detents = [.medium(), .large()]
}
present(picker, animated: true)
Detents (medium only) swift · at 0:04 ↗
if let sheet = picker.sheetPresentationController {
    sheet.detents = [.medium()]
}
present(picker, animated: true)
Present image picker in a standard sheet swift · at 0:05 ↗
func showImagePicker() {
    let picker = PHPickerViewController()
    picker.delegate = self
    present(picker, animated: true)
}

func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
    // assign result to imageView.image
    dismiss(animated: true)
}
Present at medium detent, and don’t dismiss automatically swift · at 0:06 ↗
func showImagePicker() {
    let picker = PHPickerViewController()
    picker.delegate = self
    if let sheet = picker.sheetPresentationController {
        sheet.detents = [.medium(), .large()]
    }
    present(picker, animated: true)
}

func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
    // assign result to imageView.image
}
Prevent scrolling from expanding the sheet swift · at 0:07 ↗
func showImagePicker() {
    let picker = PHPickerViewController()
    picker.delegate = self
    if let sheet = picker.sheetPresentationController {
        sheet.detents = [.medium(), .large()]
        sheet.prefersScrollingExpandsWhenScrolledToEdge = false
    }
    present(picker, animated: true)
}

func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
    // assign result to imageView.image
}
Select medium detent when a photo is picked swift · at 0:08 ↗
func showImagePicker() {
    let picker = PHPickerViewController()
    picker.delegate = self
    if let sheet = picker.sheetPresentationController {
        sheet.detents = [.medium(), .large()]
        sheet.prefersScrollingExpandsWhenScrolledToEdge = false
    }
    present(picker, animated: true)
}

func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
    // assign result to imageView.image
    if let sheet = picker.sheetPresentationController {
        sheet.selectedDetentIdentifier = .medium
    }
}
Animate selection of medium detent swift · at 0:09 ↗
func showImagePicker() {
    let picker = PHPickerViewController()
    picker.delegate = self
    if let sheet = picker.sheetPresentationController {
        sheet.detents = [.medium(), .large()]
        sheet.prefersScrollingExpandsWhenScrolledToEdge = false
    }
    present(picker, animated: true)
}

func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
    // assign result to imageView.image
    if let sheet = picker.sheetPresentationController {
        sheet.animateChanges {
            sheet.selectedDetentIdentifier = .medium
        }
    }
}
Remove dimming at medium detent swift · at 0:10 ↗
func showImagePicker() {
    let picker = PHPickerViewController()
    picker.delegate = self
    if let sheet = picker.sheetPresentationController {
        sheet.detents = [.medium(), .large()]
        sheet.prefersScrollingExpandsWhenScrolledToEdge = false
        sheet.smallestUndimmedDetentIdentifier = .medium
    }
    present(picker, animated: true)
}

func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
    // assign result to imageView.image
    if let sheet = picker.sheetPresentationController {
        sheet.animateChanges {
            sheet.selectedDetentIdentifier = .medium
        }
    }
}
iPhone in landscape swift · at 0:11 ↗
if let sheet = fontPicker.sheetPresentationController {
    sheet.prefersEdgeAttachedInCompactHeight = true
    sheet.widthFollowsPreferredContentSizeWhenEdgeAttached = true
}
present(fontPicker, animated: true)
Show a grabber swift · at 0:12 ↗
if let sheet = fontPicker.sheetPresentationController {
    sheet.prefersGrabberVisible = true
}
present(fontPicker, animated: true)
Customize the corner radius swift · at 0:13 ↗
if let sheet = fontPicker.sheetPresentationController {
    sheet.preferredCornerRadius = 20.0
}
present(fontPicker, animated: true)
Adapt a popover to a customized sheet swift · at 0:14 ↗
func showImagePicker(_ sender: UIBarButtonItem) {
    let picker = PHPickerViewController()
    picker.delegate = self
    picker.modalPresentationStyle = .popover
    if let popover = picker.popoverPresentationController {
        popover.barButtonItem = sender

        let sheet = popover.adaptiveSheetPresentationController
        sheet.detents = [.medium(), .large()]
        sheet.prefersScrollingExpandsWhenScrolledToEdge = false
        sheet.smallestUndimmedDetentIdentifier = .medium
    }
    present(picker, animated: true)
}
Be consistent when using adaptiveSheetPresentationController swift · at 0:15 ↗
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
    // assign result to imageView.image
    if let sheet = picker.popoverPresentationController?.adaptiveSheetPresentationController {
        sheet.animateChanges {
            sheet.selectedDetentIdentifier = .medium
        }
    }
}

Resources