如果重写drawRect,则iOS子视图显示为黑色矩形

6

我有一个故事板,加载了一个自定义的UIView。还向storyboard中的视图添加了一个子视图。直到我重写了子视图的drawRect方法,它就一直运行良好,但是之后我只看到了一个黑色矩形代替了子视图。以下是代码:

#import <UIKit/UIKit.h>
#import "MySubview.h"

@interface MyView : UIView

@end

#import "MyView.h"

@implementation MyView

- (void) awakeFromNib
{
    CGRect frame = [self frame];
    MySubview* sv = [[MySubview alloc] initWithFrame:frame];
    [self addSubview:sv];
}

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
    }
    return self;
}

@end

#import <UIKit/UIKit.h>

@interface MySubview : UIView

@property (retain, nonatomic) NSString* text;
@property (retain, nonatomic) UILabel* label;

@end

#import "MySubview.h"

@implementation MySubview

@synthesize text, label;


- (void)attachLabel
{
    text = @"Hello";
    label = [[UILabel alloc] init];
    [label setText:text];
    [label setFont:[UIFont fontWithName:@"Futura" size:18]];
    [label setBackgroundColor:[UIColor clearColor]];

    [label sizeToFit];

    CGRect labelFrame = label.frame;
    labelFrame.origin.x = (self.frame.size.width  - labelFrame.size.width) / 2;
    labelFrame.origin.y = (self.frame.size.height - labelFrame.size.height) / 2;
    label.frame = labelFrame;

    [self addSubview:label];
}

- (void)awakeFromNib
{
    [self attachLabel];
}

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        [self attachLabel];
    }
    return self;
}

// Works if I comment this out!
- (void)drawRect:(CGRect)rect
{
}

@end

更新 - 下面添加了绘图代码:

- (void)drawRectWithRoundBorders:(CGRect)rect
{
    [super drawRect:rect];

    // Parameters used for drawing.
    const CGFloat lineWidth = 5;
    const CGFloat shadowOffset = 3;
    const CGFloat shadowBlur = 4;
    const CGFloat spaceToBB = 10;   // Space to the bounding box of this view.
    const CGFloat cornerRadii = 5;
    const CGFloat lineColor[4] = { 0, 0, 0, 1 };

    CGContextRef ctx = UIGraphicsGetCurrentContext();

    CGContextSetLineWidth(ctx, lineWidth);
    CGContextSetStrokeColor(ctx, lineColor);
    CGContextSetShadow(ctx, CGSizeMake(shadowOffset, shadowOffset), shadowBlur);

    CGRect innerRect = rect;

    innerRect.size.width -= 2*spaceToBB;
    innerRect.size.height -= 2*spaceToBB;
    innerRect.origin.x += spaceToBB;
    innerRect.origin.y += spaceToBB;

    UIBezierPath *path = 
    [UIBezierPath bezierPathWithRoundedRect:innerRect 
                          byRoundingCorners:UIRectCornerAllCorners 
                                cornerRadii:CGSizeMake(cornerRadii, cornerRadii)
     ];

    CGContextAddPath(ctx, path.CGPath);
    CGContextStrokePath(ctx);
}


- (void)drawRect:(CGRect)rect
{
    [self drawRectWithRoundBorders:rect];
}

更新

当我首先用一些颜色填充子视图的边界框时,它似乎可以工作。

CGContextRef ctx = UIGraphicsGetCurrentContext();
CGFloat white[] = {1, 1, 1, 0.5};
CGContextSetFillColor(ctx, white);
CGContextAddRect(ctx, rect);
CGContextFillPath(ctx);

这个 - (void)drawRectWithRoundBorders:(CGRect)rect 函数什么时候被调用? - jrturton
@jrturton 在drawRect方法中,只需向下滚动一点即可。 - Nils
哦,我被上面的空实现搞混了 - 你应该从问题中删除它(还有你的代码??) - jrturton
请注意,drawRect中的'rect'不一定是视图的整个边界 - 您似乎在方法中将其用作此类边界,但实际上您应该使用self.bounds。 - jrturton
1
不透明属性正是我在寻找的!将其设置为 NO 可以得到所期望的行为。 - Nils
请在下面选择正确的答案,因为您也发现它有效。 - mahboudz
2个回答

41

只需在您的initWithFrame:方法中添加[self setOpaque:NO]即可。


4

这是因为你的drawRect没有做任何事情。如果你想进行自定义绘制,就需要重写drawRect。所以:

  • 如果你不想进行自定义绘制,那就不要重写drawRect
  • 如果你想进行自定义绘制,那就在drawRect中实际做点什么。

如果我直接在Storyboard中加载子视图类,它就可以工作。另外,如果我在drawRect中绘制一些东西,它仍然是黑色的。 - Nils
如果你想在默认视图上绘制,请添加 [super drawRect:rect] :) - deanWombourne
你的绘图代码是什么?如果还是黑色,那么你的绘图方式可能有误。 - mattjgalloway
先尝试画一条单独的线,然后逐步实现你想要达到的所有目标。而且你的背景颜色是透明的 - 这是故意的吗? - deanWombourne
5
视图的opaque属性被设置为什么?在Storyboard/xib文件中,该属性可能默认为“NO”,但以另一种方式实例化视图可能会将该属性保留为“YES”。 - sho
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接