【问题标题】:UIView overriding drawRect causes view not to obey masksToBoundsUIView 覆盖 drawRect 导致视图不遵守 maskToBounds
【发布时间】:2012-12-06 15:21:53
【问题描述】:

我试图在我的自定义视图中覆盖 UIView 的 drawRect: 方法。但是,我的视图的边界半径定义为:

    sub = [[[NSBundle mainBundle] loadNibNamed:@"ProfileView" owner:self options:nil] objectAtIndex:0];
    [self addSubview:sub];
    [sub setUserInteractionEnabled:YES];
    [self setUserInteractionEnabled:YES];
    CALayer *layer = sub.layer;
    layer.masksToBounds = YES;
    layer.borderWidth = 5.0;
    layer.borderColor = [UIColor whiteColor].CGColor;
    layer.cornerRadius = 30.0;

这非常有效,并在我的视图周围放置了一个带有边界半径的漂亮边框(不要介意后面的对角线/直线白线,它们与此视图无关):

但是,当我尝试在我的视图中覆盖 drawRect: 方法时,我可以看到黑色背景没有遮盖边界。我不做任何事情(目前),这是我的代码:

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

结果如下:

我只改变了draw方法。如何在保持视图服从角半径遮罩的同时覆盖 draw 方法?这是 iOS 中的错误还是我遗漏了什么?

【问题讨论】:

    标签: ios uiview ios6 drawrect


    【解决方案1】:

    我不知道完整的答案,但我知道 UIView 对 drawLayer:inContext: 的实现会根据您是否实现 drawRect: 的不同而有所不同。也许掩蔽/剪切到边界是它做的不同的事情之一。

    您可以尝试通过多种方式解决您的问题:

    • 让你的背景透明:

          layer.backgroundColor = [UIColor clearColor].CGColor;
      
    • 将自己夹在您的自定义drawRect:中:

      - (void)drawRect:(CGRect)rect {
          [[UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:30.0] addClip];
          [image drawInRect:rect];  // or whatever
      }
      
    • 明确地切出角落:

      CGContextBeginPath(c);
      CGContextAddArc(c, r, r, r, M_PI, 3*M_PI_2, 0);
      CGContextAddLineToPoint(c, 0, 0);
      CGContextClosePath(c);
      CGContextClip(c);
      [[UIColor grayColor] setFill];
      UIRectFill(rect);
      

    我从 WWDC 2010 的这个精彩演示中窃取了最后两条建议:Advanced Performance Optimization on iPhone OS(在this index page 列出的视频——令人讨厌的是,没有直接链接)。

    【讨论】:

      【解决方案2】:

      这是一个老问题,但我最近阅读了一篇有用的博客文章,标题为 Abusing UIView。在其中,作者建议不要覆盖drawRect 在有其他方法时执行添加边框之类的操作。他说,

      覆盖drawRect: 会导致性能下降。我没有介绍它, 所以我不知道在正常情况下这是否是一个显着的表现 情况(可能不是),但在大多数情况下,那些 覆盖drawRect: 可以更轻松地完成他们想要的事情 在视图的图层属性上设置属性。如果你需要画一个 在视图周围勾勒出轮廓,您可以这样做:

      #import <QuartzCore/QuartzCore.h>
      
      - (id)initWithFrame:(CGRect)frame {
        self = [super initWithFrame:frame];
        if (self) {
            self.layer.borderWidth = 2.f;
            self.layer.borderColor = [UIColor redColor].CGColor;
        }
        return self;
      

      我意识到这可能无法解决黑色背景透出的问题。这只是需要考虑的其他事情。

      【讨论】:

        【解决方案3】:

        设置

        opaque = false // NO for ObjC
        

        在视图上解决问题。

        【讨论】:

          【解决方案4】:

          也许你不应该打电话给

          [super drawRect:rect]
          

          在你的drawRect中。 Apple says那个:

          如果你直接继承 UIView,你的这个方法的实现 不需要调用super。但是,如果您将子类化为 不同的视图类,你应该在你的某个时候调用 super 实施。

          似乎调用 super 方法会导致奇怪的行为。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-04-03
            • 1970-01-01
            • 1970-01-01
            • 2012-08-03
            • 1970-01-01
            • 2019-03-12
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多