Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 在swift中创建一个只有两个圆角的矩形?_Ios_Swift_Core Graphics - Fatal编程技术网

Ios 在swift中创建一个只有两个圆角的矩形?

Ios 在swift中创建一个只有两个圆角的矩形?,ios,swift,core-graphics,Ios,Swift,Core Graphics,我需要创建一个在swift中只有两个圆角的矩形(目标C代码也可以) 目前,我的代码正在创建两个带有 CGPathCreateWithRoundedRect(CGRectMake(0, 0, 30, 60), 5, 5, nil); 及 合并它们(有两个直角和两个圆角),但我对代码不满意,我很确定应该有更好的方法来实现 我不熟悉iOS、图形开发和swift。在swift 2.3中,您可以通过 let maskPath = UIBezierPath(roundedRect: anyView.bou

我需要创建一个在swift中只有两个圆角的矩形(目标C代码也可以)

目前,我的代码正在创建两个带有

CGPathCreateWithRoundedRect(CGRectMake(0, 0, 30, 60), 5, 5, nil);

合并它们(有两个直角和两个圆角),但我对代码不满意,我很确定应该有更好的方法来实现


我不熟悉iOS、图形开发和swift。

在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

Objective-C中,可以使用
UIBezierPath
类方法

bezierPathWithRoundedRect:byRoundingCorners:cornerRadii:
示例实现-

// 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;
}
并将上述方法调用为-

[self setMaskTo:anyView byRoundingCorners:UIRectCornerBottomLeft | UIRectCornerBottomRight];

以下是您在Swift 2.0中的操作

var maskPath = UIBezierPath(roundedRect: anyView.bounds,
        byRoundingCorners: [.BottomLeft, .BottomRight],
        cornerRadii: CGSize(width: 10.0, height: 10.0))
更新:请参见下面的Swift 4/iOS 11,它非常简单


这里有一个快速的Swift 3扩展,您可以使用它进行取整和可选边框

注意:如果您使用的是autolayout,则可能需要在视图约束后在视图生命周期回调中调用它,如
viewdilayoutsubviews
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)
    }
    
}

Iwasrobed回答的Objective-C版本:

UIView+圆角。h

#import <UIKit/UIKit.h>

@interface UIView (RoundCorners)

/**
 Rounds the given set of corners to the specified radius

 - parameter corners: Corners to round
 - parameter radius:  Radius to round to
 */
- (void)roundCorners:(UIRectCorner)corners radius:(CGFloat)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
 */
- (void)roundCorners:(UIRectCorner)corners radius:(CGFloat)radius borderColor:(UIColor *)borderColor borderWidth:(CGFloat)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
 */
- (void)fullyRoundWithDiameter:(CGFloat)diameter borderColor:(UIColor *)borderColor borderWidth:(CGFloat)borderWidth;

@end

更新了Iwasrobed关于使用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)
    }

}

在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
  }
}
用法:

myView.layer.roundCorners([.TopLeft, .TopRight], radius: myCornerRadius)
myView.layer.roundCorners(corners: [.topLeft, .topRight], radius: myCornerRadius, viewBounds: bounds)
Swift 3.0(在本例中,边界来自视图而非图层。使用视图中的边界可使此代码用于UITableViewCell中的视图):

用法:

myView.layer.roundCorners([.TopLeft, .TopRight], radius: myCornerRadius)
myView.layer.roundCorners(corners: [.topLeft, .topRight], radius: myCornerRadius, viewBounds: bounds)
到2021年为止。。。 请注意,自从很久以前提出这个问题以来,语法/系统已经发生了很大的变化

对于某些角点,只需将代码的
路径
行更改为:


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
  }
}
那么就这样使用它:

someView.round(corners: [.topLeft, .topRight], radius: 5)
extension UIView {

    func roundCorners(_ corners: UIRectCorner, radius: Double) {
        let maskPath = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
        let shape = CAShapeLayer()
        shape.path = maskPath.cgPath
        layer.mask = shape
    }

}
view.roundCorners([.topRight, .bottomRight], radius: 10)

Swift 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

Swift 4+,iOS 11+

如果您已经有一个名为
myView
UIView
被引用为
IBOutlet
,请尝试在
ViewDidLoad()
或加载它的任何位置添加以下两行:

myView.layer.cornerRadius = 10
myView.layer.maskedCorners = [.layerMinXMaxYCorner, .layerMaxXMaxYCorner]
您可以将数组
[]
更改为
MinX
MinY
MaxX
MaxY
的任意组合,以选择所需的角点。上面的示例使底部的两个角变圆

这只是另一种方法,根据您的设计,可能会更简单一些

仅限iOS 11+版本|您可以查看iOS使用情况统计数据

解释 由于
cacornermak
rawValue是一个
UInt
,您知道
cacornermak
rawValue是每个
cacornermak.Element
rawValue的总和

更具体地说:

  • 左上角(
    layerMinyCorner
    )=1
  • 右上角(
    layerMaxMinyCorner
    )=2
  • 左下(
    layerMinXMaxYCorner
    )=4
  • 右下角(
    layerMaxyCorner
    )=8
因此,例如,如果您想要左上右上角,您可以只键入
cacornermak(rawValue:3)


范例 下面是
ui视图的简单扩展

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
    }
}
您可以这样使用:

let myRect = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 50))
myRect.roundCorners(corners: [.topRight, .topLeft])

一个简单的黑客可以如下所示。以下图所示的视图为例红色视图将具有圆角,而黄色视图(内部红色视图)将阻止圆角

现在写下红色视图的代码

        self.myView.layer.cornerRadius = 15
确保您没有将任何代码编写为clipsToBounds=truemasksToBounds=true

下图是结果


黄色视图的位置将决定哪两个角不圆角。希望这很容易实现。

总之,您可以创建如下漂亮的扩展:

someView.round(corners: [.topLeft, .topRight], radius: 5)
extension UIView {

    func roundCorners(_ corners: UIRectCorner, radius: Double) {
        let maskPath = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
        let shape = CAShapeLayer()
        shape.path = maskPath.cgPath
        layer.mask = shape
    }

}
view.roundCorners([.topRight, .bottomRight], radius: 10)
像这样使用它:

someView.round(corners: [.topLeft, .topRight], radius: 5)
extension UIView {

    func roundCorners(_ corners: UIRectCorner, radius: Double) {
        let maskPath = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
        let shape = CAShapeLayer()
        shape.path = maskPath.cgPath
        layer.mask = shape
    }

}
view.roundCorners([.topRight, .bottomRight], radius: 10)
以下是所有角点的值:

  • 左上角
  • 托普赖特先生
  • .左下角
  • .右下角
扩展cacornermak{
公共静态变量leftBottom:cacornermak{get{return.layerMinXMaxYCorner}
公共静态变量rightboottom:cacornermak{get{return.layerMaxXMaxYCorner}
公共静态变量leftTop:cacornermak{get{return.layerMaxXMinYCorner}
公共静态变量rightTop:cacornermak{get{return.layerMinXMinYCorner}
}
伸缩加速计{
func圆角(uu掩码:cacornermak,角点:CGFloat){
self.maskedCorners=掩码
自转角半径=转角
}
}
self.viewBack.layer.roundCorners([.leftBottom,.righbottom],corners:23)
最好的方法


Swift 5:用于左上角和右上角圆角

yourView.layer.cornerRadius = 12
yourView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]

bezierPathWithRoundedRect:byRoundingCorners:cornerRadii:
与往常一样,Swift中有许多小的变化,例如常量的大写等。建议向下滚动到最新的答案。我可以用你的答案解决我的问题。但奇怪的是,当我试图使用UIBezierPath.addArcWithCenter自己绘制圆角时,起点和终点的角度并不匹配上记录的所有角度。您是否询问使用起点和终点角度?#定义弧度(度)((度)/(180.0/mpi))并使用as-double startAngle=弧度(45);双端角=弧度(135);不为底层工作。i、 e.bottomLeft和BottomRight我在UITextField上使用此选项,但它会改变文本字段的宽度。为什么它会更改宽度(使用自动布局设置)。更新:只需在
viewdilayoutsubviews
@Onichan中调用扩展名,我添加了一个
fullyRound
方法,该方法也适用于自动布局视图,因为框架不可用