Skip to content

Customizable sheets using UISheetPresentationController in SwiftUI

License

Notifications You must be signed in to change notification settings

ericlewis/PageSheet

Repository files navigation

PageSheet

Customizable sheet presentations in SwiftUI. Using UISheetPresentationController under the hood.

Features

  • Uses the default sheet API under the hood, ensuring maximum compatibility & stability.
  • Exposes the exact same API as the default SwiftUI sheet implementation.
  • No hacks, follows the best practices for creating representable views in SwiftUI.
  • Configurable using view modifiers, can configure UISheetPresentationController from any child views in the presented sheet's content view.
  • Works with the interactiveDismissDisabled(_:Bool) modifier.
  • Exposes all of the UISheetPresentationController configuration options.
  • Track the currently selected detent using an Environment value.
  • Well documented API, following a similar approach to the Developer Documentation.
  • Small footprint, ~44kB thin when installed via SwiftPM.

Table of Contents

Requirements

The codebase supports iOS and requires Xcode 12.0 or newer

Installation

Xcode

Open your project. Navigate to File > Swift Packages > Add Package Dependency. Enter the url https://github.com/ericlewis/PageSheet and tap Next. Select the PageSheet target and press Add Package.

Swift Package Manager

Add the following line to the dependencies in your Package.swift file:

.package(url: "https://github.com/ericlewis/PageSheet.git", .upToNextMajor(from: "1.0.0"))

Next, add PageSheet as a dependency for your targets:

.target(name: "AppTarget", dependencies: ["PageSheet"])

A completed example may look like this:

// swift-tools-version:5.5

import PackageDescription

let package = Package(
    name: "App",
    dependencies: [
        .package(
          url: "https://github.com/ericlewis/PageSheet.git", 
          .upToNextMajor(from: "1.0.0"))
    ],
    targets: [
        .target(
          name: "AppTarget", 
          dependencies: ["PageSheet"])
    ]
)

Examples

Example Project

If you are using Xcode 13.2.1 you can navigate to the Example folder and open the enclosed Swift App Playground to test various features (and see how they are implemented).

Presentation

PageSheet works similarly to a typical sheet view modifier.

import SwiftUI
import PageSheet

struct ContentView: View {
  @State
  private var sheetPresented = false
  
  var body: some View {
    Button("Open Sheet") {
      sheetPresented = true
    }
    .pageSheet(isPresented: $sheetPresented) {
      Text("Hello!")
    }
  }
}

PageSheet also supports presentation via conditional Identifiable objects.

import SwiftUI
import PageSheet

struct ContentView: View {
  @State
  private var string: String?
  
  var body: some View {
    Button("Open Sheet") {
      string = "Hello!"
    }
    .pageSheet(item: $string) { unwrappedString in
      Text(unwrappedString)
    }
  }
}

extension String: Identifiable {
  public var id: String { self }
}

Customization

PageSheet can also be customized using a collection of view modifiers applied to the sheet's content.

import SwiftUI
import PageSheet

struct ContentView: View {
  @State
  private var sheetPresented = false
  
  var body: some View {
    Button("Open Sheet") {
      sheetPresented = true
    }
    .pageSheet(isPresented: $sheetPresented) {
      Text("Hello!")
        .preferGrabberVisible(true)
    }
  }
}

Module Documentation

PageSheet

PageSheet is split into three different modules, with PageSheetCore handling implementation and PageSheetPlus providing a new modifier called sheetPreferences(_:). The namesake module is PageSheet, which combines PageSheetCore & PageSheetPlus into a single import.

If you want to only use PageSheet without the fancy extra modifier (and extra dependency), then use PageSheetCore.

License

PageSheet is released under the MIT license. See LICENSE for details.