Skip to content
This repository was archived by the owner on Jun 24, 2024. It is now read-only.

Latest commit

 

History

History
168 lines (125 loc) · 5.42 KB

10063.md

File metadata and controls

168 lines (125 loc) · 5.42 KB
contributors
zntfdr

Session sample code

  • (From iOS 15) new customization options for sheets
  • New support for a medium detent (and more)
    • allows to create a vertically resizable sheet that only covers half the screen
    • the dimming view can be removed, allowing to build a non-modal UI where the user can interact with content behind the sheet while the sheet is presented

UISheetPresentationController

  • A sheet is an instance of a new UIPresentationController subclass called UISheetPresentationController
  • all customization options are exposed as properties on this class
  • you get an instance of UISheetPresentationController by reading the sheetPresentationController property on a view controller before you present it
  • This property will be non-nil as long the view controller's modalPresentationStyle is form sheet or page sheet (default)
if let sheet = viewController.sheetPresentationController {
  // Customize the sheet
}
present(viewController, animated: true)

Detents

  • A detent is a height where a sheet naturally rests
  • defined as a fraction of the fully expanded sheet frame
  • this is the fully expanded frame on an iPhone and iPad:

  • two system-defined detents:

    • .medium(), which is about half of a sheet's full height
    • .large(), which is the height of a fully expanded sheet
  • specify which detents you want a sheet to support via the UISheetPresentationController's detents property:

if let sheet = viewController.sheetPresentationController {
  sheet.detents = [.large()] // This is the default value
}
present(viewController, animated: true)

Scroll behavior

  • If we have a scroll view within the sheet, scrolling on that view will also expand the sheet
  • we can opt out of this behavior, meaning that the user can only explicitly resize the sheet by dragging from the bar, by setting an extra property:
if let sheet = viewController.sheetPresentationController {
  // ...
  sheet.prefersScrollingExpandsWhenScrolledToEdge = false // 👈🏻
}
present(viewController, animated: true)

Programmatically selecting a detent

We can change the current selected detent by setting the selectedDetentIdentifier property:

if let sheet = viewController.sheetPresentationController {
  sheet.selectedDetentIdentifier = .medium
}

By default it has no animation, to add one, wrap it around a sheet.animateChanges block:

if let sheet = viewController.sheetPresentationController {
  sheet.animateChanges {
    sheet.selectedDetentIdentifier = .medium
  }
}

Dimming View

  • by default all detents are dimmed
  • we can change that by setting from which detent the sheet will show the dimming view
if let sheet = viewController.sheetPresentationController {
  // ...
  sheet.smallestUndimmedDetentIdentifier = .medium
}

This property also allows the user to interact with both the content in the sheet and with the content outside of the sheet.

Keyboard avoidance

  • medium height sheets support automatic keyboard avoidance:
    • the sheet grows automatically to account for the keyboard
    • when the keyboard dismisses, the sheet automatically collapses back down

Landscape

  • new alternate landscape appearance where sheets are only attached to the screen at their bottom edge (no longer full screen on landscape)

if let sheet = viewController.sheetPresentationController {
  // ...
  sheet.prefersEdgeAttachedInCompactHeight = true
}
  • this will always give you a sheet that is as wide as the safe area
  • if you'd like a sheet whose width follows the presented view controller preferredContentSize:

if let sheet = viewController.sheetPresentationController {
  // ...
  sheet.prefersEdgeAttachedInCompactHeight = true
  sheet.widthFollowsPreferredContentSizeWhenEdgeAttached = true
}

More Appearance customization

  • We can display a default grabber:
if let sheet = viewController.sheetPresentationController {
  // ...
  sheet.prefersGrabberVisible = true
}
  • We can customize the corner radius of the sheet:
if let sheet = viewController.sheetPresentationController {
  // ...
  sheet.preferredCornerRadius = 24.0
}
  • Note that the system will keep stacked corners looking consistent: if the sheet with different radius expands to full height, the root sheet (and other stacked ones) will have a corner radius to match

Adaption from popover

  • on regular sizes Apple suggests to show a popover instead of a sheet, this popover adapts to a sheet in compact sizes:
viewController.modalPresentationStyle = .popover // popover by default
if let popover = picker.popoverPresentationController { // reach for popoverPresentationController instead of sheetPresentationController
  popover.barButtonItem = sender // the source of the popover

  let sheet = popover.adaptiveSheetPresentationController // sheet adoption
  // 👇🏻 normal sheet configuration
  sheet.detents = [.medium(), .large()]
  sheet.prefersScrollingExpandsWhenScrolledToEdge = false
  sheet.smallestUndimmedDetentIdentifier = .medium
}
present(viewController, animated: true)