Какой в настоящее время "правильный" способ установить угловой радиус UIView?
Настройка UIView
Радиус угла наклона можно сделать следующими способами:
Установить
layer
"scornerRadius
имущество:view.layer.cornerRadius = 5; view.layer.masksToBounds = true;
Применить маску:
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 }
Override
draw(_:)
: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
, учитывая следующие критерии:
- конфигурация (некоторые углы могут быть закруглены, а другие нет)
- анимация (вы можете оживить
cornerRadius
изменение) - гибкость (нарушает ли вы сторонние библиотеки или маски, которые вы уже применили)
- удобочитаемость (насколько кратко / многократно используется решение)
- скорость (влияет ли это на производительность)
6 ответов
Начиная с iOS 11
вы можете использовать определенные пользователем атрибуты времени выполнения в Identity inspector
из Interface Builder
установив следующие свойства:
layer.cornerRadius
layer.maskedCorners
layer.masksToBounds
Согласно документации CACornerMask вы можете видеть, чтоmaskedCorners
недвижимость на самом деле NSUInteger
тип данных, и вы можете установить следующие значения:
kCALayerMinXMinYCorner = 1U << 0
kCALayerMaxXMinYCorner = 1U << 1
kCALayerMinXMaxYCorner = 1U << 2
kCALayerMaxXMaxYCorner = 1U << 3
Поскольку вам разрешено bitwise OR
эти маски вместе, вам нужно только "вычислить" результирующее целое число побитового ИЛИ того, что вам действительно нужно.
Поэтому установите следующие числовые (целые) значения для maskedCorners
свойство получать закругленные углы:
0 = no corner is being rounded
1 = top left corner rounded only
2 = top right corner rounded only
3 = top left and top right corners rounded only
4 = bottom left corner rounded only
5 = top left and bottom left corners rounded only
6 = top right and bottom left corners rounded only
7 = top left, top right and bottom left corners rounded only
8 = bottom right corner rounded only
9 = top left and bottom right corners rounded only
10 = top right and bottom right corners rounded only
11 = top left, top right and bottom right corners rounded only
12 = bottom left and bottom right corners rounded only
13 = top left, bottom left and bottom right corners rounded only
14 = top right, bottom left and bottom right corners rounded only
15 = all corners rounded
Пример: если вы хотите установить радиус угла для верхнего левого и верхнего правого углов UIView, вы должны использовать эти атрибуты:
Re ваши три варианта:
С помощью
CALayer
существующие свойства: это простое (и, вероятно, наиболее эффективное) решение для простой маскировки углов. Это тоже анимация. В iOS 11 вы можете выбрать замаскированные углы.Re обычай
CAShapeLayer
Маски: Это хороший подход, если маскировка углов - это не просто округление углов, а произвольный путь. Вы должны быть осторожны, чтобы обновить эту маску, еслиframe
изменения (например, вlayoutSubviews
зрения или вviewDidLayoutSubviews
контроллера). Анимация требует больше работы.Re обычай
draw(_:)
: Это больше работы, чем стоит, и вы, вероятно, не наслаждаетесь оптимизациями, которые команда Apple, возможно, сделала за кулисами (например, что, если последующиеdraw
звонки тянут только часть полногоbounds
; ваш код перерисовывает все это независимо).
Я бы предложил вариант 1 для простых случаев и вариант 2, если вам нужно больше контроля, чем может предложить вариант 1. Но не существует "лучшего" подхода: это зависит от того, что вам нужно и сколько работы вы готовы пройти.
Я провел пару тестов с 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 *cartCornersRound = [CAShapeLayer layer];
[cartCornersRound setPath: [UIBezierPath bezierPathWithRoundedRect: viewTest.bounds byRoundingCorners: UIRectCornerTopLeft | UIRectCornerTopRight cornerRadii: (CGSize){10.0, 10.}].CGPath];
[viewTest.layer setMask: cartCornersRound];
}
- Этот код исправляет проблему с autoResizingMask, который не работает, когда используется старый способ скругления углов.
- Исправлена ошибка с UIScrollView с закругленными углами и setContentSize major для высоты объекта.
Быстрая версия это что-то вроде этого
let view = UIView()
view.clipsToBounds = true
view.layer.cornerRadius = 8
view.layer.maskedCorners = [.layerMaxXMaxYCorner, .layerMinXMaxYCorner]
Я думаю, что это наиболее полное резюме из всех: http://texturegroup.org/docs/corner-rounding.html
Моя эвристика заключается в том, что если представление не нуждается в высокой производительности (например, оно не находится внутри ячейки табличного представления), самый простой вариант - использование CALayer. cornerRadius
, Если вам нужен более продвинутый угловой радиус или высокая производительность, то лучше изучить другие варианты.
Я выбрал первый, это более чистый способ, и вы можете сделать это в IDE без кода. Откройте инспектор атрибутов, затем щелкните инспектор удостоверений и добавьте в "Атрибуты времени выполнения, определенные пользователем" эти 2 свойства:
contView.layer.cornerRadius = 25
contView.layer.maskedCorners = [.layerMaxXMinYCorner,.layerMinXMinYCorner]
contView.layer.masksToBounds = true
это результат только верхний левый и верхний правый углы