swift 更改搜索字段的图标

tyu7yeag  于 2023-01-19  发布在  Swift
关注(0)|答案(5)|浏览(125)

我尝试像在Xcode中那样实现搜索行为:如果您在搜索字段中输入内容,图标颜色会发生变化。
我将 searchFieldDidStartSearchingsearchFieldDidEndSearching 委托给控制器并更改图像。问题是只有当窗口失去焦点时图标的图像才会更改。

class ViewController: NSViewController {
    @IBOutlet weak var searchField: NSSearchField!

    func searchFieldDidStartSearching(_ sender: NSSearchField) {
        print("\(#function)")

        (searchField.cell as! NSSearchFieldCell).searchButtonCell?.image = NSImage.init(named: "NSActionTemplate")
    }

    func searchFieldDidEndSearching(_ sender: NSSearchField) {
        print("\(#function)")

        (searchField.cell as! NSSearchFieldCell).searchButtonCell?.image = NSImage.init(named: "NSHomeTemplate")
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
    }

    override var representedObject: Any? {
        didSet {
        // Update the view, if already loaded.
        }
    }
}

提前感谢您的任何想法/建议。

iswrvxsc

iswrvxsc1#

虽然我不知道原因,但它起作用了:

NSApp.mainWindow?.resignMain()
NSApp.mainWindow?.becomeMain()

下面是完整的代码:

class MyViewController: NSViewController {
    private lazy var searchField: NSSearchField = {
        let searchField = NSSearchField(string: "")

        if let searchButtonCell = searchField.searchButtonCell {
            searchButtonCell.setButtonType(.toggle)
            let filterImage = #imageLiteral(resourceName: "filter")
            searchButtonCell.image = filterImage.tinted(with: .systemGray)
            searchButtonCell.alternateImage = filterImage.tinted(with: .systemBlue)
        }
        searchField.focusRingType = .none
        searchField.bezelStyle = .roundedBezel
        searchField.delegate = self

        return searchField
    }()

    ...
}

extension MyViewController: NSSearchFieldDelegate {
    func searchFieldDidStartSearching(_ sender: NSSearchField) {
        sender.searchable = true
    }

    func searchFieldDidEndSearching(_ sender: NSSearchField) {
        sender.searchable = false
    }
}

extension NSSearchField {
    var searchButtonCell: NSButtonCell? {
        (self.cell as? NSSearchFieldCell)?.searchButtonCell
    }

    var searchable: Bool {
        get {
            self.searchButtonCell?.state == .on
        }

        set {
            self.searchButtonCell?.state = newValue ? .on : .off
            self.refreshSearchIcon()
        }
    }

    private func refreshSearchIcon() {
        NSApp.mainWindow?.resignMain()
        NSApp.mainWindow?.becomeMain()
    }
}

extension NSImage {
    func tinted(with color: NSColor) -> NSImage? {
        guard let image = self.copy() as? NSImage else { return nil }
        image.lockFocus()
        color.set()
        NSRect(origin: NSZeroPoint, size: self.size).fill(using: .sourceAtop)
        image.unlockFocus()
        image.isTemplate = false
        return image
    }
}
tez616oj

tez616oj2#

我也遇到了同样的问题。一个简单的覆盖为我解决了这个问题

extension NSSearchField{
    open override func draw(_ dirtyRect: NSRect) {
        super.draw(dirtyRect)
    }
}
6ovsh4lw

6ovsh4lw3#

正如你所看到的,当你点击视图内部时,它仍然聚焦在搜索文本字段上(就像你在它下面点击后仍然可以输入一样)。由于当它失去焦点时,改变图像是打开的,你应该检查一下你是否点击了文本字段的外部。

rbl8hiat

rbl8hiat4#

通过子类化 NSSearchFieldCell 并将该类分配给字段的单元格来解决问题。

nqwrtyyt

nqwrtyyt5#

你甚至不需要子类化NSSearchFieldCell,当你从代码中创建你的NSSearchField时,你可以这样做:

if let searchFieldCell = searchField.cell as? NSSearchFieldCell {
    let image = NSImage(named: "YourImageName")
    searchFieldCell.searchButtonCell?.image = image
    searchFieldCell.searchButtonCell?.alternateImage = image // Optionally
}

如果你使用的是故事板,你可以在@IBOutletdidSet中做同样的事情。

相关问题