objective-c - 如何在 MAC OS X 应用程序中更改 NSTableView 标题背景颜色?

标签 objective-c xcode cocoa nstableview

我尝试了所有找到的建议解决方案,但最终将此作为最接近的解决方案:

enter image description here

目标是为以下内容提供自定义颜色:

  1. 完整的标题背景(例如绿色)
  2. 文字(例如白色)
  3. 对控件颜色进行排序(例如白色)

目前我只能正确设置内部背景和文本颜色,同时将标题边框和排序控件保留为默认白色。

我使用自定义NCTableHeaderCell的方法。

// <C> changing the bgColor doesn't work this way
[self.tv.headerView setWantsLayer:YES];
self.tv.headerView.layer.backgroundColor = NSColor.redColor.CGColor;

for (NSTableColumn *tc in self.tv.tableColumns) {

    // <C> this only helps to change the header text color
    tc.headerCell = [[NCTableHeaderCell_customizable alloc]initTextCell:@"Hdr"];

    // <C> this changes the bgColor of the area of the headerCell label text (the interior) but it leaves border and sort controls in white color;
    tc.headerCell.drawsBackground = YES;
    tc.headerCell.backgroundColor = NSColor.greenColor;

    // <C> changing the textColor doesn't work this way
    // <SOLUTION> use NCTableHeaderCell_customizable as done above;
    tc.headerCell.textColor = NSColor.redColor;
}

我的自定义类如下所示:

@implementation NCTableHeaderCell_customizable

// <C> this works as expected
- (NSColor *) textColor
{
    return NSColor.whiteColor;
}

// <C> this only sets the interior bgColor leaving the borders in standard color
//
//- (NSColor *) backgroundColor
//{
//    return NSColor.redColor;
//}

- (void) drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView;
{
    // <C> this only sets the interior bgColor leaving the borders in standard color
    //
    //self.backgroundColor = NSColor.orangeColor;

    [super drawWithFrame:cellFrame inView:controlView];

    // <C> this draws the red bg as expected but doesn't show the interior;
    //
    //    [NSColor.redColor set];
    //    NSRectFillUsingOperation(cellFrame, NSCompositingOperationSourceOver);

    // <C> this draws the red bg as expected but
    //     1) doesn't layout the interior well (I could fix this);
    //     2) doesn't show the sort controls (it's over-drawn with the code bellow);
    //
    //    [NSColor.redColor setFill];
    //    NSRectFill(cellFrame);
    //    CGRect titleRect = [self titleRectForBounds:cellFrame];
    //    [self.attributedStringValue drawInRect:titleRect];
}

- (void) drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView;
{
    [super drawInteriorWithFrame:cellFrame inView:controlView];
}

- (void) drawFocusRingMaskWithFrame:(NSRect)cellFrame inView:(NSView *)controlView;
{
    [super drawFocusRingMaskWithFrame:cellFrame inView:controlView];
}

- (void) drawSortIndicatorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView ascending:(BOOL)ascending priority:(NSInteger)priority;
{
    [super drawSortIndicatorWithFrame:cellFrame inView:controlView ascending:ascending priority:priority];
    //NSTableHeaderView *v = (NSTableHeaderView *)controlView;
}

我非常接近解决方案,但我不知道如何正确绘制自定义标题单元格来存档目标。

最佳答案

像下面一样创建 NSTableHeaderCell 并使用标题单元格的框架大小和原点:

#import <Cocoa/Cocoa.h>

@interface CustomTableHeaderCell : NSTableHeaderCell {
    NSMutableDictionary *attrs;
}

#import "CustomTableHeaderCell.h"

@implementation CustomTableHeaderCell

- (id)initTextCell:(NSString *)text
{
    if (self = [super initTextCell:text]) {

        if (text == nil || [text isEqualToString:@""]) {
            [self setTitle:@"One"];
        }

        /* old_
        self.textColor = [NSColor blackColor];
         */
        // new_
        self.textColor = [NSColor whiteColor];


        attrs = [[NSMutableDictionary dictionaryWithDictionary:
                  [[self attributedStringValue]
                   attributesAtIndex:0
                   effectiveRange:NULL]]
                 mutableCopy];
//        self.font = [NSFont fontWithName:appleeH8GhKr0 size:12];
        return self;
    }
    return nil;
}

- (void)drawWithFrame:(NSRect)cellFrame
          highlighted:(BOOL)isHighlighted
               inView:(NSView *)view
{
    CGRect fillRect, borderRect;
    CGRectDivide(NSRectToCGRect(cellFrame), &borderRect, &fillRect, 1.0, CGRectMaxYEdge);

    // sets the origin and frame for header's title
//    fillRect.size.height = 25;

    if (fillRect.origin.x == 0)
    {
//        fillRect.origin.y += 5;
       // for adding left margin to first column title try to add spaces in text of header title
       // try to play with the numbers of fillRect rect
    }
    else if (fillRect.origin.x == 239)
    {
//        fillRect.size.width  -= 80;
    }

    // setting the background color of tableview's header view
    NSGradient *gradient = [[NSGradient alloc]
                            initWithStartingColor:[NSColor greenColor]
                            endingColor:[NSColor greenColor]];
    [gradient drawInRect:NSRectFromCGRect(fillRect) angle:90.0];
    [self drawInteriorWithFrame:NSRectFromCGRect(CGRectInset(fillRect, 0.0, 1.0)) inView:view];
 }


- (NSRect)adjustedFrameToVerticallyCenterText:(NSRect)frame
{
    // super would normally draw text at the top of the cell
    NSInteger offsetY = floor((NSHeight(frame) -
                              ([[self font] ascender] - [[self font] descender])) / 2);
    return NSInsetRect(frame, 20, offsetY);
}

-(void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView{
    [super drawInteriorWithFrame:[self adjustedFrameToVerticallyCenterText:cellFrame]
                          inView:controlView];
}

- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)view
{
    [self drawWithFrame:cellFrame highlighted:NO inView:view];
}

- (void)highlight:(BOOL)isHighlighted
        withFrame:(NSRect)cellFrame
           inView:(NSView *)view
{
    [self drawWithFrame:cellFrame highlighted:isHighlighted inView:view];
}

设置列的标题单元格,如下所示:

NSArray *columns = nil;
    if(self.tblVc)
        columns = [self.tblVc tableColumns];
    NSEnumerator *cols = [columns objectEnumerator];
    NSTableColumn *col = nil;
    CustomTableHeaderCell *headerCell;

    while (col = [cols nextObject]) {
        NSString *key = [[col headerCell] stringValue];
        headerCell = [[CustomTableHeaderCell alloc]
                      initTextCell:key];

        NSRect rectHeader =self.tblVc.headerView.frame;
        rectHeader.size.height = 25;
        self.tblVc.headerView.frame=rectHeader;

        [col setHeaderCell:headerCell];
    }

并使用表格 View 标题顶部的公开按钮,如下所示:

storyboard arrangement of sort button

它将显示如下结果:

custom header with coloured background

关于objective-c - 如何在 MAC OS X 应用程序中更改 NSTableView 标题背景颜色?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52315708/

相关文章:

ios - FontAwesome 图标仅在 Release模式下崩溃

ios - 应用程序在 iOS 13 上崩溃,因为从 -traitCollection 返回 nil,这是不允许的

objective-c - 如何将指针的地址传递给线程而不首先超出范围?

cocoa - 将文档保存为文件夹,例如 Pages、Numbers 等

ios - 应用图层蒙版后我的图像按比例缩小

ios - 无法在iOS10中以编程方式进行本地调用

objective-c - NSFetchedResultsController 和 UITableViewController 不通信

ios - 导航栏颜色 ios 7

objective-c - 如何从 Objective-C 登录电子邮件提供商?

objective-c - 如何在 drawRect 中为 NSTextField 或 NSTextVew 实现自定义聚焦环