禁用特定的选择器项目

Posted

技术标签:

【中文标题】禁用特定的选择器项目【英文标题】:Disable specific picker items 【发布时间】:2020-01-15 09:14:15 【问题描述】:

有没有办法?在 AppKit 中,您可以通过 NSMenuValidation 协议禁用 NSPopUpButton 项目,但可以预见的是,禁用选择器中的标签没有任何作用。只是 SwiftUI 中的另一个 API 缺口?

我试过了:

Picker(selection: $viewModel.providerSelection, label: Text("Try using:")) 
    ForEach(0..<Provider.allCases.count) 
        Text(Provider.allCases[$0].rawValue.capitalized)
            .disabled(true)
    

禁用和不使用在视觉或交互上没有区别。

【问题讨论】:

不确定此评论的相关性。视图构建器使用Int,作为$0 这里有同样的问题。我记得能够做到这一点,可能是 Xcode/swift 中的一个错误 这仍然不固定或不可用吗?还是有其他方法可以做到这一点? @Procrastin8 你有没有找到实现这一目标的方法? 【参考方案1】:

这似乎目前在纯 SwiftUI 中不支持。但是,您可以尝试将NSPopUpButton 包装在NSViewRepresentable 中,如下所示:

    /// SwiftUI wrapper for NSPopUpButton which allows items to be disabled, which is currently not supported in SwiftUI's Picker
struct PopUpButtonPicker<Item: Equatable>: NSViewRepresentable 

    final class Coordinator: NSObject 
        private let parent: PopUpButtonPicker

        init(parent: PopUpButtonPicker) 
            self.parent = parent
        

        @IBAction
        func selectItem(_ sender: NSPopUpButton) 
            let selectedItem = self.parent.items[sender.indexOfSelectedItem]
            print("selected item \(selectedItem) at index=\(sender.indexOfSelectedItem)")
            self.parent.selection = selectedItem
        
    

    let items: [Item]
    var isItemEnabled: (Item) -> Bool =  _ in true 
    @Binding var selection: Item
    let titleProvider: (Item) -> String

    func makeCoordinator() -> Coordinator 
        Coordinator(parent: self)
    

    func makeNSView(context: Self.Context) -> NSPopUpButton 
        let popUpButton = NSPopUpButton(frame: .zero, pullsDown: false)
        popUpButton.autoenablesItems = false
        popUpButton.target = context.coordinator
        popUpButton.action = #selector(Coordinator.selectItem(_:))

        for item in items.enumerated() 
            popUpButton.addItem(withTitle: self.titleProvider(item.element))
            // in order for this to work, autoenablesItems must be set to false
            popUpButton.menu?.item(at: item.offset)?.isEnabled = self.isItemEnabled(item.element)
        

        if let selectedIndex = self.items.firstIndex(where:  $0 == self.selection ) 
            popUpButton.selectItem(at: selectedIndex)
        

        return popUpButton
    

    func updateNSView(_ view: NSPopUpButton, context: Self.Context)  



// MARK: - Usage

struct ContentView: View 

    private let items: [Int] = [1, 2, 3, 4, 5]
    @State private var selectedValue: Int = 0

    var body: some View 
        PopUpButtonPicker(items: self.items, isItemEnabled:  $0 != 4 , selection: self.$selectedValue, titleProvider: String.init)
    

【讨论】:

以上是关于禁用特定的选择器项目的主要内容,如果未能解决你的问题,请参考以下文章

在 Android 日期选择器中禁用特定日期

Android - 如何在一个活动中禁用多个微调器的特定项目

如何在蚂蚁设计日期选择器中禁用所有星期日和特定日期数组

在我当前的日期选择器代码中禁用特定日期的最快方法?

反应本机 NATIVE BASE 选择器如何禁用选择器项目

我在表单中使用了日期范围选择器如何禁用从 MySQL 数据库中获取的特定日期范围