【问题标题】:Semi-transparent NSTableView background drawing bug during animation动画期间半透明NSTableView背景绘制错误
【发布时间】:2014-08-19 07:21:50
【问题描述】:

我有一个基于视图的NSTableView,其背景为半透明。这工作正常,除了在行动画期间。如果我为NSTableView 背景使用完全不透明的颜色,则没有问题。这是一个显示问题的 gif:

http://gfycat.com/ChillyVigorousChamois

正如 gif 所示,在动画期间,背景会闪烁比应有的更深的红色。如果仔细观察,实际上有一部分背景绘制正确,它向下滑动以容纳新添加的行。

NSTableView 后面的NSScrollView 是纯白色的,由以下代码设置:

-(void) awakeFromNib {
    self.drawsBackground = YES;
    self.backgroundColor = [NSColor whiteColor];
}

NSTableView 有 50% 透明的红色背景,如下代码所示:

-(BOOL) isOpaque {
    return NO;
}

- (void)drawBackgroundInClipRect:(NSRect)clipRect {
    [[[NSColor redColor] colorWithAlphaComponent:0.5] setFill];
    NSRectFillUsingOperation(clipRect, NSCompositeSourceOver);
}

使用以下代码对行进行动画处理:

[_tableView insertRowsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:insertRange]
                  withAnimation:NSTableViewAnimationSlideLeft];

目前我最好的猜测是变暗是因为在动画过程中背景被反复绘制在其顶部。过去,我通过将父视图添加到 NSAnimation 来修复类似的错误,这会迫使它与动画子视图一起重复重绘。在这种情况下,我不确定如何做同样的事情。

任何想法如何解决这个问题?

【问题讨论】:

    标签: objective-c cocoa core-animation osx-mavericks nstableview


    【解决方案1】:

    这并不能真正解决问题,但这里有一个解决方法。诀窍是将整个NSScrollView 放在自定义NSView 中,并在自定义NSView 中绘制背景。

    使NSTableView 透明:

    @implementation SJTableView
    - (BOOL)isOpaque {
        return NO;
    }
    
    -(void) drawBackgroundInClipRect:(NSRect)clipRect {
        NSRectFillUsingOperation(clipRect, NSCompositeClear);
    }
    @end
    

    使NSScrollView 透明:

    _scrollView.drawsBackground = NO;
    

    在自定义视图中绘制背景:

    @implementation SJView
    -(BOOL) isOpaque {
        return (_backgroundColor.alphaComponent >= 1.0);
    }
    
    -(void) drawRect:(NSRect)dirtyRect {
        [super drawRect:dirtyRect];
    
        if(_backgroundColor){
            [_backgroundColor setFill];
            NSRectFillUsingOperation(dirtyRect, NSCompositeSourceOver);
        }
    }
    @end
    

    【讨论】: