如何使用 SwiftUI 将条件 ToolbarItems 添加到 NavigationView 工具栏?
How to add conditional ToolbarItems to NavigationView Toolbar with SwiftUI?
我正在尝试将图标按钮添加到 NavigationView 工具栏的前缘 - 但我希望该按钮仅在设备处于横向模式时可见。 (有点像默认 Notes 应用程序的工作方式)
我有以下代码:
var body: some View {
VStack {
// ... content display
}
.toolbar {
if UIDevice.current.orientation.isLandscape {
ToolbarItem(placement: .navigationBarLeading) {
Button(action: toggleFullscreen) {
if isFullscreen {
Image(systemName: "arrow.down.right.and.arrow.up.left")
} else {
Image(systemName: "arrow.up.left.and.arrow.down.right")
}
}
}
}
ToolbarItem(placement: .navigationBarTrailing) {
Button(action: createNewNote) {
Image(systemName: "square.and.pencil")
}
}
})
}
如果我删除工具栏内容中的条件 if
子句,它可以正常工作,但它似乎根本无法识别 if
语句?
然而,VStack
中的 if
语句工作正常。
我得到的具体错误是:
Closure containing control flow statement cannot be used with result builder 'ToolbarContentBuilder'
知道如何解决这个问题吗?
P.S。将我视为一个完整的 SwiftUI 菜鸟。虽然,我精通 React - 所以任何帮助我理解的 React 类比将不胜感激。
您检测设备方向的方式有误SwiftUI
实现这一点的一种方法是使用自定义修饰符来检测设备旋转:
Cfr: https://www.hackingwithswift.com/quick-start/swiftui/how-to-detect-device-rotation
代码如下所示:
1。创建自定义修饰符:Detecting Device Rotation
// Our custom view modifier to track rotation and call our action
struct DeviceRotationViewModifier: ViewModifier {
let action: (UIDeviceOrientation) -> Void
func body(content: Content) -> some View {
content
.onAppear()
.onReceive(NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification)) { _ in
action(UIDevice.current.orientation)
}
}
}
// A View wrapper to make the modifier easier to use
extension View {
func onRotate(perform action: @escaping (UIDeviceOrientation) -> Void) -> some View {
self.modifier(DeviceRotationViewModifier(action: action))
}
}
2。使用创建的修饰符:
struct ContentView: View {
@State private var isFullscreen = false
@State private var orientation = UIDeviceOrientation.unknown
var body: some View {
NavigationView {
VStack {
// ... content display
}
.onRotate { orientation = [=11=] }
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
if orientation.isLandscape {
Button(action: {}) {
if isFullscreen {
Image(systemName: "arrow.down.right.and.arrow.up.left")
} else {
Image(systemName: "arrow.up.left.and.arrow.down.right")
}
}
}
}
ToolbarItem(placement: .navigationBarTrailing) {
Button(action: {}) {
Image(systemName: "square.and.pencil")
}
}
}
}
}
}
我正在尝试将图标按钮添加到 NavigationView 工具栏的前缘 - 但我希望该按钮仅在设备处于横向模式时可见。 (有点像默认 Notes 应用程序的工作方式)
我有以下代码:
var body: some View {
VStack {
// ... content display
}
.toolbar {
if UIDevice.current.orientation.isLandscape {
ToolbarItem(placement: .navigationBarLeading) {
Button(action: toggleFullscreen) {
if isFullscreen {
Image(systemName: "arrow.down.right.and.arrow.up.left")
} else {
Image(systemName: "arrow.up.left.and.arrow.down.right")
}
}
}
}
ToolbarItem(placement: .navigationBarTrailing) {
Button(action: createNewNote) {
Image(systemName: "square.and.pencil")
}
}
})
}
如果我删除工具栏内容中的条件 if
子句,它可以正常工作,但它似乎根本无法识别 if
语句?
然而,VStack
中的 if
语句工作正常。
我得到的具体错误是:
Closure containing control flow statement cannot be used with result builder 'ToolbarContentBuilder'
知道如何解决这个问题吗?
P.S。将我视为一个完整的 SwiftUI 菜鸟。虽然,我精通 React - 所以任何帮助我理解的 React 类比将不胜感激。
您检测设备方向的方式有误SwiftUI
实现这一点的一种方法是使用自定义修饰符来检测设备旋转:
Cfr: https://www.hackingwithswift.com/quick-start/swiftui/how-to-detect-device-rotation
代码如下所示:
1。创建自定义修饰符:Detecting Device Rotation
// Our custom view modifier to track rotation and call our action
struct DeviceRotationViewModifier: ViewModifier {
let action: (UIDeviceOrientation) -> Void
func body(content: Content) -> some View {
content
.onAppear()
.onReceive(NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification)) { _ in
action(UIDevice.current.orientation)
}
}
}
// A View wrapper to make the modifier easier to use
extension View {
func onRotate(perform action: @escaping (UIDeviceOrientation) -> Void) -> some View {
self.modifier(DeviceRotationViewModifier(action: action))
}
}
2。使用创建的修饰符:
struct ContentView: View {
@State private var isFullscreen = false
@State private var orientation = UIDeviceOrientation.unknown
var body: some View {
NavigationView {
VStack {
// ... content display
}
.onRotate { orientation = [=11=] }
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
if orientation.isLandscape {
Button(action: {}) {
if isFullscreen {
Image(systemName: "arrow.down.right.and.arrow.up.left")
} else {
Image(systemName: "arrow.up.left.and.arrow.down.right")
}
}
}
}
ToolbarItem(placement: .navigationBarTrailing) {
Button(action: {}) {
Image(systemName: "square.and.pencil")
}
}
}
}
}
}