更改搜索栏的图标

时间:2018-10-13 11:07:10

标签: swift cocoa nsimage nssearchfield

我尝试实现类似Xcode的搜索行为:如果您在搜索字段中输入内容,图标就会更改颜色。

我将 searchFieldDidStartSearching searchFieldDidEndSearching 委托给控制器并更改图像。 问题在于图标的图像仅在窗口失去焦点时才会更改。

enter image description here

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.
        }
    }
}

预先感谢您的任何想法/建议。

4 个答案:

答案 0 :(得分:0)

如您所见,当您在视图内单击时,它仍然集中在搜索文本字段上(因为单击它下方仍可以在其中键入内容)。由于更改图像失去焦点时会亮起,因此您应该检查是否在文本字段之外单击。

答案 1 :(得分:0)

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

答案 2 :(得分:0)

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

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
    }
}

答案 3 :(得分:0)

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

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