0. 概览
今年年初,Apple 推出了最新的 Xcode 14.3 以及对应的 iOS 16.4 。
与此同时,它们对目前最新的 SwiftUI 4.0 也添加了一些新功能:
- sheet 弹窗后部视图(Interact with a view Behind a sheet)可交互;
- sheet 弹窗背景透明化;
- 调整 sheet 弹窗顶角弧度;
- 控制弹窗内滚动手势优先级;
- 定制紧密(compact-size )尺寸下 sheet 弹窗大小;
- Xcode 预览(Preview)模式下对调试输出的支持;
让我们依次来了解一下它们吧。
Let‘s go!!!😉
1. sheet 后部视图可交互
在 iOS 16.4 之前,SwiftUI 中 sheet 弹窗后,如果点击其后部的视图会导致弹窗立即被关闭,从而无法与弹窗后部的视图进行交互。
从 iOS 16.4 开始,我们可以为 sheet 弹窗应用 presentationBackgroundInteraction() 方法,以达到不关闭弹窗而与后部视图交互之目的:
@available(iOS 16.4, *)
struct ContentView: View {
@State private var isPresented = false
@State private var number = 0
var body: some View {
ZStack(alignment: .top) {
Rectangle()
.fill(Gradient(colors: [.red,.green]).opacity(0.66))
.ignoresSafeArea()
Button("Sheet") {
isPresented = true
}
.buttonStyle(.borderedProminent)
.padding()
VStack {
Button("产生随机数: \(number)"){
number = Int.random(in: 0..<10000000)
}
.foregroundColor(.white)
.font(.title.weight(.black))
}.padding(.top, 200)
}
.sheet(isPresented: $isPresented) {
Text("大熊猫侯佩 @ csdn")
.font(.headline)
.presentationDetents([.height(120), .medium, .large])
// 开启后部视图交互
.presentationBackgroundInteraction(.enabled)
}
}
}
2. sheet 背景透明化
从 iOS 16.4 开始,我们可以为 sheet 弹窗选择透明样式,更好的美化弹出窗口的显示效果。
如下代码所示,我们在 sheet 弹窗上应用了 presentationBackground(_: ) 修改器以实现透明磨砂效果:
@available(iOS 16.4, *)
struct ContentView: View {
@State private var isSheet = false
@State private var isSheetTransparency = false
var body: some View {
ZStack(alignment: .top) {
Rectangle()
.fill(Gradient(colors: [.red,.green]).opacity(0.66))
.ignoresSafeArea()
HStack {
Button("弹出") {
isSheet = true
}
.sheet(isPresented: $isSheet) {
Text("大熊猫侯佩 @ csdn")
.font(.headline)
.presentationDetents([.height(120), .medium, .large])
// 或使用 .background 调用 presentationBackground() 方法效果相同
//.presentationBackground(.background)
}
Spacer()
Button("透明弹出") {
isSheetTransparency = true
}
.sheet(isPresented: $isSheetTransparency) {
Text("大熊猫侯佩 @ csdn")
.font(.headline)
.presentationDetents([.height(120), .medium, .large])
.presentationBackground(.ultraThinMaterial)
}
}
.font(.headline)
.buttonStyle(.borderedProminent)
.padding(.top, 200)
.padding(.horizontal, 50)
}
}
}
3. sheet 顶部弧度调整
感觉 sheet 弹窗顶角生硬无弧度的小伙伴们有福了,从 iOS 16.4 开始,SwiftUI 开始支持调整 sheet 弹出窗口顶角的弧度了。
我们可以使用 .presentationCornerRadius() 修改器来实现这一功能:
@available(iOS 16.4, *)
struct ContentView: View {
@State private var isSheet = false
@State private var isSheetRadius = false
var body: some View {
ZStack(alignment: .top) {
Rectangle()
.fill(Gradient(colors: [.red,.green]).opacity(0.66))
.ignoresSafeArea()
HStack {
Button("弹出") {
isSheet = true
}
.sheet(isPresented: $isSheet) {
Text("大熊猫侯佩 @ csdn")
.font(.headline)
.presentationDetents(.height(120), .medium, .large])
}
Spacer()
Button("顶角圆润弧度弹出") {
isSheetRadius = true
}
.sheet(isPresented: $isSheetRadius) {
Text("大熊猫侯佩 @ csdn")
.font(.headline)
.presentationDetents([.height(120), .medium, .large])
.presentationCornerRadius(30.0)
}
}
.font(.headline)
.buttonStyle(.borderedProminent)
.padding(.top, 200)
.padding(.horizontal, 50)
}
}
}
4. sheet 滚动手势优先级调整
在 iOS 16.4 之前,如果我们 sheet 尺寸可变弹窗中包含滚动视图(比如 List,ScrollView 等),当用户在弹窗中滚动将会首先引起弹窗尺寸的改变,而不是其滚动内容的改变。
在 iOS 16.4 之后,我们可以调整 sheet 弹窗滚动手势优先级,以确保首先滚动其内容而不是改变弹窗尺寸。
这是通过 .presentationContentInteraction(.scrolls) 方法来实现的:
@available(iOS 16.4, *)
struct ContentView: View {
@State private var isSheet = false
@State private var isSheetScrollable = false
var body: some View {
ZStack(alignment: .top) {
Rectangle()
.fill(Gradient(colors: [.red,.green]).opacity(0.66))
.ignoresSafeArea()
HStack {
Button("弹出") {
isSheet = true
}
.sheet(isPresented: $isSheet) {
VStack(spacing: 16) {
Text("大熊猫侯佩 @ csdn")
.font(.headline)
List(0..<50, id: \.self){ i in
Text("Item \(i)")
.font(.subheadline)
}
.listStyle(.plain)
}
.padding()
.presentationDetents([.height(120), .medium, .large])
}
Spacer()
Button("滚动高优先级弹出") {
isSheetScrollable = true
}
.sheet(isPresented: $isSheetScrollable) {
VStack(spacing: 16) {
Text("大熊猫侯佩 @ csdn")
.font(.headline)
List(0..<50, id: \.self){ i in
Text("Item \(i)")
.font(.subheadline)
}
.listStyle(.plain)
}
.padding()
.presentationDetents([.height(120), .medium, .large])
.presentationContentInteraction(.scrolls)
}
}
.font(.headline)
.buttonStyle(.borderedProminent)
.padding(.top, 200)
.padding(.horizontal, 50)
}
}
}
5. 定制 sheet 在紧密尺寸下的大小
在 iOS 16.4 之前,如果在 iPhone 横屏时 sheet 弹窗,则弹出窗口将会铺满整个屏幕。
从 iOS 16.4 开始,我们可以为弹窗应用新的 .presentationCompactAdaptation(_: ) 修改器来改变横屏时弹窗的大小:
struct SheetView: View {
@Environment(\.dismiss) var dismiss
var body: some View {
VStack(spacing: 16) {
Text("大熊猫侯佩 @ csdn")
Button("关闭"){
dismiss()
}
}
}
}
@available(iOS 16.4, *)
struct ContentView: View {
@State private var isSheet = false
@State private var isSheetCompactSizeCustom = false
var body: some View {
ZStack(alignment: .top) {
Rectangle()
.fill(Gradient(colors: [.red,.green]).opacity(0.66))
.ignoresSafeArea()
HStack {
Button("弹出") {
isSheet = true
}
.sheet(isPresented: $isSheet) {
SheetView()
.padding()
.frame(width: 200)
.presentationDetents([.height(200), .medium, .large])
}
Spacer()
Button("自定义尺寸弹出") {
isSheetCompactSizeCustom = true
}
.sheet(isPresented: $isSheetCompactSizeCustom) {
VStack(spacing: 16) {
Text("大熊猫侯佩 @ csdn")
}
.padding()
.frame(width: 350)
.presentationDetents([.height(200), .medium, .large])
.presentationCompactAdaptation(.sheet)
}
}
.font(.headline)
.buttonStyle(.borderedProminent)
.padding(.top, 200)
.padding(.horizontal, 50)
}
}
}
6. Xcode 预览模式对调试输出的支持
Xcode 14.3 之前,我们在预览(Preview)模式中测试 SwiftUI 界面功能时无法观察调试语句( print 等方法)的输出结果,必须在模拟器或真机中运行才可以在 Xcode 底部调试小窗口中看到 print() 等方法的输出。
从 Xcode 14.3 开始,以预览模式运行 App 时也可以在调试窗口中看到调试语句的输出了,真是太方便了:
@available(iOS 16.4, *)
struct ContentView: View {
var body: some View {
ZStack(alignment: .center) {
Rectangle()
.fill(Gradient(colors: [.red,.green]).opacity(0.66))
.ignoresSafeArea()
Button("显示 debug 输出") {
print("显示随机数: \(Int.random(in: 0..<10000000))")
}
}
}
}
7. 总结
在本篇博文中,我们介绍了在 Xcode 14.3 和 iOS 16.4 中 SwiftUI 为我带来的新方法和新功能,解决了诸多燃眉之急的问题,小伙伴们不想赶快尝试一下吗?🚀
感谢观赏,再会!😎