Как изменить цвет текста NSTextField при выборе строки?

для какао, у меня есть NSTableView установить на основе представления. При выборе строки текстовые поля изменяют свой цвет на белый. Как мне сохранить его черным?

Я также должен отметить, что выделение установлено в список источников (он делает то же самое на регулярной основе). Highlight Setting

невыбранные строки Unselected

Выбранной Строки Selected Row

Я надеялся на что-то похожее на государство config для iOS:

enter image description here

Это было предложено в сеансе WWDC 2011 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];
        }
    }];
}

6 ответов


в зависимости от того, почему вам нужно это сделать, есть 2 подхода.

вы можете подкласс NSTableRowView и переопределить -[NSTableRowView interiorBackgroundStyle] вернуться NSBackgroundStyleLight. Это скажет клеткам, что они находятся на светлом фоне и нарисовать темный текст, который будет черным.

другой способ-подкласс NSTableCellView и заменить -[NSTableCellView setBackgroundStyle:] и установите цвета сами там.


переопределите NSTableCellView и добавьте этот метод, чтобы изменить цвет текста при выборе ячейки.

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

}

для этого нет необходимости в пользовательском коде.

просто установите цвет метки в" цвет метки " в Interface Builder. Автоматическая белая / черная вещь работает только в том случае, если метка имеет набор "цвет текста управления" и находится в NSTableCellView.


Я придумал другое решение. Подклассы NSTableCellView были бы прекрасны, если бы Cocoa поддерживал @IBOutletCollection. Потому что тогда у меня может быть один подкласс ячейки, который имеет массив всех NSTextFields в ячейке. Но поскольку у меня было много видов ячеек с различным количеством NSTextFields, мне не понравился этот вариант. Вместо этого я взглянул на документацию Apple для backgroundStyle свойство в NSTableCellView.

реализация по умолчанию автоматически пересылает вызовы ко всем подвидам, реализующим setBackgroundStyle: или являются NSControl, которые имеют классы NSCell, которые отвечают backgroundStyle.

Если мои текстовые поля реализуют setBackgroundStyle, они должны получать уведомления при изменении выбора ячейки. Однако такая переадресация фонового стиля не является рекурсивной. Поскольку мои NSTextFields были в пределах NSStackViews, они не получали сообщение. Чтобы обойти это, я просто написал расширение для реализации setBackgroundStyle на всех NSViews. Он просто пересылает сообщение. Наконец, я добавил расширение в NSTextField, чтобы также реализовать этот метод. Из этого расширения я меняю цвет текста и вызываю super. Это решение также приятно, потому что подклассы не нужны. Нет подклассов NSTableCellView или NSTextField.

добавление этой функции ко всем представлениям и ко всем полям NSTextFields может вызвать проблемы с полями NSTextFields, которые не находятся в пределах NSTableViews, неожиданно меняя цвет. Но пока только те, что в моем TableViews/OutlineViews меняются цвета и thats точно, что я искал. Если вы видите, что текстовые поля меняют цвет, который вы не ожидаете, может потребоваться подкласс 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)
    }
}

для моего приложения Swift ни одно из вышеперечисленных, казалось, не работает правильно. Этот метод обрабатывает nstableview потери фокуса правильно и когда окно не является ключевым окном, но ячейка по-прежнему выбрана.

внутри NSTableCellView подкласс используйте следующее:

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

основываясь на ответе @sabes, я создал это NSTextFieldCell подкласс, который можно использовать для установки пользовательских цветов текста при выборе или отмене строки. Вы можете установить подкласс соответствующей ячейки текстового поля В IB.

@interface SNBlueTextFieldCell : NSTextFieldCell

@end

@implementation SNBlueTextFieldCell

- (void)setBackgroundStyle:(NSBackgroundStyle)backgroundStyle {
    [self setTextColor:(backgroundStyle==NSBackgroundStyleDark ? [NSColor blackColor] : [NSColor blueColor])];
}

@end