All Projects → edudnyk → SheeKit

edudnyk / SheeKit

Licence: MIT license
Customize and resize sheets in SwiftUI with SheeKit. Utilise the power of `UISheetPresentationController` and other UIKit features.

Programming Languages

swift
15916 projects
objective c
16641 projects - #2 most used programming language
ruby
36898 projects - #4 most used programming language

Projects that are alternatives of or similar to SheeKit

NativeMarkKit
NativeMark is a flavor of Markdown designed to be rendered by native apps.
Stars: ✭ 36 (-35.71%)
Mutual labels:  uikit, swiftui
About Swiftui
Gathering all info published, both by Apple and by others, about new framework SwiftUI.
Stars: ✭ 5,954 (+10532.14%)
Mutual labels:  uikit, swiftui
CurrencyText
Currency text field formatter available for UIKit and SwiftUI 💶✏️
Stars: ✭ 124 (+121.43%)
Mutual labels:  uikit, swiftui
column-text-view-ui
📄 Column Text View is an adaptive UI component that renders text in columns, horizontally [iOS 12, UIKit, TextKit, SwiftUI].
Stars: ✭ 11 (-80.36%)
Mutual labels:  uikit, swiftui
VCore
VCore is a Swift collection containing objects, functions, and extensions that I use for my projects
Stars: ✭ 32 (-42.86%)
Mutual labels:  uikit, swiftui
ColorUp
An easy way to generate strongly typed Swift extensions for either UIColor or Color based off of your colors within the project's asset catalog.
Stars: ✭ 16 (-71.43%)
Mutual labels:  uikit, swiftui
Swift Composable Architecture
A library for building applications in a consistent and understandable way, with composition, testing, and ergonomics in mind.
Stars: ✭ 5,199 (+9183.93%)
Mutual labels:  uikit, swiftui
iOS14-Resources
A curated collection of iOS 14 projects ranging from SwiftUI to ML, AR etc.
Stars: ✭ 85 (+51.79%)
Mutual labels:  uikit, swiftui
swiftui-example
SwiftUI 示例,技巧和技术集合,帮助我构建应用程序,解决问题以及了解SwiftUI的实际工作方式。
Stars: ✭ 109 (+94.64%)
Mutual labels:  uikit, swiftui
SwiftCurrent
A library for managing complex workflows in Swift
Stars: ✭ 286 (+410.71%)
Mutual labels:  uikit, swiftui
Redux
Manage iOS App state with Redux and Async/Await :)
Stars: ✭ 18 (-67.86%)
Mutual labels:  uikit, swiftui
NavigationRouter
A router implementation designed for complex modular apps, written in Swift
Stars: ✭ 89 (+58.93%)
Mutual labels:  uikit, swiftui
SwiftUIKit
📱 UIKit code that is fun to write
Stars: ✭ 71 (+26.79%)
Mutual labels:  uikit, swiftui
Movie Trailers SwiftUI
A simple app which shows the lastest movies trailers based on different genres developed using SwiftUI.
Stars: ✭ 51 (-8.93%)
Mutual labels:  uikit, swiftui
LocalConsole
In-app console and debug tools for iOS developers
Stars: ✭ 595 (+962.5%)
Mutual labels:  uikit, swiftui
Swiftui Cheat Sheet
SwiftUI 2.0 Cheat Sheet
Stars: ✭ 3,417 (+6001.79%)
Mutual labels:  uikit, swiftui
BottomSheet
Access UISheetPresentationController in SwiftUI on iOS 15 using a simple .bottomSheet modifier.
Stars: ✭ 332 (+492.86%)
Mutual labels:  uikit, swiftui
Render
UIKit a-là SwiftUI.framework [min deployment target iOS10]
Stars: ✭ 2,150 (+3739.29%)
Mutual labels:  uikit, swiftui
UIViewPreviewProvider
Allows displaying UIViews inside the Xcode preview canvas
Stars: ✭ 36 (-35.71%)
Mutual labels:  uikit, swiftui
Builder
Demonstrates SwiftUI builder patterns for UIKit and networking.
Stars: ✭ 100 (+78.57%)
Mutual labels:  uikit, swiftui

SheeKit

Customize and resize sheets in SwiftUI with SheeKit. Utilise the power of UISheetPresentationController and other UIKit features.

Overview

SheeKit is a bridge between SwiftUI and UIKit which enriches the modal presentations in SwiftUI with the features available in UIKit.

SheeKit provides two modifiers for presenting the sheet, similar to SwiftUI.sheet(...):

  • controlled by isPresented boolean flag
  • controlled by the optional Identifiable item

Additionally, SheeKit allows to:

  • customize sheet detents to present half-screen sheets
  • define different modal presentation styles for different Identifiable items
  • customize the preferred presented view controller properties via UIViewControllerProxy
  • utilise the UIPopoverPresentationController.adaptiveSheetPresentationController and customize adaptive sheet for popover which will be used on iPhone and in compact horizontal size class of the scene on iPad.

Customizing sheet detents to present half-screen sheets

With iOS 15, sheets can be resizable between large() and medium() detents and animate the size transitions. In order to customize detents, provide SheetProperties to the ModalPresentationStyle/pageSheet(properties:) or ModalPresentationStyle/formSheet(properties:).

struct ShowLicenseAgreement: View {
    @State private var isShowingSheet = false
    @State private var selectedDetentIdentifier = UISheetPresentationController.Detent.Identifier.medium 
    var body: some View {
        Button(action: {
            isShowingSheet.toggle()
        }) {
            Text("Show License Agreement")
        }
        .shee(isPresented: $isShowingSheet,
              presentationStyle: .formSheet(properties: .init(detents: [ .medium(), .large() ], selectedDetentIdentifier: $selectedDetentIdentifier, animatesSelectedDetentIdentifierChange: true)),
              onDismiss: didDismiss) {
            VStack {
                Text("License Agreement")
                    .font(.title)
                    .padding(50)
                Text("""
                        Terms and conditions go here.
                    """)
                    .padding(50)
                Button("Dismiss",
                       action: { isShowingSheet.toggle() })
            }
        }
    }

    func didDismiss() {
        // Handle the dismissing action.
    }
}

Define different modal presentation styles for different Identifiable items

In SwiftUI, there are three different modifiers for popover, fullScreenCover and sheet, which don't allow the developer to show different styles of the dialog based on the same source of truth (provided by item).

With SheeKit, it's possible - just provide presentationStyle which corresponds to your item.

struct ShowPartDetail: View {
    @State var sheetDetail: InventoryItem?
    var body: some View {
        Button("Show Part Details") {
            sheetDetail = InventoryItem(
                id: "0123456789",
                partNumber: "Z-1234A",
                quantity: 100,
                name: "Widget")
        }
        .shee(item: $sheetDetail,
              presentationStyle: presentationStyle,
              onDismiss: didDismiss) { detail in
            VStack(alignment: .leading, spacing: 20) {
                Text("Part Number: \(detail.partNumber)")
                Text("Name: \(detail.name)")
                Text("Quantity On-Hand: \(detail.quantity)")
            }
            .onTapGesture {
                sheetDetail = nil
            }
        }
    }

    func didDismiss() {
        // Handle the dismissing action.
    }

    var presentationStyle: ModalPresentationStyle {
        var sheetProperties = SheetProperties()
        sheetProperties.detents = sheetDetail?.quantity ?? 0 > 100500 ? [ .large() ] : [ .medium() ]
        return .formSheet(properties: sheetProperties)
    }
}

struct InventoryItem: Identifiable {
    var id: String
    let partNumber: String
    let quantity: Int
    let name: String
}

Customize the preferred presented view controller properties via UIViewControllerProxy

In UIKit, UIViewController class has many properties which allow to alter the user experience depending on the use case, like forbidding of interactive dismiss of the sheets via isModalInPresentation, customizing status bar appearance, preferred content size, or modal transition style. Unfortunately, this functionality is not exposed in SwiftUI. SheeKit solves this problem by allowing the consumer to provide UIViewControllerProxy which defines preferred parameters of the presented view controller.

struct ShowLicenseAgreement: View {
    @State private var isShowingSheet = false
    @State private var selectedDetentIdentifier = UISheetPresentationController.Detent.Identifier.medium 
    var body: some View {
        Button(action: {
            isShowingSheet.toggle()
        }) {
            Text("Show License Agreement")
        }
        .shee(isPresented: $isShowingSheet,
              presentationStyle: .formSheet(properties: .init(detents: [ .medium(), .large() ], selectedDetentIdentifier: $selectedDetentIdentifier, animatesSelectedDetentIdentifierChange: true)),
              presentedViewControllerParameters: presentedViewControllerParameters,
              onDismiss: didDismiss) {
            VStack {
                Text("License Agreement")
                    .font(.title)
                    .padding(50)
                Text("""
                        Terms and conditions go here.
                    """)
                    .padding(50)
                Button("Dismiss",
                       action: { isShowingSheet.toggle() })
            }
        }
    }

    func didDismiss() {
        // Handle the dismissing action.
    }

    var presentedViewControllerParameters: UIViewControllerProxy {
        var parameters = UIViewControllerProxy()
        parameters.preferredStatusBarStyle = .darkContent
        parameters.preferredStatusBarUpdateAnimation = .fade
        parameters.isModalInPresentation = true
        parameters.modalTransitionStyle = .flipHorizontal
        return parameters
    }
}

Utilise the adaptiveSheetPresentationController of UIPopoverPresentationController and customize adaptive sheet for popover

In SwiftUI, when popover is shown as a sheet when the user minimizes the app to the smallest size on top of the other app on iPad, or when the popover is shown on iPhone as a sheet, developer can't get a medium-detent sheet in a compact size class of a scene instead of a popover. The sheet into which popover adapts, is always with .large() detent.

SheeKit allows the developer to customize this behavior and to specify the detents for the sheet in which the popover adapts to, along with the preferred popover arrow direction and the source rect.

struct ShowLicenseAgreement: View {
    @State private var isShowingSheet = false
    @State private var selectedDetentIdentifier = UISheetPresentationController.Detent.Identifier.medium 
    var body: some View {
        Button(action: {
            isShowingSheet.toggle()
        }) {
            Text("Show License Agreement")
        }
        .shee(isPresented: $isShowingSheet,
              presentationStyle: .popover(permittedArrowDirections: .top, 
                                          sourceRectTransform: { $0.offsetBy(dx: 16, dy: 16) }, 
                                          adaptiveSheetProperties: .init(detents: [ .medium(), .large() ], 
                                                                         selectedDetentIdentifier: $selectedDetentIdentifier, 
                                                                         animatesSelectedDetentIdentifierChange: true)),
              onDismiss: didDismiss) {
            VStack {
                Text("License Agreement")
                    .font(.title)
                    .padding(50)
                Text("""
                        Terms and conditions go here.
                    """)
                    .padding(50)
                Button("Dismiss",
                       action: { isShowingSheet.toggle() })
            }
        }
    }

    func didDismiss() {
        // Handle the dismissing action.
    }
}

Demo of the library

SheeKit Demo on YouTube

Installation

Xcode 13

  1. Select your project in File Navigator, then select the project again on top of the list of targets. You'll see list of packages.
  2. Press + button.
  3. In the appeared window, press + button in the bottom left corner.
  4. In the appeared menu, select "Add Swift Package Collection"
  5. In the appeared dialog, enter package collection URL: https://swiftpackageindex.com/edudnyk/collection.json
  6. Press "Add Collection"
  7. Select SheeKit package from the collection.

If you want to use SheeKit in any other project that uses SwiftPM, add the package as a dependency in Package.swift:

dependencies: [
  .package(name: "SheeKit", url: "https://github.com/edudnyk/SheeKit.git", from: "2.0.0"),
]

Next, add SheeKit as a dependency of your test target:

targets: [
  .target(name: "MyApp", dependencies: ["SheeKit"], path: "Sources"),
]

Carthage

If you use Carthage, you can add the following dependency to your Cartfile:

github "edudnyk/SheeKit" ~> 2.0.0

CocoaPods

If your project uses CocoaPods, add the pod to any applicable targets in your Podfile:

target 'MyApp' do
  pod 'SheeKit', '~> 2.0.0'
end

Topics

  • DismissAction
  • ModalPresentationStyle
  • ModalPresentationStyleCompat
  • SheetProperties
  • UIViewControllerProxy
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].