UIOnboarding 是一个动画的、可配置的欢迎屏幕,以 Swift Package 的形式呈现 – 其灵感来源于 Apple 的 Stocks 应用。
它支持运行 iOS 和 iPadOS 13 或更高版本的 iPhone、iPad 和 iPod touch,包括核心辅助功能,例如所有设备的动态字体、减少动态效果和旁白 – iPad 的分屏浏览和侧拉功能。
由 Lukman Aščić 开发和设计。
默认 6.5" | 默认 4" |
---|---|
![]() |
![]() |
12.9" 纵向 | 12.9" 横向 |
---|---|
![]() |
![]() |
1/3 iPad 横向 | 1/2 iPad 横向 | 2/3 iPad 横向 |
---|---|---|
![]() |
![]() |
![]() |
1/3 iPad 纵向 | 2/3 iPad 纵向 |
---|---|
![]() |
![]() |
iPad 纵向 | iPad 横向 |
---|---|
![]() |
![]() |
动态字体 | 旁白 | 减少动态效果 |
---|---|---|
![]() |
![]() |
![]() |
在 Xcode 的包管理器中,在 File > Add Packages
下添加 https://github.com/lascic/UIOnboarding.git
。从 2.0.0
版本或 main
分支中选择版本。
.package(url: "https://github.com/lascic/UIOnboarding.git", from: "2.0.0")
// or
.package(url: "https://github.com/lascic/UIOnboarding.git", branch: "main")
在 /Demo
目录中可以找到三个演示项目,包括在 SwiftUI 应用中使用 UIOnboarding 的示例。
克隆仓库或将演示项目下载为 .zip 文件,以便在 Xcode 中的物理设备或模拟器上打开和运行它们。
在构建和运行项目之前,请确保使用您自己的配置描述文件进行设置。
UIOnboardingViewController
接受一个 UIOnboardingViewConfiguration
参数用于设置。
确保您要呈现的视图控制器嵌入在 UINavigationController
中。OnboardingViewController
已设置为全屏视图呈现。
// In the view controller you're presenting
import UIKit
import UIOnboarding
let onboardingController: UIOnboardingViewController = .init(withConfiguration: .setUp())
onboardingController.delegate = self
navigationController?.present(onboardingController, animated: false)
使用提供的委托方法关闭引导视图。
extension ViewController: UIOnboardingViewControllerDelegate {
func didFinishOnboarding(onboardingViewController: UIOnboardingViewController) {
onboardingViewController.modalTransitionStyle = .crossDissolve
onboardingViewController.dismiss(animated: true, completion: nil)
}
}
SwiftUI 的 UIViewControllerRepresentable
协议使 UIKit 的 UIOnboardingViewController
表现为 SwiftUI 的 View
。
创建一个实现该协议的 OnboardingView
结构体,并使用 iOS 和 iPadOS 14 中引入的 .fullScreenCover()
修饰符在您要呈现的 SwiftUI 视图中显示它。
.fullScreenCover(isPresented: $showingOnboarding, content: {
OnboardingView.init()
.edgesIgnoringSafeArea(.all)
}
请注意,我们将 SwiftUI 的协调器指定为引导视图控制器的委托对象。
onboardingController.delegate = context.coordinator
// In OnboardingView.swift
import SwiftUI
import UIOnboarding
struct OnboardingView: UIViewControllerRepresentable {
typealias UIViewControllerType = UIOnboardingViewController
func makeUIViewController(context: Context) -> UIOnboardingViewController {
let onboardingController: UIOnboardingViewController = .init(withConfiguration: .setUp())
onboardingController.delegate = context.coordinator
return onboardingController
}
func updateUIViewController(_ uiViewController: UIOnboardingViewController, context: Context) {}
class Coordinator: NSObject, UIOnboardingViewControllerDelegate {
func didFinishOnboarding(onboardingViewController: UIOnboardingViewController) {
onboardingViewController.dismiss(animated: true, completion: nil)
}
}
func makeCoordinator() -> Coordinator {
return .init()
}
}
// In ContentView.swift
import SwiftUI
struct ContentView: View {
@State private var showingOnboarding = true
var body: some View {
NavigationView {
Text("Hello, UIOnboarding!")
.toolbar {
Button {
showingOnboarding = true
} label: {
Image(systemName: "repeat")
}
}
.fullScreenCover(isPresented: $showingOnboarding, content: {
OnboardingView.init()
.edgesIgnoringSafeArea(.all)
})
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView.init()
}
}
UIOnboardingViewConfiguration
由六种非可选的组件类型组成。
UIImage
NSMutableAttributedString
NSMutableAttributedString
Array<UIOnboardingFeature>
UIOnboardingTextViewConfiguration
(例如:隐私政策、服务条款、作品集、网站)UIOnboardingButtonConfiguration
创建一个辅助结构体 UIOnboardingHelper
来定义这些组件,并将它们组合在 UIOnboardingViewConfiguration
的 扩展 中。
import UIKit
import UIOnboarding
struct UIOnboardingHelper {
// App Icon
static func setUpIcon() -> UIImage {
return Bundle.main.appIcon ?? .init(named: "onboarding-icon")!
}
// First Title Line
// Welcome Text
static func setUpFirstTitleLine() -> NSMutableAttributedString {
.init(string: "Welcome to", attributes: [.foregroundColor: UIColor.label])
}
// Second Title Line
// App Name
static func setUpSecondTitleLine() -> NSMutableAttributedString {
.init(string: Bundle.main.displayName ?? "Insignia", attributes: [
.foregroundColor: UIColor.init(named: "camou")!
])
}
// Core Features
static func setUpFeatures() -> Array<UIOnboardingFeature> {
return .init([
.init(icon: .init(named: "feature-1")!,
title: "Search until found",
description: "Over a hundred insignia of the Swiss Armed Forces – each redesigned from the ground up."),
.init(icon: .init(named: "feature-2")!,
title: "Enlist prepared",
description: "Practice with the app and pass the rank test on the first run."),
.init(icon: .init(named: "feature-3")!,
title: "#teamarmee",
description: "Add name tags of your comrades or cadre. Insignia automatically keeps every name tag you create in iCloud.")
])
}
// Notice Text
static func setUpNotice() -> UIOnboardingTextViewConfiguration {
return .init(icon: .init(named: "onboarding-notice-icon")!,
text: "Developed and designed for members of the Swiss Armed Forces.",
linkTitle: "Learn more...",
link: "https://www.lukmanascic.ch/portfolio/insignia",
tint: .init(named: "camou"))
}
// Continuation Title
static func setUpButton() -> UIOnboardingButtonConfiguration {
return .init(title: "Continue",
titleColor: .white, // Optional, `.white` by default
backgroundColor: .init(named: "camou")!)
}
}
如果欢迎标题只需要一行(例如,在另一种语言中),只需为任一参数提供一个空的 NSMutableAttributedString
值。UIOnboardingTitleLabelStack
会自动调整自身大小以适应相应的行数,无需额外更改。
以下是一个葡萄牙语的示例,第二行标题留空。
// First Title Line
// App Name
static func setUpFirstTitleLine() -> NSMutableAttributedString {
return .init(string: Bundle.main.displayName ?? "Distintivos", attributes: [
.foregroundColor: UIColor.init(named: "camou")!
])
}
// Second Title Line
// Empty
static func setUpSecondTitleLine() -> NSMutableAttributedString {
return .init(string: "")
}
import UIOnboarding
extension UIOnboardingViewConfiguration {
// UIOnboardingViewController init
static func setUp() -> UIOnboardingViewConfiguration {
return .init(appIcon: UIOnboardingHelper.setUpIcon(),
firstTitleLine: UIOnboardingHelper.setUpFirstTitleLine(),
secondTitleLine: UIOnboardingHelper.setUpSecondTitleLine(),
features: UIOnboardingHelper.setUpFeatures(),
textViewConfiguration: UIOnboardingHelper.setUpNotice(),
buttonConfiguration: UIOnboardingHelper.setUpButton())
}
}
您可以借助 User Defaults
标志仅在首次应用启动时显示欢迎屏幕。请注意,未指定的 UserDefaults bool(forKey:)
键默认设置为 false
。
if !UserDefaults.standard.bool(forKey: "hasCompletedOnboarding") {
showOnboarding()
}
在提供的委托方法中切换引导完成状态。
func didFinishOnboarding(onboardingViewController: OnboardingViewController) {
onboardingViewController.modalTransitionStyle = .crossDissolve
onboardingViewController.dismiss(animated: true) {
UserDefaults.standard.set(true, forKey: "hasCompletedOnboarding")
}
}
isReduceMotionEnabled
traitCollectionDidChange(_:)
viewWillTransition(to:with:)
UIViewControllerRepresentable
makeCoordinator()
UserDefaults
UIOnboarding 使用 MIT 许可证。
Insignia 应用图标和 Insignia 功能单元格资源版权归 Lukman Aščić 所有。保留所有权利。未经版权所有者事先书面许可,不得以任何方式复制或分发这些材料或其任何部分。