目前设置UIView角落半径的“正确”方法是什么?

时间:2017-06-18 05:02:06

标签: ios swift uiview

设置UIView的角半径可以通过以下方式完成:

  1. 设置layer的{​​{1}}属性:

    cornerRadius
  2. 涂抹面膜:

    view.layer.cornerRadius = 5;
    view.layer.masksToBounds = true;
    
  3. 覆盖func roundCorners(corners:UIRectCorner, radius: CGFloat) { let path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius)) let mask = CAShapeLayer() mask.path = path.cgPath self.layer.mask = mask }

    draw(_:)
  4. 这些通常被认为是在func draw(_ rect: CGRect) { // Size of rounded rectangle let rectWidth = rect.width let rectHeight = rect.height // Find center of actual frame to set rectangle in middle let xf: CGFloat = (self.frame.width - rectWidth) / 2 let yf: CGFloat = (self.frame.height - rectHeight) / 2 let ctx = UIGraphicsGetCurrentContext()! ctx.saveGState() let rect = CGRect(x: xf, y: yf, width: rectWidth, height: rectHeight) let clipPath = UIBezierPath(roundedRect: rect, cornerRadius: rectCornerRadius).cgPath ctx.addPath(clipPath) ctx.setFillColor(rectBgColor.cgColor) ctx.closePath() ctx.fillPath() ctx.restoreGState() } 上实施圆角的“正确”方式,符合以下标准:

    • 配置(某些角落可能会被舍入,而其他角落则不会)
    • 动画(可以动画UIView更改)
    • 灵活性(它是否会破坏您已应用的第三方库或掩码)
    • 可读性(解决方案的简洁/可重用性)
    • 速度(对性能产生负面影响)

5 个答案:

答案 0 :(得分:7)

重申三个选择:

  1. 使用CALayer现有属性:这是一种简单(可能是最有效)的简单角落遮罩解决方案。它也是可动画的。在iOS 11中,您可以选择蒙面角。

  2. 重新定制CAShapeLayer面具:如果角落遮挡不是简单的圆角,而是一些任意路径,这是很好的方法。如果frame发生更改(例如在视图的layoutSubviews或控制器的viewDidLayoutSubviews中),则必须小心谨慎以确保更新此掩码。动画需要更多的工作。

  3. 重新定制draw(_:):这比其价值更多的工作,你可能不会享受Apple团队可能在幕后所做的优化(例如,后续的draw来电是什么只绘制完整bounds的一部分;无论如何,您的代码都会重绘整个内容。

  4. 我建议选项1用于简单案例,如果你需要更多控制而不是选项1可以提供选项2。但是没有“最好的”方法:这取决于你需要什么以及你愿意经历多少工作。

答案 1 :(得分:7)

我使用iOS 11或更低版本进行了一些测试以及我发现的最佳练习,可以绕过特定或所有角落,您可以使用下一个代码。

// Full size
CGSize vSize = [UIScreen mainScreen].bounds.size;

// Object
UIView *viewTest = [[UIView alloc] initWithFrame: CGRectMake(0, 0, vSize.width, vSize.height)];
[viewTest setAutoresizingMask: UIViewAutoresizingFlexibleHeight];
[viewTest setBackgroundColor: [UIColor grayColor]];

// maskedCorners is only available in iOS 11
if (@available(iOS 11.0, *)) {
    [viewTest setClipsToBounds: YES];
    [viewTest.layer setCornerRadius: 10];

    // Only if you want to round the left and right top corners
    [viewTest.layer setMaskedCorners: kCALayerMinXMinYCorner | kCALayerMaxXMinYCorner];
}
else {
    // The old way used in lower version
    CAShapeLayer *shapeLayerObj = [CAShapeLayer layer];
    [shapeLayerObj setPath: [UIBezierPath bezierPathWithRoundedRect: viewTest.bounds byRoundingCorners: UIRectCornerTopLeft | UIRectCornerTopRight cornerRadii: (CGSize){10.0, 10.}].CGPath];

    [viewTest.layer setMask: shapeLayerObj];
}
  • 此代码解决了autoResizingMask在使用旧方法圆角时不起作用的问题。
  • 使用圆角修复UIScrollView的错误,将setContentSize major修复为对象的高度。

快速版本就是这样的

let view = UIView()
view.clipsToBounds = true
view.layer.cornerRadius = 8
view.layer.maskedCorners = [.layerMaxXMaxYCorner, .layerMinXMaxYCorner]

答案 2 :(得分:6)

从iOS 11向上

您可以通过设置以下属性在Identity inspector的{​​{1}}中使用用户定义的运行时属性:

Interface Builder

根据documentation of the CACornerMask,您可以看到layer.cornerRadius layer.maskedCorners layer.masksToBounds 属性实际上是maskedCorners数据类型,并且可以设置以下值:

NSUInteger

由于允许您一起kCALayerMinXMinYCorner = 1U << 0 kCALayerMaxXMinYCorner = 1U << 1 kCALayerMinXMaxYCorner = 1U << 2 kCALayerMaxXMaxYCorner = 1U << 3 使用这些掩码,因此您只需要“计算”该按位或实际所需的整数。

因此,请为bitwise OR属性设置以下数字(整数)值以获取圆角:

maskedCorners

示例:如果要为UIView的左上角和右上角设置拐角半径,则可以使用以下属性:

top-left and top-right corner of a UIView

答案 3 :(得分:5)

我认为这是最全面的摘要:http://texturegroup.org/docs/corner-rounding.html

我的启发式是,如果视图不需要高性能(例如,它不在表视图单元格内),最简单的选择是使用CALayer的cornerRadius。如果您需要更高级的角半径或高性能,那么最好探索其他选项。

答案 4 :(得分:1)

我选择第一个,它是更干净的方式,你可以在没有代码的IDE中完成它。打开属性检查器,然后单击Identity检查器并在“User Defined Runtime attributes”下添加这两个属性:

enter image description here