所以,我有一个自定义的UIView子类,它可以绘制圆形边。事情完美无缺,但背景总是填满整个边界,尽管首先剪切到路径。边框也在上面绘制矩形背景,尽管事实上我在drawRect:中绘制边框在背景之前。所以我删除了drawRect:的全部内容,现在几乎是空的 - 然而背景被绘制了!
有人对此作出解释吗?我在Interface Builder中设置了backgroundColor。谢谢!
答案 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
就这么简单。
糟糕。我误解了这个问题。 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()
}