Jum*_*hyn 77 iphone objective-c rounded-corners ios
不久之前,我发布了一个关于在视图的两个角上进行四舍五入的问题,得到了很好的响应,但是在实现它时遇到了问题.这是我的drawRect:方法:
- (void)drawRect:(CGRect)rect {
//[super drawRect:rect]; <------Should I uncomment this?
int radius = 5;
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextBeginPath(context);
CGContextAddArc(context, rect.origin.x + radius, rect.origin.y + rect.size.height - radius, radius, M_PI, M_PI / 2, 1);
CGContextAddArc(context, rect.origin.x + rect.size.width - radius, rect.origin.y + rect.size.height - radius, radius, M_PI / 2, 0.0f, 1);
CGContextClosePath(context);
CGContextClip(context);
}
Run Code Online (Sandbox Code Playgroud)
正在调用该方法,但似乎不会影响视图的结果.有什么想法吗?
Sac*_*hin 79
iOS 11中引入了CACornerMask,它有助于在视图层中定义topleft,topright,bottomleft,bottom right.以下是使用示例.
在这里,我尝试仅舍入两个顶角:
myView.clipsToBounds = true
myView.layer.cornerRadius = 10
myView.layer.maskedCorners = [.layerMinXMinYCorner,.layerMaxXMinYCorner]
Run Code Online (Sandbox Code Playgroud)
提前致谢.
lom*_*anf 72
据我所知,如果你还需要掩盖子视图,你可以使用CALayer掩蔽.有两种方法可以做到这一点.第一个是更优雅,第二个是解决方法:-)但它也很快.两者都基于CALayer掩蔽.我去年在几个项目中使用了这两种方法,然后我希望你能找到有用的东西.
首先,我创建了这个函数来生成一个UIImage带有我需要的圆角的fly()图像蒙版.该功能基本上需要5个参数:图像边界和4个角半径(左上角,右上角,左下角和右下角).
static inline UIImage* MTDContextCreateRoundedMask( CGRect rect, CGFloat radius_tl, CGFloat radius_tr, CGFloat radius_bl, CGFloat radius_br ) {
CGContextRef context;
CGColorSpaceRef colorSpace;
colorSpace = CGColorSpaceCreateDeviceRGB();
// create a bitmap graphics context the size of the image
context = CGBitmapContextCreate( NULL, rect.size.width, rect.size.height, 8, 0, colorSpace, kCGImageAlphaPremultipliedLast );
// free the rgb colorspace
CGColorSpaceRelease(colorSpace);
if ( context == NULL ) {
return NULL;
}
// cerate mask
CGFloat minx = CGRectGetMinX( rect ), midx = CGRectGetMidX( rect ), maxx = CGRectGetMaxX( rect );
CGFloat miny = CGRectGetMinY( rect ), midy = CGRectGetMidY( rect ), maxy = CGRectGetMaxY( rect );
CGContextBeginPath( context );
CGContextSetGrayFillColor( context, 1.0, 0.0 );
CGContextAddRect( context, rect );
CGContextClosePath( context );
CGContextDrawPath( context, kCGPathFill );
CGContextSetGrayFillColor( context, 1.0, 1.0 );
CGContextBeginPath( context );
CGContextMoveToPoint( context, minx, midy );
CGContextAddArcToPoint( context, minx, miny, midx, miny, radius_bl );
CGContextAddArcToPoint( context, maxx, miny, maxx, midy, radius_br );
CGContextAddArcToPoint( context, maxx, maxy, midx, maxy, radius_tr );
CGContextAddArcToPoint( context, minx, maxy, minx, midy, radius_tl );
CGContextClosePath( context );
CGContextDrawPath( context, kCGPathFill );
// Create CGImageRef of the main view bitmap content, and then
// release that bitmap context
CGImageRef bitmapContext = CGBitmapContextCreateImage( context );
CGContextRelease( context );
// convert the finished resized image to a UIImage
UIImage *theImage = [UIImage imageWithCGImage:bitmapContext];
// image is retained by the property setting above, so we can
// release the original
CGImageRelease(bitmapContext);
// return the image
return theImage;
}
Run Code Online (Sandbox Code Playgroud)
现在你只需要几行代码.我把东西放在我的viewController viewDidLoad方法中因为它更快但你也可以在自定义中使用它UIView与layoutSubviews示例中的方法.
- (void)viewDidLoad {
// Create the mask image you need calling the previous function
UIImage *mask = MTDContextCreateRoundedMask( self.view.bounds, 50.0, 50.0, 0.0, 0.0 );
// Create a new layer that will work as a mask
CALayer *layerMask = [CALayer layer];
layerMask.frame = self.view.bounds;
// Put the mask image as content of the layer
layerMask.contents = (id)mask.CGImage;
// set the mask layer as mask of the view layer
self.view.layer.mask = layerMask;
// Add a backaground color just to check if it works
self.view.backgroundColor = [UIColor redColor];
// Add a test view to verify the correct mask clipping
UIView *testView = [[UIView alloc] initWithFrame:CGRectMake( 0.0, 0.0, 50.0, 50.0 )];
testView.backgroundColor = [UIColor blueColor];
[self.view addSubview:testView];
[testView release];
[super viewDidLoad];
}
Run Code Online (Sandbox Code Playgroud)
这个解决方案有点"脏".基本上你可以用你需要的圆角创建一个遮罩层(所有角落).然后,您应该通过角半径的值增加遮罩层的高度.通过这种方式,底部圆角被隐藏,您只能看到上圆角.我将代码放在viewDidLoad方法中因为它更快,但您也可以在自定义中使用它UIView与layoutSubviews示例中的方法.
- (void)viewDidLoad {
// set the radius
CGFloat radius = 50.0;
// set the mask frame, and increase the height by the
// corner radius to hide bottom corners
CGRect maskFrame = self.view.bounds;
maskFrame.size.height += radius;
// create the mask layer
CALayer *maskLayer = [CALayer layer];
maskLayer.cornerRadius = radius;
maskLayer.backgroundColor = [UIColor blackColor].CGColor;
maskLayer.frame = maskFrame;
// set the mask
self.view.layer.mask = maskLayer;
// Add a backaground color just to check if it works
self.view.backgroundColor = [UIColor redColor];
// Add a test view to verify the correct mask clipping
UIView *testView = [[UIView alloc] initWithFrame:CGRectMake( 0.0, 0.0, 50.0, 50.0 )];
testView.backgroundColor = [UIColor blueColor];
[self.view addSubview:testView];
[testView release];
[super viewDidLoad];
}
Run Code Online (Sandbox Code Playgroud)
希望这可以帮助.再见!
P.L*_*.L. 68
通过几个答案和评论,我发现使用UIBezierPath bezierPathWithRoundedRect和CAShapeLayer最简单,最直接的方式.它可能不适用于非常复杂的情况,但是对于偶尔的角落圆角,它对我来说工作快速而顺畅.
我创建了一个简化的帮助器,在面具中设置适当的角落:
-(void) setMaskTo:(UIView*)view byRoundingCorners:(UIRectCorner)corners
{
UIBezierPath* rounded = [UIBezierPath bezierPathWithRoundedRect:view.bounds byRoundingCorners:corners cornerRadii:CGSizeMake(10.0, 10.0)];
CAShapeLayer* shape = [[CAShapeLayer alloc] init];
[shape setPath:rounded.CGPath];
view.layer.mask = shape;
}
Run Code Online (Sandbox Code Playgroud)
要使用它,只需使用适当的UIRectCorner枚举调用,例如:
[self setMaskTo:self.photoView byRoundingCorners:UIRectCornerTopLeft|UIRectCornerBottomLeft];
Run Code Online (Sandbox Code Playgroud)
请注意,对我来说,我使用它来分组UITableViewCell中的照片圆角,10.0半径适合我,如果需要只是根据需要更改值.
编辑:只是注意到之前的答案非常类似于这个(链接).如果需要,您仍然可以将此答案用作附加的便利功能.
extension UIView {
func maskByRoundingCorners(_ masks:UIRectCorner, withRadii radii:CGSize = CGSize(width: 10, height: 10)) {
let rounded = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: masks, cornerRadii: radii)
let shape = CAShapeLayer()
shape.path = rounded.cgPath
self.layer.mask = shape
}
}
Run Code Online (Sandbox Code Playgroud)
要使用它,可以简单地调用maskByRoundingCorner任何UIView:
view.maskByRoundingCorners([.topLeft, .bottomLeft])
Run Code Online (Sandbox Code Playgroud)
Nat*_*ror 56
在评论@ lomanf的答案时,我无法满足这一切.所以我将其添加为答案.
就像@lomanf所说的那样,你需要添加一个图层蒙版来防止子图层在你的路径边界之外绘制.不过现在这样做要容易得多.只要您的目标是iOS 3.2或更高版本,就不需要使用石英创建图像并将其设置为蒙版.你可以简单地CAShapeLayer用a 创建一个UIBezierPath并使用它作为掩码.
此外,在使用图层蒙版时,请确保在添加蒙版时,您正在屏蔽的图层不是任何图层层次结构的一部分.否则行为未定义.如果您的视图已经在层次结构中,则需要将其从超级视图中删除,将其屏蔽,然后将其放回原位.
CAShapeLayer *maskLayer = [CAShapeLayer layer];
UIBezierPath *roundedPath =
[UIBezierPath bezierPathWithRoundedRect:maskLayer.bounds
byRoundingCorners:UIRectCornerTopLeft |
UIRectCornerBottomRight
cornerRadii:CGSizeMake(16.f, 16.f)];
maskLayer.fillColor = [[UIColor whiteColor] CGColor];
maskLayer.backgroundColor = [[UIColor clearColor] CGColor];
maskLayer.path = [roundedPath CGPath];
//Don't add masks to layers already in the hierarchy!
UIView *superview = [self.view superview];
[self.view removeFromSuperview];
self.view.layer.mask = maskLayer;
[superview addSubview:self.view];
Run Code Online (Sandbox Code Playgroud)
由于Core Animation渲染的工作方式,掩蔽操作相对较慢.每个掩码需要额外的渲染通道.所以请谨慎使用面具.
这种方法的最佳部分之一是您不再需要创建自定义UIView和覆盖drawRect:.这应该使您的代码更简单,甚至更快.
Fre*_*eer 30
我采用了Nathan的例子并创建了一个类别,UIView以允许人们遵守DRY原则.无需再费周折:
#import <UIKit/UIKit.h>
@interface UIView (Roundify)
-(void)addRoundedCorners:(UIRectCorner)corners withRadii:(CGSize)radii;
-(CALayer*)maskForRoundedCorners:(UIRectCorner)corners withRadii:(CGSize)radii;
@end
Run Code Online (Sandbox Code Playgroud)
#import "UIView+Roundify.h"
@implementation UIView (Roundify)
-(void)addRoundedCorners:(UIRectCorner)corners withRadii:(CGSize)radii {
CALayer *tMaskLayer = [self maskForRoundedCorners:corners withRadii:radii];
self.layer.mask = tMaskLayer;
}
-(CALayer*)maskForRoundedCorners:(UIRectCorner)corners withRadii:(CGSize)radii {
CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.frame = self.bounds;
UIBezierPath *roundedPath = [UIBezierPath bezierPathWithRoundedRect:
maskLayer.bounds byRoundingCorners:corners cornerRadii:radii];
maskLayer.fillColor = [[UIColor whiteColor] CGColor];
maskLayer.backgroundColor = [[UIColor clearColor] CGColor];
maskLayer.path = [roundedPath CGPath];
return maskLayer;
}
@end
Run Code Online (Sandbox Code Playgroud)
致电:
[myView addRoundedCorners:UIRectCornerBottomLeft | UIRectCornerBottomRight
withRadii:CGSizeMake(20.0f, 20.0f)];
Run Code Online (Sandbox Code Playgroud)
Jos*_*eso 24
为了扩展PL的答案我改写了方法,因为它没有UIButton正确地舍入某些对象
- (void)setMaskTo:(id)sender byRoundingCorners:(UIRectCorner)corners withCornerRadii:(CGSize)radii
{
// UIButton requires this
[sender layer].cornerRadius = 0.0;
UIBezierPath *shapePath = [UIBezierPath bezierPathWithRoundedRect:[sender bounds]
byRoundingCorners:corners
cornerRadii:radii];
CAShapeLayer *newCornerLayer = [CAShapeLayer layer];
newCornerLayer.frame = [sender bounds];
newCornerLayer.path = shapePath.CGPath;
[sender layer].mask = newCornerLayer;
}
Run Code Online (Sandbox Code Playgroud)
并称之为
[self setMaskTo:self.continueButton byRoundingCorners:UIRectCornerBottomLeft|UIRectCornerBottomRight withCornerRadii:CGSizeMake(3.0, 3.0)];
Run Code Online (Sandbox Code Playgroud)
Kev*_*ord 11
如果你想在Swift中这样做,你可以使用a的扩展名UIView.通过这样做,所有子类都将能够使用以下方法:
import QuartzCore
extension UIView {
func roundCorner(corners: UIRectCorner, radius: CGFloat) {
let maskPath = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
let maskLayer = CAShapeLayer()
maskLayer.frame = bounds
maskLayer.path = maskPath.CGPath
layer.mask = maskLayer
}
}
Run Code Online (Sandbox Code Playgroud)
用法示例:
self.anImageView.roundCorner(.topRight, radius: 10)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
67627 次 |
| 最近记录: |