不久之前,我发布了一个关于rounding just two corners of a view的问题,并得到了很好的回应,但是在实现它时遇到了问题 . 这是我的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);
}
正在调用该方法,但似乎不会影响视图的结果 . 有什么想法吗?
18 回答
iOS 11中引入了CACornerMask,它有助于在视图层中定义topleft,topright,bottomleft,bottom right . 以下是使用示例 .
在这里,我尝试仅舍入两个顶角:
提前致谢 .
仅供参考文献:
据我所知,如果你还需要掩盖子视图,你可以使用
CALayer
掩蔽 . 有两种方法可以做到这一点 . 第一个是更优雅,第二个是解决方法:-)但它也很快 . 两者都基于CALayer
掩蔽 . 我去年在几个项目中使用了这两种方法,然后我希望你能找到有用的东西 .解决方案1
首先,我创建了这个函数来动态生成一个图像蒙版(
UIImage
),我需要圆角 . 该功能基本上需要5个参数:图像边界和4个角半径(左上角,右上角,左下角和右下角) .现在你只需要几行代码 . 我把东西放在我的viewController
viewDidLoad
方法中,因为它更快,但你也可以在自定义UIView
中使用它,例如layoutSubviews
方法 .解决方案2
这个解决方案多一点"dirty" . 基本上你可以用你需要的圆角创建一个遮罩层(所有角落) . 然后,您应该通过角半径的值增加遮罩层的高度 . 通过这种方式,底部圆角被隐藏,您只能看到上圆角 . 我把代码放在
viewDidLoad
方法中因为它更快但你也可以在自定义UIView
中使用它与示例中的layoutSubviews
方法 .希望这可以帮助 . 再见!
通过几个答案和评论,我发现使用
UIBezierPath bezierPathWithRoundedRect
和CAShapeLayer
是最简单和最直接的方式 . 它可能不适用于非常复杂的情况,但是对于偶尔的角落圆角,它对我来说工作快速而顺畅 .我创建了一个简化的帮助器,在面具中设置适当的角落:
要使用它,只需使用适当的UIRectCorner枚举调用,例如:
请注意,对我来说,我使用它来分组UITableViewCell中的照片圆角,10.0半径适合我,如果需要只是根据需要更改值 .
EDIT: 只是注意到之前的回答非常类似于这个(link) . 如果需要,您仍然可以将此答案用作附加的便利功能 .
EDIT: 与Swift 3中的UIView扩展名相同的代码
要使用它,只需在
UIView
上调用maskByRoundingCorner
:在评论@ lomanf的答案时,我无法满足这一切 . 所以我将其添加为答案 .
就像@lomanf说的那样,你需要添加一个图层蒙版来防止子图层在你的路径之外绘制's bounds. It'现在要容易得多了 . 只要您需要使用石英创建图像并将其设置为蒙版 . 您可以使用
UIBezierPath
创建CAShapeLayer
并将其用作蒙版 .此外,在使用图层蒙版时,请确保在添加蒙版时,您正在屏蔽的图层不是任何图层层次结构的一部分 . 否则行为未定义 . 如果您的视图已经在层次结构中,则需要将其从超级视图中删除,将其屏蔽,然后将其放回原位 .
由于Core Animation渲染的工作方式,掩蔽操作相对较慢 . 每个掩码需要额外的渲染通道 . 所以请谨慎使用面具 .
这种方法的最佳部分之一是您不再需要创建自定义
UIView
并覆盖drawRect:
. 这应该使您的代码更简单,甚至更快 .我是've taken Nathan'的例子并在
UIView
上创建了一个类别,以允许其遵守DRY原则 . 无需再费周折:UIView Roundify.h
UIView Roundify.m
致电:
要在P.L 's answer I rewrote the method like so as it wasn' t上稍微扩展某些对象,例如
UIButton
并称之为
如果你想在Swift中做到这一点,你可以使用
UIView
的扩展名 . 通过这样做,所有子类都将能够使用以下方法:用法示例:
根据您的需要更改 "AllCorners" .
提供的所有解决方案都实现了目标 . 但是,
UIConstraints
有时可能会打击它 .Highlighting:
如果此代码在
viewDidLoad
中设置,则上面的代码段将仅围绕右上角 . 因为roundedView.bounds
将在约束更新UIView
后更改 .创建一个遮罩并将其设置在视图的图层上
从您的代码开始,您可能会使用下面的代码段 .
我'm not sure if this is the sort of result you'之后 . 值得注意的是,如果/当系统再次调用drawRect:再次要求重绘部分rect时,这将表现得非常奇怪 . 如上所述,Nevan's approach可能是一个更好的方法 .
Bezier路径是anwer,如果你需要额外的代码,这个为我工作:https://stackoverflow.com/a/13163693/936957
UIBezierPath解决方案 .
扩展接受的答案,让我们添加向后兼容性 . 在iOS 11之前,view.layer.maskedCorners不可用 . 所以我们可以这样做
我们已经将maskByRoundingCorners编写为UIView扩展,以便改进代码重用 .
致@SachinVsSachin和@ P.L :)我已经将他们的代码组合起来以使其更好 .
这只有在某些事情设置正确的情况下才有效:
clipsToBounds必须设置为YES
不透明必须是NO
backgroundColor应为"clearColor"(我不完全确定)
contentMode必须是"UIContentModeRedraw",因为如果没有,则不经常调用drawRect
必须在CGContextClip之后调用
[super drawRect:rect]
您的视图可能不包含任意子视图(不确定)
务必至少设置一次"needsDisplay:"以触发您的画笔
一个稍微hacky,但相对简单(没有子类,掩码等)的方式是有两个UIViews . 两者都
clipToBounds = YES
. 在子视图上设置圆角,然后将其放置在父视图中,以便裁剪您想要的直角 .不支持您希望两个对角相对的圆角圆滑的情况 .
我意识到你正试图绕过UITableView的前两个角,但出于某种原因我发现最好的解决方案是使用:
程序上它应该围绕所有四个角落,但由于某种原因它只围绕前两个 . **请参阅下面的屏幕截图,看看我上面编写的代码的效果 .
我希望这有帮助!
你可能需要剪辑到边界 . 添加行
在代码中的某个地方设置该属性 .