带有透明圆角矩形的 UIView?

UIView with transparent rounded rectangles?

首先,我寻找并发现了这个: Cut transparent hole in UIView 在我的视图上放置多个透明矩形,但现在我需要将这些矩形变成圆角,如下所示: http://postimg.org/image/ozxr0m5sh/ 所以我混合了一些我发现的代码并这样做了,但由于某种原因它只适用于第一个矩形,这里是自定义视图的完整代码: (如果你取消方法 "addRoundedRect..." 调用,它适用于所有 rects)。

- (void)drawRect:(CGRect)rect{

[backgroundColor setFill];
UIRectFill(rect);

// clear the background in the given rectangles
for (NSValue *holeRectValue in rectsArray) {
    CGRect holeRect = [holeRectValue CGRectValue];
    CGRect holeRectIntersection = CGRectIntersection( holeRect, rect );
    CGContextRef context = UIGraphicsGetCurrentContext();

    if( CGRectIntersectsRect( holeRectIntersection, rect ) )
    {
        addRoundedRectToPath(context, holeRectIntersection, 6, 6);
        CGContextClosePath(context);
        CGContextClip(context);
        CGContextClearRect(context, holeRectIntersection);
        CGContextSetFillColorWithColor( context, [UIColor clearColor].CGColor );
        CGContextFillRect( context, holeRectIntersection);
    }

}

static void addRoundedRectToPath(CGContextRef context, CGRect rect, float ovalWidth, float ovalHeight){
    float fw, fh;
    if (ovalWidth == 0 || ovalHeight == 0) {
        CGContextAddRect(context, rect);
        return;
    }
    CGContextSaveGState(context);
    CGContextTranslateCTM (context, CGRectGetMinX(rect),        CGRectGetMinY(rect));
    CGContextScaleCTM (context, ovalWidth, ovalHeight);
    fw = CGRectGetWidth (rect) / ovalWidth;
    fh = CGRectGetHeight (rect) / ovalHeight;
    CGContextMoveToPoint(context, fw, fh/2);
    CGContextAddArcToPoint(context, fw, fh, fw/2, fh, 1);
    CGContextAddArcToPoint(context, 0, fh, 0, fh/2, 1);
    CGContextAddArcToPoint(context, 0, 0, fw/2, 0, 1);
    CGContextAddArcToPoint(context, fw, 0, fw, fh/2, 1);
    CGContextClosePath(context);
    CGContextRestoreGState(context);
}

在iOS中一般最好不要使用drawRect。它往往比其他呈现内容的方法慢。

我不知道你为什么不能在视图中打出多个圆边孔的问题的具体答案,但我建议采用不同的方法。而不是在 drawRect 方法中使用 CGContexts。

使用您需要的任何内容设置您的视图。然后创建一个与视图大小相同的 CAShapeLayer 并用路径填充它(形状图层需要 CGPath,但您可以创建一个 UIBezierPath 并从中获取 CGPath。)将形状图层附加为视图图层的蒙版。 (不过,您放置在遮罩层中的形状定义了视图的不透明部分,因此您必须创建一个填充遮罩的形状,然后用其他形状在其中打孔。

我在这里遇到了一个裂缝。必须在此视图上关闭 UserInteraction 才能传递触摸事件,因此不要在此处添加任何子视图,除非您希望它们也忽略触摸..

接口:

#import "AslottedView.h"
//header is empty but for #import <UIKit/UIKit.h>
//this is a subclass on UIView
@interface AslottedView ()

//helper function, nb resultantPath will rerquire releasing(create in func name)
CGMutablePathRef CGPathCreateRoundedRect(CGRect rect, CGFloat cornerRadius);


@end

实施:

@implementation AslottedView
{
  CGRect slots[4];
}

CGMutablePathRef CGPathCreateRoundedRect(CGRect rect, CGFloat cornerRadius){

  CGMutablePathRef result = CGPathCreateMutable();

  CGPathMoveToPoint(result, nil, CGRectGetMinX(rect)+cornerRadius, (CGRectGetMinY(rect)) );

  CGPathAddArc(result, nil, (CGRectGetMinX(rect)+cornerRadius), (CGRectGetMinY(rect)+cornerRadius), cornerRadius, M_PI*1.5, M_PI*1.0, 1);//topLeft
  CGPathAddArc(result, nil, (CGRectGetMinX(rect)+cornerRadius), (CGRectGetMaxY(rect)-cornerRadius), cornerRadius, M_PI*1.0, M_PI*0.5, 1);//bottomLeft
  CGPathAddArc(result, nil, (CGRectGetMaxX(rect)-cornerRadius), (CGRectGetMaxY(rect)-cornerRadius), cornerRadius, M_PI*0.5, 0.0, 1);//bottomRight
  CGPathAddArc(result, nil, (CGRectGetMaxX(rect)-cornerRadius), (CGRectGetMinY(rect)+cornerRadius), cornerRadius, 0.0, M_PI*1.5, 1);//topRight
  CGPathCloseSubpath(result);
  return result;

}

CGColorRef fillColor(){

  return [UIColor whiteColor].CGColor;
  //or whatever..
}

-(instancetype )initWithFrame:(CGRect)frame{

  if (self = [super initWithFrame:frame]) {

    self.userInteractionEnabled = NO;
    self.backgroundColor = [UIColor clearColor];

 //quick loop to make some rects
    CGRect rct = CGRectMake(10.0, 10.0, 40.0, 40.0);
    CGFloat margin = 30.0;

    for (NSInteger i = 0; i < 4; i ++) {

      slots[i] = CGRectOffset(rct, ((rct.size.width+margin) * ((i%2==0)? 1.0 : 0.0))  , ((rct.size.height+margin) * ((i>1)? 1.0:0.0) )) ;
    }
  }
  return self;
}




- (void)drawRect:(CGRect)rect {

  CGContextRef ctx = UIGraphicsGetCurrentContext();
  CGContextSetFillColorWithColor(ctx, fillColor() );

  CGContextAddRect(ctx, self.bounds);
  for (NSInteger i = 0; i < 4; i ++) {

    CGMutablePathRef roundRect = CGPathCreateRoundedRect(slots[i], 5.0);
    CGContextAddPath(ctx, roundRect);
    CGPathRelease(roundRect);

  }
  CGContextEOFillPath(ctx);

}


@end