在 UIScrollView 中覆盖 drawRect 时的黑色背景

Posted

技术标签:

【中文标题】在 UIScrollView 中覆盖 drawRect 时的黑色背景【英文标题】:black background when overriding drawRect in UIScrollView 【发布时间】:2012-07-03 20:52:06 【问题描述】:

所以我试图在我的 UIScrollView 中覆盖 drawRect,但是它给了我这个黑色背景,而不是我为我的 UIScrollView 指定的背景颜色。为什么是这样?如果我删除 drawRect 代码,那么一切都很好:

- (void)drawRect:(CGRect)rect

    [super drawRect:rect];
    if (shouldDrawVerticalLineForProfile)

        CGContextRef context = UIGraphicsGetCurrentContext();
        CGColorRef separatorColor = [UIColor colorWithRed:47.0/255.0 green:47.0/255.0 
                                                     blue:47.0/255.0 alpha:1.0].CGColor;

        // Add at bottom
        CGPoint startPoint = CGPointMake(60, 0);
        CGPoint endPoint = CGPointMake(60, 10000);

        CGContextSaveGState(context);
        CGContextSetLineCap(context, kCGLineCapSquare);
        CGContextSetStrokeColorWithColor(context, separatorColor);
        CGContextSetLineWidth(context, 5.0);
        CGContextMoveToPoint(context, startPoint.x + 0.5, startPoint.y + 0.5);
        CGContextAddLineToPoint(context, endPoint.x + 0.5, endPoint.y + 0.5);
        CGContextStrokePath(context);
        CGContextRestoreGState(context);  

    


【问题讨论】:

我认为 backgroundColor 属性只是简单地包装了一个 CGContextAddRect 和 CGContextFillPath,如果你这样做呢? 使用我上面提到的两个函数手动绘制bgcolor。 我知道这并不能从根本上解决问题,但我只是最终将我的自定义逻辑从 override func draw(rect: CGRect) 方法移动到 override func layoutSubviews()。但它特别适用于我的情况。 【参考方案1】:

我猜你要搜索的是:

myScrollViewInstance.opaque = NO

之后,滚动视图的背景不再是黑色。

【讨论】:

我试过这个但没有帮助。我认为不是背景是黑色的。只有当scrollView的drawRect被覆盖时,scrollView才会变黑。如果 drawRect 未被覆盖,则滚动视图正常为白色。 此答案仅在您真正想要半透明背景的情况下才是正确的。如果您期望不明确的backgroundColor 得到尊重,它将失败。【参考方案2】:

我在 UIScrollView 子类中覆盖 drawRect 时遇到了类似的情况。

简单地覆盖:

- (void)drawRect:(CGRect)rect

    [super drawRect:rect];

导致黑色背景,而不是我在不覆盖的情况下获得的所需清晰背景。

我发现这是因为在 Interface Builder 中将 View Background 设置为 Default 并且将其设置为 Clear Color 为我解决了这个问题。

我不确定这是否与您的问题有关,但我想分享一下以防万一。

【讨论】:

UIView 的drawRect: 被记录为“这个方法的默认实现什么都不做。”,所以调用它肯定不会做任何事情。你必须自己填充背景。【参考方案3】:

AppleDocs 中非常清楚地记录了 UIView 的drawRect: 方法的答案。第一句话是:

这个方法的默认实现什么都不做。

因此,此处调用 super 的建议无济于事。其余答案包含在讨论的更下方:

...如果您的视图的 opaque 属性设置为 YES,您的 drawRect: 方法必须用不透明的内容完全填充指定的矩形。

意思是如果你不打算有一个透明的背景,你需要实际绘制背景。最正确的做法是使用以下drawRect: 模板:

- (void)drawRect:(CGRect)rect

    [super drawRect:rect]; // optional if a direct UIView-subclass, should be called otherwise.

    CGContextRef context = UIGraphicsGetCurrentContext();
    // Fill the background color, if needed
    if (self.opaque) 
        UIGraphicsPushContext(context);
        CGContextSetFillColorWithColor(context, self.backgroundColor.CGColor);
        CGContextFillRect(context, rect);
        UIGraphicsPopContext();
    

    // Your code here...

【讨论】:

绝对有效的答案。很好的解释亚当 乐于助人。也许这是我的答案最终获得额外 15 票成为榜首的十年:)【参考方案4】:

这应该会有所帮助

CGContextSetFillColorWithColor(context, colorBack);
CGContextFillRect(context, self.bounds); 

// 相应地选择bounds和colorBack

【讨论】:

使用矩形,而不是边界,让 UIKit 在需要时优化绘图。【参考方案5】:

请试试这个它为我工作

 - (id)initWithFrame:(CGRect)frame 
        if (self = [super initWithFrame:frame]) 
            [self setBackgroundColor:[UIColor clearColor]];
        
        return self;
    
    - (void)drawRect:(CGRect)rect
    
        [super drawRect:rect];
        if (shouldDrawVerticalLineForProfile)

            CGContextRef context = UIGraphicsGetCurrentContext();
            CGColorRef separatorColor = [UIColor colorWithRed:47.0/255.0 green:47.0/255.0 
                                                         blue:47.0/255.0 alpha:1.0].CGColor;

            // Add at bottom
            CGPoint startPoint = CGPointMake(60, 0);
            CGPoint endPoint = CGPointMake(60, 10000);

            CGContextSaveGState(context);
            CGContextSetLineCap(context, kCGLineCapSquare);
            CGContextSetStrokeColorWithColor(context, separatorColor);
            CGContextSetLineWidth(context, 5.0);
            CGContextMoveToPoint(context, startPoint.x + 0.5, startPoint.y + 0.5);
            CGContextAddLineToPoint(context, endPoint.x + 0.5, endPoint.y + 0.5);
            CGContextStrokePath(context);
            CGContextRestoreGState(context);  

        

    

【讨论】:

【参考方案6】:

唯一对我有用的是在调用setNeedsDisplay 之后显式设置背景。在我的示例中,我在地图上使用了 MKAnnotationView 的子类,而不是 UIScrollView,所以我真的不知道这在 OP 场景中的适用程度如何。就我而言,我从setAnnotation 调用setNeedsDisplay,我发现这样做会重置backgroundColor。只需在setNeedsDisplay 解决问题后由backgroundColor 重新设置即可。

FWIW,我也观察到简单地覆盖 drawRect 以委托给超类会导致这个黑色背景问题。

【讨论】:

以上是关于在 UIScrollView 中覆盖 drawRect 时的黑色背景的主要内容,如果未能解决你的问题,请参考以下文章

如何在 UIScrollView 中的图像上呈现非缩放覆盖

为啥即使我覆盖 touchesMoved:withEvent:,UIScrollView 的子类仍会滚动?

如何覆盖'UIScrollView.delegate'?

UICollectionView targetContentOffsetForProposedContentOffset:被 UIScrollView 覆盖

UIScrollView 覆盖顶部的控制器

当我覆盖“drawRect”时,UIButton 样式设置被忽略