VisionOS中Popover内使用ColorPicker报错‘不允许空间呈现’,求解决方案
解决VisionOS Popover中使用ColorPicker触发“Spatial presentations are not permitted”异常的方案
在VisionOS应用的Popover中使用系统ColorPicker时,选择颜色会抛出异常:Spatial presentations are not permitted from popovers,但其他选择器(如数字列表)可正常工作。这是因为系统ColorPicker默认采用空间化展示界面,而Popover容器不允许从内部触发空间展示。
以下是两种可行的解决方案:
方案一:自定义简化颜色选择器
通过创建自定义的颜色选择器,使用预设颜色网格替代系统组件,避免触发空间展示:
struct CustomColorPicker: View { @Binding var selectedColor: Color // 可根据需求扩展颜色列表 let colors: [Color] = [.red, .green, .blue, .yellow, .purple, .orange, .pink, .gray] var body: some View { VStack(spacing: 12) { Text("选择颜色") .font(.headline) LazyVGrid(columns: [GridItem(.adaptive(minimum: 50))], spacing: 12) { ForEach(colors, id: \.self) { color in Button { selectedColor = color } label: { Circle() .fill(color) .frame(width: 40, height: 40) .overlay(selectedColor == color ? Circle().stroke(.white, lineWidth: 3) : nil) } } } } .padding() } }
在ContentView中替换系统ColorPicker:
struct ContentView: View { @State var popoverPresented = false @State var color: Color = .red var body: some View { VStack { Button("Show Popover") { popoverPresented = true } .popover(isPresented: $popoverPresented) { CustomColorPicker(selectedColor: $color) } } } }
方案二:使用UIKit颜色选择器包装视图
如果需要完整的颜色选择功能(包括自定义颜色),可以将UIKit的UIColorPickerViewController包装为SwiftUI视图,它不会触发空间展示:
struct UIKitColorPicker: UIViewControllerRepresentable { @Binding var selectedColor: Color @Binding var isPresented: Bool func makeUIViewController(context: Context) -> UIColorPickerViewController { let picker = UIColorPickerViewController() picker.delegate = context.coordinator picker.selectedColor = UIColor(selectedColor) return picker } func updateUIViewController(_ uiViewController: UIColorPickerViewController, context: Context) { uiViewController.selectedColor = UIColor(selectedColor) } func makeCoordinator() -> Coordinator { Coordinator(self) } class Coordinator: NSObject, UIColorPickerViewControllerDelegate { let parent: UIKitColorPicker init(_ parent: UIKitColorPicker) { self.parent = parent } func colorPickerViewControllerDidSelectColor(_ viewController: UIColorPickerViewController) { parent.selectedColor = Color(viewController.selectedColor) } func colorPickerViewControllerDidFinish(_ viewController: UIColorPickerViewController) { parent.isPresented = false } } }
修改ContentView,通过按钮触发该选择器:
struct ContentView: View { @State var popoverPresented = false @State var colorPickerPresented = false @State var color: Color = .red var body: some View { VStack { Button("Show Popover") { popoverPresented = true } .popover(isPresented: $popoverPresented) { VStack(spacing: 20) { Text("当前颜色") .font(.headline) Circle() .fill(color) .frame(width: 60, height: 60) Button("选择颜色") { colorPickerPresented = true } .buttonStyle(.borderedProminent) } .padding() .sheet(isPresented: $colorPickerPresented) { UIKitColorPicker(selectedColor: $color, isPresented: $colorPickerPresented) } } } } }
内容的提问来源于stack exchange,提问作者Ethan
相关产品推荐
相关产品推荐

