尽管完全是空的drawRect,UIView子类绘制背景: - 为什么?

时间:2009-10-11 17:52:12

标签: objective-c cocoa-touch iphone-sdk-3.0 uiview

所以,我有一个自定义的UIView子类,它可以绘制圆形边。事情完美无缺,但背景总是填满整个边界,尽管首先剪切到路径。边框也在上面绘制矩形背景,尽管事实上我在drawRect:中绘制边框在背景之前。所以我删除了drawRect:的全部内容,现在几乎是空的 - 然而背景被绘制了!

有人对此作出解释吗?我在Interface Builder中设置了backgroundColor。谢谢!

6 个答案:

答案 0 :(得分:20)

对不起这段独白。 :)

问题是UIView的图层显然绘制了背景,它独立于drawRect:。这就是为什么你不能通过覆盖drawRect:来摆脱背景。

您可以覆盖- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx并使图层绘制您想要的任何内容,或者覆盖- (void) setBackgroundColor:(UIColor *)newColor并且不将 newColor 分配给 backgroundColor ,但是对于你自己的ivar,比如 myBackgroundColor 。然后,您可以在drawRect中使用 myBackgroundColor ;按照你喜欢的方式绘制背景。


覆盖setBackgroundColor:

定义一个实例变量来保存背景颜色,例如 myBackgroundColor 。在init方法中,将实际背景颜色设置为clearColor:

- (id) initWithCoder:(NSCoder *)aDecoder
{
    if ((self = [super init...])) {
        [super setBackgroundColor:[UIColor clearColor]];
    }
    return self;
}

覆盖:

- (void) setBackgroundColor:(UIColor *)newColor
{
    if (newColor != myBackgroundColor) {
        [myBackgroundColor release];
        myBackgroundColor = [newColor retain];
    }
}

然后在drawRect:方法中使用 myBackgroundColor 。这样,您就可以在代码中使用Interface Builder(或Xcode4)指定的颜色。

答案 1 :(得分:8)

这是一个更容易解决的问题:

self.backgroundColor = [UIColor clearColor];

答案 2 :(得分:6)

我毫不犹豫地提出这个建议,因为我不想冒犯你,但是你有不透明吗?

答案 3 :(得分:0)

这很容易重现:

创建一个新的基于视图的iPhone应用程序。创建一个UIView子类并使drawRect:方法完全为空。在Interface Builder中,将UIView拖到主视图中,为其指定背景颜色,并将视图的类设置为子类。保存,构建和运行,并看到视图显示背景颜色。

我通过重写setBackgroundColor来规避这种行为:并将颜色分配给我自己的ivar,总是将backgroundColor属性保留为nil。这有效,但我仍然想知道为什么这样做。

答案 4 :(得分:0)

你应该设置

clearsContextBeforeDrawing = NO

就这么简单。

来自UIView Reference Docs

糟糕。我误解了这个问题。 OP(原始海报)希望他们的自定义控件支持标准的“backgroundColor”属性(例如,由gui设计师设置),但不希望系统绘制该颜色。 OP想要自己画bg,以便他可以绕过角落。

在这种情况下,关于覆盖图层级绘图的帖子是正确的。

我发布的解决方案将阻止UI系统在绘制之前清除缓冲区。如果没有定义bg,如果设置了clearsContextBeforeDrawing,iOS将清除视图的缓冲区,将所有像素设置为透明黑色。在全屏视图中执行此操作需要大约5毫秒的iPad3,所以它不是免费的(推动2048x1536像素永远不会)。为了比较绘图,全屏位图(使用kCGBlendModeCopy强制进行blitting)需要大约25ms(使用石英,而不是GPU)。

答案 5 :(得分:0)

虽然可以覆盖将背景颜色复制到视图层的代码,但我不喜欢这种方法。我相信它会导致不透明的视图出现问题。我的建议是像这样创建一个自定义颜色变量:

@IBInspectable var foregroundColor: UIColor = .black {
    didSet { setNeedsDisplay() }
}

现在,将视图的 backgroundColor 设置为清除并在绘图代码中使用 foregroundColor 代替它。上面的代码负责在值更改时更新它,并在需要时将其公开给 Interface Builder。

另一种替代方法是改用视图的 tintColor,并确保它在色调颜色更改时正确更新。不过,您可能会将色调保留用于其他用途,因此这不一定是理想的。如果您使用 tintColor,请不要忘记包含以下内容:

override func tintColorDidChange() {
    setNeedsDisplay()
}