带有透明圆角矩形的 UIView?

Posted

技术标签:

【中文标题】带有透明圆角矩形的 UIView?【英文标题】:UIView with transparent rounded rectangles? 【发布时间】:2015-02-07 02:30:45 【问题描述】:

首先,我寻找并找到了这个: Cut transparent hole in UIView 在我的视图上放置多个透明矩形,但现在我需要对这些矩形进行四舍五入,如下所示: http://postimg.org/image/ozxr0m5sh/ 所以我混合了我找到的一些代码并这样做了,但由于某种原因它只适用于第一个矩形,这是自定义视图的完整代码: (如果您取消方法“addRoundedRect...”调用,它适用于所有矩形)。

- (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);

【问题讨论】:

【参考方案1】:

ios 中,通常最好不要使用 drawRect。它往往比其他渲染内容的方法慢。

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

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

【讨论】:

【参考方案2】:

这里我有一个裂缝。必须在此视图上关闭 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

【讨论】:

以上是关于带有透明圆角矩形的 UIView?的主要内容,如果未能解决你的问题,请参考以下文章

绘制圆角矩形的透明度问题

Android中实现圆角矩形及半透明效果。

带有圆角矩形的 SKScene

圆角矩形框绘制-iOS

从带有圆角的矩形中检测角点

创建带有圆角矩形的进度指示器