每个角有不同的角半径

问题描述 投票:0回答:5

我想为 iOS 中的视图设置不同的角半径。我可以将每个角的半径设置为与下一篇文章中提到的相同的值如何仅为 UIView 的左上角和右上角设置cornerRadius?

有没有办法可以按以下格式设置圆角半径?

左上角半径:18
右上角半径:18
右下半径:3
左下半径:18

ios uiview cornerradius
5个回答
58
投票

您想为每个角添加独特的角值吗?

之后要

添加边框吗?

我有一个解决方案,如下所示:

looks like this

首先,添加我制作的UIBezierPath

扩展:

extension UIBezierPath { convenience init(shouldRoundRect rect: CGRect, topLeftRadius: CGSize = .zero, topRightRadius: CGSize = .zero, bottomLeftRadius: CGSize = .zero, bottomRightRadius: CGSize = .zero){ self.init() let path = CGMutablePath() let topLeft = rect.origin let topRight = CGPoint(x: rect.maxX, y: rect.minY) let bottomRight = CGPoint(x: rect.maxX, y: rect.maxY) let bottomLeft = CGPoint(x: rect.minX, y: rect.maxY) if topLeftRadius != .zero{ path.move(to: CGPoint(x: topLeft.x+topLeftRadius.width, y: topLeft.y)) } else { path.move(to: CGPoint(x: topLeft.x, y: topLeft.y)) } if topRightRadius != .zero{ path.addLine(to: CGPoint(x: topRight.x-topRightRadius.width, y: topRight.y)) path.addCurve(to: CGPoint(x: topRight.x, y: topRight.y+topRightRadius.height), control1: CGPoint(x: topRight.x, y: topRight.y), control2:CGPoint(x: topRight.x, y: topRight.y+topRightRadius.height)) } else { path.addLine(to: CGPoint(x: topRight.x, y: topRight.y)) } if bottomRightRadius != .zero{ path.addLine(to: CGPoint(x: bottomRight.x, y: bottomRight.y-bottomRightRadius.height)) path.addCurve(to: CGPoint(x: bottomRight.x-bottomRightRadius.width, y: bottomRight.y), control1: CGPoint(x: bottomRight.x, y: bottomRight.y), control2: CGPoint(x: bottomRight.x-bottomRightRadius.width, y: bottomRight.y)) } else { path.addLine(to: CGPoint(x: bottomRight.x, y: bottomRight.y)) } if bottomLeftRadius != .zero{ path.addLine(to: CGPoint(x: bottomLeft.x+bottomLeftRadius.width, y: bottomLeft.y)) path.addCurve(to: CGPoint(x: bottomLeft.x, y: bottomLeft.y-bottomLeftRadius.height), control1: CGPoint(x: bottomLeft.x, y: bottomLeft.y), control2: CGPoint(x: bottomLeft.x, y: bottomLeft.y-bottomLeftRadius.height)) } else { path.addLine(to: CGPoint(x: bottomLeft.x, y: bottomLeft.y)) } if topLeftRadius != .zero{ path.addLine(to: CGPoint(x: topLeft.x, y: topLeft.y+topLeftRadius.height)) path.addCurve(to: CGPoint(x: topLeft.x+topLeftRadius.width, y: topLeft.y) , control1: CGPoint(x: topLeft.x, y: topLeft.y) , control2: CGPoint(x: topLeft.x+topLeftRadius.width, y: topLeft.y)) } else { path.addLine(to: CGPoint(x: topLeft.x, y: topLeft.y)) } path.closeSubpath() cgPath = path } }

然后,添加这个UIView

扩展:

extension UIView{ func roundCorners(topLeft: CGFloat = 0, topRight: CGFloat = 0, bottomLeft: CGFloat = 0, bottomRight: CGFloat = 0) {//(topLeft: CGFloat, topRight: CGFloat, bottomLeft: CGFloat, bottomRight: CGFloat) { let topLeftRadius = CGSize(width: topLeft, height: topLeft) let topRightRadius = CGSize(width: topRight, height: topRight) let bottomLeftRadius = CGSize(width: bottomLeft, height: bottomLeft) let bottomRightRadius = CGSize(width: bottomRight, height: bottomRight) let maskPath = UIBezierPath(shouldRoundRect: bounds, topLeftRadius: topLeftRadius, topRightRadius: topRightRadius, bottomLeftRadius: bottomLeftRadius, bottomRightRadius: bottomRightRadius) let shape = CAShapeLayer() shape.path = maskPath.cgPath layer.mask = shape } }

最后,调用方法

myView.roundCorners(topLeft: 10, topRight: 20, bottomLeft: 30, bottomRight: 40)

并添加边框。显然,layer.borderRadius 无法正常工作,因此使用

CAShapeLayer

 和之前创建的路径创建边框。 

let borderLayer = CAShapeLayer() borderLayer.path = (myView.layer.mask! as! CAShapeLayer).path! // Reuse the Bezier path borderLayer.strokeColor = UIColor.red.cgColor borderLayer.fillColor = UIColor.clear.cgColor borderLayer.lineWidth = 5 borderLayer.frame = myView.bounds myView.layer.addSublayer(borderLayer)

瞧!


43
投票
您可以将默认的

layer.cornerRadius

设置为最小值,然后将图层蒙版的边框设置为更大的值。 

let demoView = UIView(frame: CGRect(x: 100, y: 200, width: 100, height: 100)) demoView.backgroundColor = UIColor.red demoView.layer.cornerRadius = 3.0 let maskPath = UIBezierPath(roundedRect: demoView.bounds, byRoundingCorners: [.topLeft, .topRight, .bottomLeft], cornerRadii: CGSize(width: 18.0, height: 0.0)) let maskLayer = CAShapeLayer() maskLayer.path = maskPath.cgPath demoView.layer.mask = maskLayer view.addSubview(demoView)
    

9
投票
基于@Kirill Dobryakov 的答案略有改进和简化。曲线可能会留下非常小但明显的不规则性,当您观察它时,您知道它不是理想的圆形(例如,尝试查看边 40 和半径 20)。我不知道这是怎么可能的,但无论如何,最可靠的方法是使用弧线来形成理想的圆角,并且还为您提供一个

@IBDesigneable

组件:

extension UIBezierPath { convenience init(shouldRoundRect rect: CGRect, topLeftRadius: CGFloat, topRightRadius: CGFloat, bottomLeftRadius: CGFloat, bottomRightRadius: CGFloat){ self.init() let path = CGMutablePath() let topLeft = rect.origin let topRight = CGPoint(x: rect.maxX, y: rect.minY) let bottomRight = CGPoint(x: rect.maxX, y: rect.maxY) let bottomLeft = CGPoint(x: rect.minX, y: rect.maxY) if topLeftRadius != 0 { path.move(to: CGPoint(x: topLeft.x + topLeftRadius, y: topLeft.y)) } else { path.move(to: topLeft) } if topRightRadius != 0 { path.addLine(to: CGPoint(x: topRight.x - topRightRadius, y: topRight.y)) path.addArc(tangent1End: topRight, tangent2End: CGPoint(x: topRight.x, y: topRight.y + topRightRadius), radius: topRightRadius) } else { path.addLine(to: topRight) } if bottomRightRadius != 0 { path.addLine(to: CGPoint(x: bottomRight.x, y: bottomRight.y - bottomRightRadius)) path.addArc(tangent1End: bottomRight, tangent2End: CGPoint(x: bottomRight.x - bottomRightRadius, y: bottomRight.y), radius: bottomRightRadius) } else { path.addLine(to: bottomRight) } if bottomLeftRadius != 0 { path.addLine(to: CGPoint(x: bottomLeft.x + bottomLeftRadius, y: bottomLeft.y)) path.addArc(tangent1End: bottomLeft, tangent2End: CGPoint(x: bottomLeft.x, y: bottomLeft.y - bottomLeftRadius), radius: bottomLeftRadius) } else { path.addLine(to: bottomLeft) } if topLeftRadius != 0 { path.addLine(to: CGPoint(x: topLeft.x, y: topLeft.y + topLeftRadius)) path.addArc(tangent1End: topLeft, tangent2End: CGPoint(x: topLeft.x + topLeftRadius, y: topLeft.y), radius: topLeftRadius) } else { path.addLine(to: topLeft) } path.closeSubpath() cgPath = path } } @IBDesignable open class VariableCornerRadiusView: UIView { private func applyRadiusMaskFor() { let path = UIBezierPath(shouldRoundRect: bounds, topLeftRadius: topLeftRadius, topRightRadius: topRightRadius, bottomLeftRadius: bottomLeftRadius, bottomRightRadius: bottomRightRadius) let shape = CAShapeLayer() shape.path = path.cgPath layer.mask = shape } @IBInspectable open var topLeftRadius: CGFloat = 0 { didSet { setNeedsLayout() } } @IBInspectable open var topRightRadius: CGFloat = 0 { didSet { setNeedsLayout() } } @IBInspectable open var bottomLeftRadius: CGFloat = 0 { didSet { setNeedsLayout() } } @IBInspectable open var bottomRightRadius: CGFloat = 0 { didSet { setNeedsLayout() } } override open func layoutSubviews() { super.layoutSubviews() applyRadiusMaskFor() } }
    

0
投票
我发现使用贝塞尔曲线和蒙版的所有答案都非常聪明,但我个人更喜欢通过使用连续的角半径来坚持 SwiftUI 中已有的方法。例如,尝试将其添加到您的视图中以获得 2 个不同的顶角:

.cornerRadius(20, corners: [.topRight]).cornerRadius(10, corners: [.topLeft])
    

-1
投票
iOS 11之后最好的方法,这样看起来更流畅。

func roundCorners(_ corners: UIRectCorner, radius: CGFloat) { clipsToBounds = true layer.cornerRadius = radius layer.maskedCorners = CACornerMask(rawValue: corners.rawValue) }
原始答案:

https://stackoverflow.com/a/50289822/4206186

© www.soinside.com 2019 - 2024. All rights reserved.