Привет, я ищу чистое решение без перезаписи drawRect
или тому подобного, чтобы создать UIView
с закругленными углами в верхней части Вид. Моя главная проблема здесь заключается в том, чтобы создать переменное решение, если представление будет изменено или что-то в этом роде.
Есть ли чистое решение? Apple - это тоже в первом элементе таблицы. это не может быть так сложно сделать.
Округлые углы только на вершине UIView
Ответ 1
Вы можете сделать это, установив mask
на свой уровень просмотра:
CAShapeLayer * maskLayer = [CAShapeLayer layer];
maskLayer.path = [UIBezierPath bezierPathWithRoundedRect: self.bounds byRoundingCorners: UIRectCornerTopLeft | UIRectCornerTopRight cornerRadii: (CGSize){10.0, 10.}].CGPath;
self.layer.mask = maskLayer;
ВАЖНО:. Вы должны сделать это в своем виде layoutSubviews()
, так что представление уже было изменено с раскадровки
В Swift <= 1.2
let maskLayer = CAShapeLayer()
maskLayer.path = UIBezierPath(roundedRect: bounds, byRoundingCorners: .TopLeft | .TopRight, cornerRadii: CGSize(width: 10.0, height: 10.0)).CGPath
layer.mask = maskLayer
Swift 2.x
let maskLayer = CAShapeLayer()
maskLayer.path = UIBezierPath(roundedRect: bounds, byRoundingCorners: UIRectCorner.TopLeft.union(.TopRight), cornerRadii: CGSizeMake(10, 10)).CGPath
layer.mask = maskLayer
Swift 3.x
let maskLayer = CAShapeLayer()
maskLayer.path = UIBezierPath(roundedRect: view.bounds, byRoundingCorners: [.topLeft, .topRight], cornerRadii: CGSize(width: 10, height: 10)).cgPath
layer.mask = maskLayer
Ответ 2
Просто попробовал с Swift 3.0
, Xcode 8.0
:
ПОМНИТЕ, чтобы установить кнопку в viewDidLayoutSubviews()
или layoutSubViews
как
@rob описал здесь.
И когда вы хотите изменить фон с кнопками, вам просто нужно позвонить:
yourButton.backgroundColor = UIColor.someColour
Источник:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
yourButton.layer.masksToBounds = true
yourButton.roundCorners(corners: [.topLeft,.topRight], radius: 5)
}
extension UIButton
{
func roundCorners(corners:UIRectCorner, radius: CGFloat)
{
let maskLayer = CAShapeLayer()
maskLayer.path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius)).cgPath
self.layer.mask = maskLayer
}
}
- Вот результат:
Состояние по умолчанию:
Сохраненное состояние:
Надеюсь на эту помощь!
Ответ 3
Я справился с этим с помощью Эшли.
Прежде всего я подклассифицировал UIView. Создание собственного конструктора для моего класса под названием - (id)initWithContentView:(UIView *)aView forTableView:(UITableView *)table andIndex:(NSIndexPath *)indexPath;
. В этом конструкторе я определяю, какую ячейку таблицы я хочу стилизовать.
Затем я перезаписываю l - (void)layoutSubviews
для создания CAShapeLayer
и применения маски слоя.
.h Код файла
typedef enum {
tableCellMiddle,
tableCellTop,
tableCellBottom,
tableCellSingle
} tableCellPositionValue;
@interface TableCellBackgrounds : UIView
{
tableCellPositionValue position;
}
- (id)initWithContentView:(UIView *)aView forTableView:(UITableView *)table andIndex:(NSIndexPath *)indexPath;
@end
.m Код файла
- (id)initWithContentView:(UIView *)aView forTableView:(UITableView *)table andIndex:(NSIndexPath *)indexPath
{
self = [super initWithFrame:aView.frame];
[self setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
if(self)
{
[self setBackgroundColor:[UIColor colorWithRed:(float)230/255 green:(float)80/255 blue:(float)70/255 alpha:1]];
if(table.style == UITableViewStyleGrouped)
{
int rows = [table numberOfRowsInSection:indexPath.section];
if(indexPath.row == 0 && rows == 1)
{
self.layer.cornerRadius = 11;
position = tableCellSingle;
}
else if (indexPath.row == 0)
position = tableCellTop;
else if (indexPath.row != rows - 1)
position = tableCellMiddle;
else
position = tableCellBottom;
}
}
return self;
}
- (void)layoutSubviews
{
[super layoutSubviews];
if(position == tableCellTop)
{
CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.path = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:UIRectCornerTopLeft|UIRectCornerTopRight cornerRadii:(CGSize){10.0, 10.0}].CGPath;
self.layer.mask = maskLayer;
}
else if (position == tableCellBottom)
{
CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.path = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:UIRectCornerBottomLeft|UIRectCornerBottomRight cornerRadii:(CGSize){10.0, 10.0}].CGPath;
self.layer.mask = maskLayer;
}
}
Ответ 4
Расширение для UIView, которое закругляет выбранные углы (Swift 4):
extension UIView {
/// Round UIView selected corners
///
/// - Parameters:
/// - corners: selected corners to round
/// - radius: round amount
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
}
}
пример:
ratingView.roundCorners([.topLeft, .topRight, .bottomRight], radius: 6)
Ответ 5
Для iOS11 и более поздних версий вы можете использовать свойство слоя представления:
@property CACornerMask maskedCorners
Это определяет, какой из четырех углов получает маскировку при использовании свойства cornerRadius. По умолчанию все четыре угла. (Apple Doc)
Ответ 6
С быстрым 3.0 ниже работало для меня
let maskLayer = CAShapeLayer()
maskLayer.path = UIBezierPath(roundedRect: view.bounds, byRoundingCorners: [.topLeft, .topRight], cornerRadii: CGSize(width: 10, height: 10)).cgPath
(imageView.)layer.mask = maskLayer
Важно: убедитесь, что это "layoutSubviews" не "awakeFromNib" (если вы используете TableViewCell) или аналогичные для UIView, или только верхний левый угол округлен!
Ответ 7
Современный & Простое решение
iOS 11+
Теперь у нас есть свойство maskedCorners
на слое вида & это делает жизнь намного проще.
Просто установите желаемый радиус угла и укажите, какие углы должны быть замаскированы. Самое приятное то, что это хорошо работает с границами - граница слоя будет следовать за краем слоя, независимо от того, закруглен он или нет! Попробуйте следующий код на игровой площадке (не забудьте открыть вид в реальном времени, нажав command+option+return
, чтобы вы могли видеть, как он выглядит)
import UIKit
import PlaygroundSupport
let wrapperView = UIView(frame: CGRect(x: 0, y: 0, width: 400, height: 160))
wrapperView.backgroundColor = .lightGray
let roundedCornerView = UIView(frame: CGRect(x: 50, y: 50, width: 300, height: 60))
roundedCornerView.backgroundColor = .white
wrapperView.addSubview(roundedCornerView)
roundedCornerView.layer.cornerRadius = 10
roundedCornerView.layer.borderColor = UIColor.red.cgColor
roundedCornerView.layer.borderWidth = 1
// this is the key part - try out different corner combinations to achieve what you need
roundedCornerView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
PlaygroundPage.current.liveView = wrapperView
Вот как это выглядит:
Ответ 8
CAShapeLayer * maskLayer = [CAShapeLayer layer];
maskLayer.path = [UIBezierPath bezierPathWithRoundedRect: registerbtn.bounds byRoundingCorners: UIRectCornerBottomLeft | UIRectCornerBottomRight cornerRadii: (CGSize){9.0, 12.0}].CGPath;
registerbtn.layer.mask = maskLayer;
это сделает только один округленный угол
Ответ 9
Простым способом сделать это будет определение пути в нужной форме и заполнение его любым цветом, который вы хотите использовать для фона. Вы можете использовать для этого UIBezierPath
или CGPath
. Например, используя CGPath
, вы можете построить путь, используя такие методы, как CGMoveToPoint()
, CGAddLineToPoint()
и CGAddArc()
. Затем вы заполните его CGContextFillPath()
. Посмотрите Quartz 2D Programming Guide для полного обсуждения.
Другим способом было бы добавить subview с закругленными углами (вы можете установить свойство subview layer cornerRadius), но пусть одна сторона подвью будет обрезана родительским представлением.
Третий способ - добавить фоновое изображение с желаемой формой. Вы можете сделать углы прозрачными и сделать вид фона прозрачным, и вы получите желаемый эффект. Однако это не будет работать для изменения размера.
Где вы застреваете?