带有活动标签的“ColorPicker”?

`ColorPicker` with active label?

考虑以下代码:

struct ContentView: View {
    @State var color: Color = .blue
    var body: some View {
        ColorPicker(selection: $color) {
            Label("Pallete", systemImage: "paintpalette")
        }
    }
}

如果您点击色环,它会弹出一个颜色选择器模式视图。我希望标签上的点击也能发生同样的情况。

这些是我们可以随心所欲地使用花哨的系统颜色选择器的方法,但是从 iOS15 开始,它需要与 UIKit 一起使用。

像这样创建一个新的视图结构:

import SwiftUI

struct ColorPickerPanel: UIViewControllerRepresentable {
    @Binding var color: Color
    
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
    
    func makeUIViewController(context: Context) -> UIColorPickerViewController {
        let picker = UIColorPickerViewController()
        picker.delegate = context.coordinator
        return picker
    }
    
    func updateUIViewController(_ picker: UIColorPickerViewController, context: Context) {
        picker.selectedColor = UIColor(color)
    }
    
    class Coordinator: NSObject, UIColorPickerViewControllerDelegate {
        var parent: ColorPickerPanel
        
        init(_ pageViewController: ColorPickerPanel) {
            self.parent = pageViewController
        }
        
        func colorPickerViewControllerDidSelectColor(_ viewController: UIColorPickerViewController) {
            parent.color = Color(uiColor: viewController.selectedColor)
        }
    }
}

然后像这样使用它:

struct ContentView: View {
    @State var color: Color = .accentColor
    @State var isColorPickerPresented = false
    var body: some View {
        VStack {
            Button {
                isColorPickerPresented = true
            } label: {
                ColorPicker(selection: $color) {
                    Label("Pallete", systemImage: "paintpalette")
                        .allowsHitTesting(true)
                        .accessibilityAddTraits(.isButton)
                }
            }
        }
        .sheet(isPresented: $isColorPickerPresented) {
            ZStack (alignment: .topTrailing) {
                ColorPickerPanel(color: $color)
                Button {
                    isColorPickerPresented = false
                } label: {
                    Image(systemName: "xmark.circle.fill")
                        .foregroundStyle(.tint, .secondary)
                        .font(.title)
                }
                .offset(x: -10, y: 10)
            }
        }
    }
}

当然,您可以提供另一个关闭选择器。