【问题标题】:How to change NSTextField text color on row selection?如何在行选择中更改 NSTextField 文本颜色?
【发布时间】:2012-06-29 20:36:36
【问题描述】:

对于可可,我有一个 NSTableView 设置为基于视图。选择一行后,文本字段的颜色将变为白色。如何保持黑色?

我还应该注意,Highlight 设置为 Source List(它在 Regular 上做同样的事情)。

未选中的行

选中行

我希望类似于 iOS 的状态配置:

这是在 WWDC 2011 Session 120 中提出的,但它有点延迟,所以我不会使用它。不过,它可能对其他人有用。

- (void)tableViewSelectionDidChange:(NSNotification *)notification
{
    [tableView enumerateAvailableRowViewsUsingBlock:^(NSTableRowView *rowView, NSInteger row){
        NSTableCellView *cellView = [rowView viewAtColumn:0];
        if(rowView.selected){
            cellView.textField.font = [NSFont boldSystemFontOfSize:14];
        }else{
            cellView.textField.font = [NSFont systemFontOfSize:14];
        }
    }];
}

【问题讨论】:

  • 谢谢。除非我错过了什么,否则它看起来更像是背景颜色。我已经为我的自定义背景颜色做到了这一点。我正在寻找文本的颜色。
  • 取消选择该行时,文本字段的颜色是否会变回?我试图了解这是如何发生的以及为什么会发生。
  • 是的,他们变回来了。我相信这是正常的行为。我通常会使用 tableView:willDisplayCell:forTableColumn:row: 来更新文本颜色,所以我想我可以检查行选择并更新 tableView:viewForTableColumn:row: 方法中的文本颜色。但是,我希望在 IB 中找到一个设置,可以用来设置选择颜色,比如如何为 iOS 配置控制状态。
  • 您需要在- (void)tableViewSelectionIsChanging:(NSNotification *)aNotification 中执行相同的操作,才能在鼠标选择期间工作。这是你说的延迟吗?

标签: cocoa nstextfield


【解决方案1】:

不需要自定义代码来完成。

只需在 Interface Builder 中将标签的颜色设置为“标签颜色”即可。仅当标签设置了“控制文本颜色”并且位于 NSTableCellView 中时,自动白/黑功能才有效。

【讨论】:

    【解决方案2】:

    根据您需要这样做的原因,有两种方法。

    您可以继承 NSTableRowView 并覆盖 -[NSTableRowView interiorBackgroundStyle] 以返回 NSBackgroundStyleLight。这将告诉单元格它们位于浅色背景上并绘制深色文本,这将是黑色的。

    另一种方法是继承NSTableCellView 并覆盖-[NSTableCellView setBackgroundStyle:] 并在那里自己设置颜色。

    【讨论】:

      【解决方案3】:

      重写 NSTableCellView 并添加此方法以在选择单元格时更改文本颜色。

      - (void) setBackgroundStyle:(NSBackgroundStyle)backgroundStyle
      {
          NSTableRowView *row = (NSTableRowView*)self.superview;
          if (row.isSelected) {
              self.textField.textColor = [NSColor blackColor];
          } else {
              self.textField.textColor = [NSColor whiteColor];
          }
      
      }
      

      【讨论】:

      • 当有选择但窗口不是关键时,这不会正确绘制。 Cocoa 将(从 10.10 开始)绘制灰色背景,但文本字段为黑色,因此自定义控件需要绘制为“非活动”。比较 backgroundStyle != NSBackgroundStyleLight 以确定控件是否应该被绘制为活动的似乎是关键。
      【解决方案4】:

      我想出了一个不同的解决方案。如果 Cocoa 支持 @IBOutletCollection,子类化 NSTableCellView 会很好。因为那时我可以有一个 Cell 子类,其中包含单元格中所有 NSTextFields 的数组。但由于我有多种类型的单元格和不同数量的 NSTextField,我不喜欢这个选项。相反,我查看了 Apple 关于 NSTableCellView 中 backgroundStyle 属性的文档。

      默认实现自动将调用转发到所有实现 setBackgroundStyle: 或者是 NSControl 的子视图,这些子视图具有响应 backgroundStyle 的 NSCell 类。

      如果我的 TextFields 实现了 setBackgroundStyle,那么它们应该在单元格选择发生变化时得到通知。但是,背景样式的这种转发不是递归的。因为我的 NSTextFields 在 NSStackViews 中,所以他们没有收到消息。为了解决这个问题,我刚刚编写了一个扩展来在所有 NSView 上实现 setBackgroundStyle。它只是转发消息。最后,我为 NSTextField 添加了一个扩展来实现这个方法。从这个扩展中,我改变了文本颜色并调用了 super。这个解决方案也很好,因为不需要子类。没有 NSTableCellView 或 NSTextField 的子类。

      将此功能添加到所有视图和所有 NSTextFields 可能会导致不在 NSTableViews 中的 NSTextFields 出现意外更改颜色的问题。但到目前为止,只有我的 TableViews/OutlineViews 中的那些正在改变颜色,而这正是我正在寻找的。如果您看到文本字段更改了您不期望的颜色,您可能希望继承 NSTextField 并仅在该子类上实现 setBackgroundStyle 覆盖,而不是将其添加到所有 NSTextFields。

      我使用的 Swift 3 中的代码粘贴在下面。

      extension NSView {
          func setBackgroundStyle(_ newValue: NSBackgroundStyle) {
              for view in self.subviews {
                  view.setBackgroundStyle(newValue)
              }
          }
      }
      
      extension NSTextField {
          override func setBackgroundStyle(_ newValue: NSBackgroundStyle) {
              switch newValue {
              case .dark:
                  self.textColor = NSColor.controlLightHighlightColor
              case .light, .lowered, .raised:
                  self.textColor = NSColor.labelColor
              }
              super.setBackgroundStyle(newValue)
          }
      }
      

      【讨论】:

      • 谢谢,这将解决我遇到的类似问题。但是我认为对所有 NSView 进行扩展过于宽泛。不是更好的解决方案是将 NSStackView 子类化以传递此消息并在有此问题的 NSTableCellViews 上使用它吗?
      【解决方案5】:

      对于我的 Swift 应用程序,上述方法似乎都不能正常工作。此方法正确处理 NSTableView 失去焦点,当窗口不是关键窗口但仍选中单元格时。

      NSTableCellView 子类中使用以下内容:

      override var backgroundStyle: NSView.BackgroundStyle {
        willSet {
          if newValue == .dark {
            title.textColor = NSColor.white
          } else {
            title.textColor = NSColor.labelColor
          }
        }
      }
      

      【讨论】:

        【解决方案6】:

        根据@sabes 的回答,我创建了这个NSTextFieldCell 子类,您可以在选择或取消选择一行时使用它来设置自定义文本颜色。您可以在IB中设置相关文本字段单元格的子类。

        @interface SNBlueTextFieldCell : NSTextFieldCell
        
        @end
        
        @implementation SNBlueTextFieldCell
        
        - (void)setBackgroundStyle:(NSBackgroundStyle)backgroundStyle {
            [self setTextColor:(backgroundStyle==NSBackgroundStyleDark ? [NSColor blackColor] : [NSColor blueColor])];
        }
        
        @end
        

        【讨论】:

          【解决方案7】:

          在 macOS 11 或更高版本中,.dark.light 背景样式已弃用。但你可以改用.emphased

          override var backgroundStyle: NSView.BackgroundStyle {
              willSet {
                  textField.textColor = newValue == .emphasized ? .labelColor : .secondaryLabelColor
              }
          }
          

          在示例中,.labelColor 是选中的颜色,.secondaryLabelColor 是未选中的颜色。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-11-23
            • 2023-01-12
            相关资源
            最近更新 更多