Создать прямоугольник с двумя закругленными углами?
Мне нужно создать прямоугольник с двумя закругленными углами в быстром (Objective C code также хорошо).
В настоящий момент мой код создает два прямоугольника с
CGPathCreateWithRoundedRect(CGRectMake(0, 0, 30, 60), 5, 5, nil);
и
CGPathCreateWithRoundedRect(CGRectMake(0, 0, 30, 60), 0, 0, nil);
и слияние их (чтобы иметь два угла с прямым углом и два закругленных), но я не доволен кодом, и я уверен, что должны быть гораздо лучшие способы сделать это.
Я новичок в iOS и графическом развитии и быстро.
Ответы
Ответ 1
В 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];
Ответ 2
Здесь быстро расширяется расширение Swift 3, которое можно использовать для округления и дополнительных границ.
Примечание. Если вы используете автозапуск, вам может потребоваться вызвать это в одном из обратных вызовов жизненного цикла вида, например 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 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)
}
}
Ответ 3
Swift 4+, iOS 11+
Если у вас уже есть UIView
именем myView
ссылается как IBOutlet
, попробуйте добавить следующие две строки в ViewDidLoad()
или везде, где они загружаются:
myView.layer.cornerRadius = 10
myView.layer.maskedCorners = [.layerMinXMaxYCorner, .layerMaxXMaxYCorner]
Вы можете изменить массив []
на любую комбинацию MinX
, MinY
, MaxX
и MaxY
чтобы выбрать нужные углы. Вышеприведенный пример округляет нижние два угла.
Это просто другой подход, который может быть немного проще в зависимости от вашего дизайна.
Ответ 4
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)
Ответ 5
Основываясь на превосходном ответе Санджая, я написал быстрое расширение CALayer для Swift 2.3, на случай, если вам понадобится сделать это "только вокруг некоторых углов" более одного раза.
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)
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
}
Использование:
myView.layer.roundCorners(corners: [.topLeft, .topRight], radius: myCornerRadius, viewBounds: bounds)
Ответ 6
Вот что вы делаете в Swift 2.0
var maskPath = UIBezierPath(roundedRect: anyView.bounds,
byRoundingCorners: [.BottomLeft, .BottomRight],
cornerRadii: CGSize(width: 10.0, height: 10.0))
Ответ 7
2017...
![enter image description here]()
@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
}
}
Для некоторых углов просто измените на:
![enter image description here]()
roundedRect: self.bounds,
byRoundingCorners: [.topLeft, .topRight],
cornerRadii: CGSize(width: r, height: r)
Обратите внимание, что, как обычно, в Swift было много небольших изменений, например, капитализация констант и т.д.
Ответ 8
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
Ответ 9
Обновлен ответ 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 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)
}
}
Ответ 10
iOS 11+ Только | Вы можете проверить статистику использования iOS здесь
объяснение
Поскольку CACornerMask
rawValue является UInt
вы знаете, что CACornerMask
rawValue является суммой каждого CACornerMask.Element
rawValue.
Более конкретно:
- TopLeft (
layerMinXMinYCorner
) = 1 - TopRight (
layerMaxXMinYCorner
) = 2 - BottomLeft (
layerMinXMaxYCorner
) = 4 - BottomRight (
layerMaxXMaxYCorner
) = 8
Так, например, если вы хотите верхний левый и верхний правый углы, вы можете просто набрать CACornerMask(rawValue: 3)
.
пример
Ниже простое расширение 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
}
}
Вы можете использовать это как:
let myRect = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 50))
myRect.roundCorners(corners: [.topRight, .topLeft])
Ответ 11
Objective-C версия ответа iWasRobbed:
UIView + RoundCorners.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 diameter
- parameter borderColor: The border color
- parameter borderWidth: The border width
*/
- (void)fullyRoundWithDiameter:(CGFloat)diameter borderColor:(UIColor *)borderColor borderWidth:(CGFloat)borderWidth;
@end
UIView + RoundCorners.m
#import "UIView+RoundCorners.h"
@implementation UIView (RoundCorners)
- (void)roundCorners:(UIRectCorner)corners radius:(CGFloat)radius {
[self _roundCorners:corners radius:radius];
}
- (void)roundCorners:(UIRectCorner)corners radius:(CGFloat)radius borderColor:(UIColor *)borderColor borderWidth:(CGFloat)borderWidth {
CAShapeLayer *mask = [self _roundCorners:corners radius:radius];
[self addBorderWithMask:mask borderColor:borderColor borderWidth:borderWidth];
}
- (void)fullyRoundWithDiameter:(CGFloat)diameter borderColor:(UIColor *)borderColor borderWidth:(CGFloat)borderWidth {
self.layer.masksToBounds = YES;
self.layer.cornerRadius = diameter / 2;
self.layer.borderWidth = borderWidth;
self.layer.borderColor = borderColor.CGColor;
}
- (CAShapeLayer *)_roundCorners:(UIRectCorner)corners radius:(CGFloat)radius {
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:corners cornerRadii:CGSizeMake(radius, radius)];
CAShapeLayer *mask = [CAShapeLayer layer];
mask.path = path.CGPath;
self.layer.mask = mask;
return mask;
}
- (void)addBorderWithMask:(CAShapeLayer *)mask borderColor:(UIColor *)borderColor borderWidth:(CGFloat)borderWidth {
CAShapeLayer *borderLayer = [CAShapeLayer layer];
borderLayer.path = mask.path;
borderLayer.fillColor = UIColor.clearColor.CGColor;
borderLayer.strokeColor = borderColor.CGColor;
borderLayer.lineWidth = borderWidth;
borderLayer.frame = self.bounds;
[self.layer addSublayer:borderLayer];
}
@end
Ответ 12
Один простой взлом может быть следующим. Возьмите взгляды как пример ниже в изображении. Красный вид будет иметь закругленные углы, а желтый вид (внутри красного вида) предотвратит скругление углов
![enter image description here]()
Теперь напишите ниже код для Red View.
self.myView.layer.cornerRadius = 15
Удостоверьтесь, что вы не пишете код как clipsToBounds = true или masksToBounds = true.
Ниже изображение является результатом
![enter image description here]()
Размещение Yellow View решит, какие 2 угла не будут округлены. Надеюсь, это легко реализовать.
Ответ 13
В итоге вы можете создать красивое расширение, например, так:
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)
Вот все значения углов:
- .topLeft
- .topRight
- .bottomLeft
- .Нижний правый