操作NSTableView时更新NSTextField 实现类Spotlight的双控件聚焦效果
解决方案
要实现Spotlight的双控件同步聚焦效果,只需两步处理,分别解决选中状态灰化和焦点抢夺的问题:
1. 强制表格选中行始终显示活跃高亮
默认NSTableView只有自身为第一响应者时选中行才会显示蓝色高亮,失去焦点时会变为灰选状态,我们可以通过自定义NSTableRowView强制高亮始终为活跃状态:
// 自定义行视图,始终返回活跃强调状态 class AlwaysEmphasizedTableRowView: NSTableRowView { override var isEmphasized: Bool { get { true } set {} } }
在表格的delegate中替换默认行视图:
func tableView(_ tableView: NSTableView, rowViewForRow row: Int) -> NSTableRowView? { let reuseId = NSUserInterfaceItemIdentifier("AlwaysEmphasizedRow") guard let rowView = tableView.makeView(withIdentifier: reuseId, owner: self) as? AlwaysEmphasizedTableRowView else { let newRowView = AlwaysEmphasizedTableRowView() newRowView.identifier = reuseId return newRowView } return rowView }
2. 阻止表格抢夺文本框焦点
子类化NSTableView,禁止其成为第一响应者,同时手动处理鼠标点击选中逻辑:
class NoFocusTableView: NSTableView { // 拒绝成为第一响应者,不会抢走文本框的输入焦点 override var acceptsFirstResponder: Bool { false } override func mouseDown(with event: NSEvent) { let clickPoint = convert(event.locationInWindow, from: nil) let targetRow = row(at: clickPoint) guard targetRow >= 0 else { super.mouseDown(with: event) return } // 手动选中点击的行 selectRowIndexes(IndexSet(integer: targetRow), byExtendingSelection: false) // 若需要支持点击行直接触发操作(比如跳转、打开文件等),可在此处添加对应逻辑 } }
最后在Interface Builder或代码中把你的NSTableView的自定义类设置为NoFocusTableView即可。
额外补充
你的方向键选中逻辑已经可以直接复用,因为焦点始终停留在NSTextField,用户的所有键盘输入都会被文本框捕获,不会出现焦点切换问题。如果需要支持回车触发选中行的操作,直接在NSTextField的control:textView:doCommandBySelector:代理方法中监听回车事件,读取当前表格选中行处理即可。
内容的提问来源于stack exchange,提问作者glocore
相关产品推荐
相关产品推荐

