在我的自定义 UIView 中,设置子视图的 backgroundColor 会导致它覆盖我的 drawRect 绘图(CGContextRef、CGMutablePathRef 等)。怎么修?

Posted

技术标签:

【中文标题】在我的自定义 UIView 中,设置子视图的 backgroundColor 会导致它覆盖我的 drawRect 绘图(CGContextRef、CGMutablePathRef 等)。怎么修?【英文标题】:In my custom UIView, setting a subview's backgroundColor causes it to cover up my drawRect drawings (CGContextRef, CGMutablePathRef,etc). How to fix? 【发布时间】:2016-12-09 22:11:48 【问题描述】:

我有一个带有橙色 @​​987654327@ 的自定义容器视图。

在这个自定义视图中,我通过覆盖drawRect 来绘制线条。在我尝试在子视图上画线之前,这很有效。

以下是一些与代码编辑相关的屏幕截图,以说明我面临的问题:

^ 这张图片显示了我的自定义视图,其中存在self.graphBackgroundView,但没有设置明确的backgroundColor。我的drawRect 的线路是可见的。这很好。

^ 这张图片显示了我的自定义视图,其中存在self.graphBackgroundView,但设置了明确的backgroundColor。就好像我的绿色子视图的 z-index 比我的 drawRect 的 z-index 高一样。

^ 最后,这张图片显示了我的自定义视图,其中self.graphBackgroundView 存在,一个明确的backgroundColor 正在设置(仍然是绿色),但self.graphBackgroundView.layer.opacity 设置为0.25。在这里我们可以再次看到 drawRect 线,但它并不完全正确,我们真的希望这条线完全绘制在视图的顶部,而不是下方。

真正的问题是我们在绿色屏幕截图中看到的内容。我们想要不透明的绿色子视图,我们只想在它上面绘制白线。

非常感谢任何帮助!

代码如下:

- (void)drawRect:(CGRect)rect

    // GET CONTEXT
    CGContextRef context = UIGraphicsGetCurrentContext();

    // INIT PATH
    CGMutablePathRef path = CGPathCreateMutable();

    // CONFIG PATH
    CGContextSetLineWidth(context, 1.0);
    CGContextSetStrokeColor(context, CGColorGetComponents([UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:1.0].CGColor)); // 4 color component white for use with CGColorGetComponents

    // ESTABLISH STARTING POINT
    CGPathMoveToPoint(path, NULL, 0.0, 100.0);

    // GRAPH NEXT POINT
    CGPathAddQuadCurveToPoint(path, NULL, 120.0, 160.0, 120.0, 160.0);

    // GRAPH NEXT POINT
    CGPathAddQuadCurveToPoint(path, NULL, 130.0, 170.0, 130.0, 170.0);

    // ADD THE PATH
    CGContextAddPath(context, path);

    // DRAW
    CGContextDrawPath(context, kCGPathStroke);


- (id)init

    self = [super init];
    if (self)
    
        // INIT UI ELEMENTS
        self.graphBackgroundView = [[UIView alloc] init];

        // INIT AUTO LAYOUT VIEWS DICT
        self.viewsDictionary = [NSMutableDictionary new];
        [self.viewsDictionary setObject:self.graphBackgroundView forKey:@"graphBackgroundView"];

        // TURN ON AUTO LAYOUT
        self.graphBackgroundView.translatesAutoresizingMaskIntoConstraints = NO;

        // ESTABLISH VIEW HIERARCHY
        [self addSubview:self.graphBackgroundView];

        // LAYOUT

        // graphBackgroundView
        [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(0)-[graphBackgroundView]-(0)-|" options:0 metrics:0 views:self.viewsDictionary]];
        [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(topMargin)-[graphBackgroundView]-(bottomMargin)-|" options:0 metrics:@@"topMargin":self.topMargin,@"bottomMargin":self.bottomMargin views:self.viewsDictionary]];

        // CONFIG

        // self
        self.backgroundColor = [UIColor orangeColor]; // My drawRect code DOES draw on top of this color

        // graphBackgroundView
        self.graphBackgroundView.backgroundColor = [UIColor greenColor]; // My drawRect code does NOT draw on top of this color
        //self.graphBackgroundView.layer.opacity = 0.25; // <-- If I uncomment this I can kind of see the line I'm drawing underneath it via the effects of transparency
    
    return self;

【问题讨论】:

【参考方案1】:

就好像我的绿色子视图的 z-index 比我的 drawRect 的 z-index 高一样。

嗯,确实如此。如果您有一个父视图及其子视图,则子视图将绘制在 在父视图的前面。这是子视图的一部分。这里唯一的惊喜是你很惊讶。

【讨论】:

在我写代码的时候,我认为包含自定义视图是一个“单一的东西”。就像,drawRect 负责绘制自身及其子视图(在我的 init 中,我正在将它们布置出来......)。是的,我现在明白,当你想到视图、它们的内部绘图代码等时,这没有任何意义……无论如何,我现在已经弄清楚了,你的答案很有趣。从某种意义上说,它非常有帮助,因为它准确地阐明了这里发生的事情。干杯队友,谢谢!

以上是关于在我的自定义 UIView 中,设置子视图的 backgroundColor 会导致它覆盖我的 drawRect 绘图(CGContextRef、CGMutablePathRef 等)。怎么修?的主要内容,如果未能解决你的问题,请参考以下文章

重新排序 UIView 子视图

如何为 UIView 的自定义子类设置约束?

故事板中的自定义 UIView 不显示子视图

我的自定义 UIView 没有收到触摸

为子视图的子视图设置框架

来自 XIB 的自定义 UIView 加载具有巨大规模的子视图