ios 快速创建一个只有两个圆角的矩形?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/29618760/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Create a rectangle with just two rounded corners in swift?
提问by Maralc
I need to create a rectangle that have just two rounded corners in swift (Objective C code also ok).
我需要快速创建一个只有两个圆角的矩形(Objective C 代码也可以)。
At the moment my code is creating two rectangles with
目前我的代码正在创建两个矩形
CGPathCreateWithRoundedRect(CGRectMake(0, 0, 30, 60), 5, 5, nil);
and
和
CGPathCreateWithRoundedRect(CGRectMake(0, 0, 30, 60), 0, 0, nil);
and merging them (to have two right angle corners and two rounded ones) but I am not happy with the code and I am pretty sure there should be much better ways to do it.
并合并它们(有两个直角和两个圆角)但我对代码不满意,我很确定应该有更好的方法来做到这一点。
I am new to iOS and graphical development and swift.
我是 iOS 和图形开发的新手,而且很快。
回答by iwasrobbed
Here's a quick Swift 3 extension you can use to do rounding and optional borders.
这是一个快速的 Swift 3 扩展,您可以使用它来进行舍入和可选边框。
Note: if you're using autolayout, you may need to call this in one of the view lifecycle callbacks like viewDidLayoutSubviews
or layoutSubviews
after the view has been constrained.
注意:如果您使用自动布局,您可能需要在视图生命周期回调之一中调用它,例如viewDidLayoutSubviews
或layoutSubviews
在视图被约束之后。
import UIKit
extension UIView {
/**
Rounds the given set of corners to the specified radius
- parameter corners: Corners to round
- parameter radius: Radius to round to
*/
func round(corners: UIRectCorner, radius: CGFloat) {
_ = _round(corners: corners, radius: radius)
}
/**
Rounds the given set of corners to the specified radius with a border
- parameter corners: Corners to round
- parameter radius: Radius to round to
- parameter borderColor: The border color
- parameter borderWidth: The border width
*/
func round(corners: UIRectCorner, radius: CGFloat, borderColor: UIColor, borderWidth: CGFloat) {
let mask = _round(corners: corners, radius: radius)
addBorder(mask: mask, borderColor: borderColor, borderWidth: borderWidth)
}
/**
Fully rounds an autolayout view (e.g. one with no known frame) with the given diameter and border
- parameter diameter: The view's diameter
- parameter borderColor: The border color
- parameter borderWidth: The border width
*/
func fullyRound(diameter: CGFloat, borderColor: UIColor, borderWidth: CGFloat) {
layer.masksToBounds = true
layer.cornerRadius = diameter / 2
layer.borderWidth = borderWidth
layer.borderColor = borderColor.cgColor;
}
}
private extension UIView {
@discardableResult func _round(corners: UIRectCorner, radius: CGFloat) -> CAShapeLayer {
let path = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
let mask = CAShapeLayer()
mask.path = path.cgPath
self.layer.mask = mask
return mask
}
func addBorder(mask: CAShapeLayer, borderColor: UIColor, borderWidth: CGFloat) {
let borderLayer = CAShapeLayer()
borderLayer.path = mask.path
borderLayer.fillColor = UIColor.clear.cgColor
borderLayer.strokeColor = borderColor.cgColor
borderLayer.lineWidth = borderWidth
borderLayer.frame = bounds
layer.addSublayer(borderLayer)
}
}
回答by Sanjay Mohnani
In Swift 2.3you could do so by
在Swift 2.3你可以这样做
let maskPath = UIBezierPath(roundedRect: anyView.bounds,
byRoundingCorners: [.BottomLeft, .BottomRight],
cornerRadii: CGSize(width: 10.0, height: 10.0))
let shape = CAShapeLayer()
shape.path = maskPath.CGPath
view.layer.mask = shape
In Objective-Cyou could use the UIBezierPath
class method
在Objective-C 中,你可以使用UIBezierPath
class 方法
bezierPathWithRoundedRect:byRoundingCorners:cornerRadii:
example implementation-
示例实现-
// set the corner radius to the specified corners of the passed container
- (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;
}
and call the above method as-
并将上述方法称为-
[self setMaskTo:anyView byRoundingCorners:UIRectCornerBottomLeft | UIRectCornerBottomRight];
回答by wcarhart
Swift 4+, iOS 11+
斯威夫特 4+,iOS 11+
If you already have a UIView
named myView
referenced as an IBOutlet
, try adding the following two lines in ViewDidLoad()
or wherever it's being loaded:
如果您已经有一个UIView
被myView
引用为 an的命名IBOutlet
,请尝试在ViewDidLoad()
加载它的地方或任何地方添加以下两行:
myView.layer.cornerRadius = 10
myView.layer.maskedCorners = [.layerMinXMaxYCorner, .layerMaxXMaxYCorner]
You can change the array []
to any combination of MinX
, MinY
, MaxX
, and MaxY
to select the desired corners. The above example rounds the bottom two corners.
可以将阵列改变[]
到的任何组合MinX
,MinY
,MaxX
,和MaxY
选择所需的角落。上面的例子圆了底部的两个角。
This is just another approach, can be a bit simpler depending on your design.
这只是另一种方法,根据您的设计可能会更简单一些。
回答by budidino
Swift 3- Useful UIView
extension when you need to round specific corners of some views:
Swift 3-UIView
当您需要圆某些视图的特定角时的有用扩展:
extension UIView {
func round(corners: UIRectCorner, radius: CGFloat) {
let path = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
let mask = CAShapeLayer()
mask.path = path.cgPath
self.layer.mask = mask
}
}
then just use it like this:
然后像这样使用它:
someView.round(corners: [.topLeft, .topRight], radius: 5)
回答by Eric
Building on top of Sanjay's excellent answer, I wrote a quick CALayer extension for Swift 2.3, in case you need to do this sort of "only round some corners" thing more than once.
以 Sanjay 的出色回答为基础,我为 Swift 2.3 编写了一个快速的 CALayer 扩展,以防您需要不止一次地做这种“只绕过某些角落”的事情。
extension CALayer {
func roundCorners(corners: UIRectCorner, radius: CGFloat) {
let maskPath = UIBezierPath(roundedRect: bounds,
byRoundingCorners: corners,
cornerRadii: CGSize(width: radius, height: radius))
let shape = CAShapeLayer()
shape.path = maskPath.CGPath
mask = shape
}
}
Usage:
用法:
myView.layer.roundCorners([.TopLeft, .TopRight], radius: myCornerRadius)
Swift 3.0 (In this example the bounds came from the view not from the layer. Using the bounds from the view make this code to work with views in a UITableViewCell.):
Swift 3.0(在这个例子中,边界来自视图而不是层。使用视图的边界使这段代码可以与 UITableViewCell 中的视图一起使用。):
func roundCorners(corners: UIRectCorner, radius: CGFloat, viewBounds: CGRect) {
let maskPath = UIBezierPath(roundedRect: viewBounds,
byRoundingCorners: corners,
cornerRadii: CGSize(width: radius, height: radius))
let shape = CAShapeLayer()
shape.path = maskPath.cgPath
mask = shape
}
Usage:
用法:
myView.layer.roundCorners(corners: [.topLeft, .topRight], radius: myCornerRadius, viewBounds: bounds)
回答by Andy
Here is what you do in Swift 2.0
这是您在Swift 2.0 中所做的
var maskPath = UIBezierPath(roundedRect: anyView.bounds,
byRoundingCorners: [.BottomLeft, .BottomRight],
cornerRadii: CGSize(width: 10.0, height: 10.0))
回答by Fattie
2017...
2017...
@IBDesignable
class RoundedEnds: UIView {
override func layoutSubviews() { setup() } // "layoutSubviews" is best
func setup() {
let r = self.bounds.size.height / 2
let path = UIBezierPath(roundedRect: self.bounds, cornerRadius:r)
let mask = CAShapeLayer()
mask.path = path.cgPath
self.layer.mask = mask
}
}
For only some corners, just change to:
只有一些角落,只需更改为:
roundedRect: self.bounds,
byRoundingCorners: [.topLeft, .topRight],
cornerRadii: CGSize(width: r, height: r)
Note that as usual there have been many small changes in Swift, eg capitalization of constants, etc.
请注意,像往常一样,Swift 中有许多小的变化,例如常量的大写等。
回答by Bogdan Bystritskiy
Swift 4:
斯威夫特 4:
let maskPath = UIBezierPath(
roundedRect: view.bounds,
byRoundingCorners: [.allCorners],
cornerRadii: CGSize(width: 10.0, height: 10.0)
)
let shape = CAShapeLayer()
shape.path = maskPath.cgPath
view.layer.mask = shape
回答by cjnevin
Updated iWasRobbed's answer to work with the Swift 3.0 GM version:
更新了 iWasRobbed 的答案以使用 Swift 3.0 GM 版本:
import UIKit
extension UIView {
/**
Rounds the given set of corners to the specified radius
- parameter corners: Corners to round
- parameter radius: Radius to round to
*/
func round(corners: UIRectCorner, radius: CGFloat) {
_round(corners: corners, radius: radius)
}
/**
Rounds the given set of corners to the specified radius with a border
- parameter corners: Corners to round
- parameter radius: Radius to round to
- parameter borderColor: The border color
- parameter borderWidth: The border width
*/
func round(corners: UIRectCorner, radius: CGFloat, borderColor: UIColor, borderWidth: CGFloat) {
let mask = _round(corners: corners, radius: radius)
addBorder(mask: mask, borderColor: borderColor, borderWidth: borderWidth)
}
/**
Fully rounds an autolayout view (e.g. one with no known frame) with the given diameter and border
- parameter diameter: The view's diameter
- parameter borderColor: The border color
- parameter borderWidth: The border width
*/
func fullyRound(diameter: CGFloat, borderColor: UIColor, borderWidth: CGFloat) {
layer.masksToBounds = true
layer.cornerRadius = diameter / 2
layer.borderWidth = borderWidth
layer.borderColor = borderColor.cgColor;
}
}
private extension UIView {
@discardableResult func _round(corners: UIRectCorner, radius: CGFloat) -> CAShapeLayer {
let path = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
let mask = CAShapeLayer()
mask.path = path.cgPath
self.layer.mask = mask
return mask
}
func addBorder(mask: CAShapeLayer, borderColor: UIColor, borderWidth: CGFloat) {
let borderLayer = CAShapeLayer()
borderLayer.path = mask.path
borderLayer.fillColor = UIColor.clear.cgColor
borderLayer.strokeColor = borderColor.cgColor
borderLayer.lineWidth = borderWidth
borderLayer.frame = bounds
layer.addSublayer(borderLayer)
}
}
回答by rawnly
iOS 11+ Only | You can check iOS usage stats here
仅限 iOS 11+ | 您可以在此处查看 iOS 使用情况统计信息
Explanation
解释
Since the CACornerMask
rawValue is an UInt
you know that a CACornerMask
rawValueis the sum of each CACornerMask.Element
rawValue
由于CACornerMask
rawValue 是一个UInt
你知道一个CACornerMask
rawValue是每个rawValue的总和CACornerMask.Element
More specifically:
进一步来说:
- TopLeft (
layerMinXMinYCorner
) = 1 - TopRight (
layerMaxXMinYCorner
) = 2 - BottomLeft (
layerMinXMaxYCorner
) = 4 - BottomRight (
layerMaxXMaxYCorner
) = 8
- 左上角 (
layerMinXMinYCorner
) = 1 - 右上 (
layerMaxXMinYCorner
) = 2 - 左下角 (
layerMinXMaxYCorner
) = 4 - 右下角 (
layerMaxXMaxYCorner
) = 8
So for example if you want top leftand top rightcorners you can just type CACornerMask(rawValue: 3)
.
因此,例如,如果您想要左上角和右上角,则只需键入CACornerMask(rawValue: 3)
.
?Example
?例子
Below a simple extension of an UIView
下面是一个简单的扩展 UIView
extension UIView {
enum Corner:Int {
case bottomRight = 0,
topRight,
bottomLeft,
topLeft
}
private func parseCorner(corner: Corner) -> CACornerMask.Element {
let corners: [CACornerMask.Element] = [.layerMaxXMaxYCorner, .layerMaxXMinYCorner, .layerMinXMaxYCorner, .layerMinXMinYCorner]
return corners[corner.rawValue]
}
private func createMask(corners: [Corner]) -> UInt {
return corners.reduce(0, { (a, b) -> UInt in
return a + parseCorner(corner: b).rawValue
})
}
func roundCorners(corners: [Corner], amount: CGFloat = 5) {
layer.cornerRadius = amount
let maskedCorners: CACornerMask = CACornerMask(rawValue: createMask(corners: corners))
layer.maskedCorners = maskedCorners
}
}
You can use this like:
你可以这样使用:
let myRect = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 50))
myRect.roundCorners(corners: [.topRight, .topLeft])