带有透明圆角矩形的 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
首先,我寻找并发现了这个: 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