【问题标题】:NSTableView selected row flickering while scrolling with arrow keysNSTableView 选择的行在使用箭头键滚动时闪烁
【发布时间】:2020-11-12 12:28:41
【问题描述】:

我有一个基于视图的 NSTableView,但不知道如何解决当前选定的行在使用箭头键向上或向下滚动时闪烁的视觉故障。

根据滚动方向,所选行应“粘合”到视图的顶部或底部。 Finder 在列表视图中显示了这种正确的行为,但常规的表视图似乎并不是开箱即用的。我很困惑为什么会这样,并且看不到明显的方法来规避它。谁能指出可能的原因/解决方案?

编辑编号 1

默认情况下,基于单元格的 NSTableView 以所需的方式运行,因此这可能是特定于基于视图的实现的错误。不过,出于不相关的原因,我不想使用基于单元格的表格。

2号编辑

我已经尝试让表格视图的父视图层支持,以及拦截向上/向下箭头键击以进行我自己的滚动,但到目前为止我还无法消除闪烁。

第 3 号编辑

我创建了一个小sample project 来重现该问题。

【问题讨论】:

  • 如果你给我们一个能重现问题的最小应用程序,那真的很有帮助。把它放在 GitHub 上,给我们一个链接。
  • @jvarela 我添加了一个显示问题的示例项目。
  • 我能够重现您的错误。实际上,即使是我自己的表格代码也显示了这个错误,这是我从未注意到的。我什至检查了 Apple 的示例代码,他们也有同样的问题。也许解决问题的唯一方法是自定义选择的绘制方式。我尝试通过覆盖 NSTableRowView drawSelection(in:) 来自定义此绘图,但使用 NSRect fill() 方法会导致相同的闪烁。或许你应该打开一个 DTS 事件并询问 Apple 如何解决这个 bug。
  • Big Sur 上也会闪烁(测试版 3)。
  • 看起来选择发生了变化,并且重新绘制了新旧选定行。接下来选定的行向上/向下动画。禁用滚动动画可以解决问题。

标签: xcode macos nstableview appkit


【解决方案1】:

看起来选择发生了变化,并且重新绘制了新旧选定行。接下来选定的行向上/向下动画。禁用滚动动画可解决此问题。滚动动画可以通过继承 NSClipView 并覆盖 scroll(to:) 来禁用。

override func scroll(to newOrigin: NSPoint) {
    setBoundsOrigin(newOrigin)      
}

可能会有一些副作用。

编辑

从 zrzka 的解决方案中复制,并进行了一些调整。使用向上箭头或向下箭头键时,滚动动画暂时被禁用。

class TableView: NSTableView {

    override func keyDown(with event: NSEvent) {
        if let clipView = enclosingScrollView?.contentView as? ClipView,
            (125...126).contains(event.keyCode) && // down arrow and up arrow
            event.modifierFlags.intersection([.option, .shift]).isEmpty {
            clipView.isScrollAnimationEnabled = false
            super.keyDown(with: event)
            clipView.isScrollAnimationEnabled = true
        }
        else {
            super.keyDown(with: event)
        }
    }
    
}

class ClipView: NSClipView {

    var isScrollAnimationEnabled: Bool = true
    
    override func scroll(to newOrigin: NSPoint) {
        if isScrollAnimationEnabled {
            super.scroll(to: newOrigin)
        } else {
            setBoundsOrigin(newOrigin)
            documentView?.enclosingScrollView?.flashScrollers()
        }
    }
    
}

【讨论】:

  • 一个是 Home / End 键滚动没有动画效果(如果你没有全键盘,它与 Fn + Left Arrow / Fn + Right Arrow 相同)。
  • 非常感谢,这行得通!也许这个答案可以建立在允许 home / end 仍然是动画的基础上,但我很高兴按原样使用它。
  • 仅供参考 - 我为此花费了我的 TSI(技术支持事件)。我只是好奇苹果人推荐/认为什么。 DTS 将我的 TSI 还给了我,并告诉我提交错误报告。做到了(FB8249979)。
【解决方案2】:

你有没有尝试改变视图?

scrollView.wantsLayer = true

如果您使用了界面生成器:

选择滚动视图 打开 View Effects Inspector(或按 Cmd-Opt-8) 在表格中,找到滚动视图所在的行并选中该框。

【讨论】:

  • 是的,我确实尝试过。没有任何明显的区别,仍然闪烁。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-06
  • 2023-03-18
  • 2015-07-22
  • 2011-05-16
相关资源
最近更新 更多