Как установить cornerRadius только для верхнего левого и верхнего правого угла UIView?
есть ли способ установить cornerRadius
только для верхнего левого и верхнего правого угла a UIView
?
я попробовал следующий, но он в конечном итоге не видя вид.
UIView *view = [[UIView alloc] initWithFrame:frame];
CALayer *layer = [CALayer layer];
UIBezierPath *shadowPath = [UIBezierPath bezierPathWithRoundedRect:frame byRoundingCorners:(UIRectCornerTopLeft|UIRectCornerTopRight) cornerRadii:CGSizeMake(3.0, 3.0)];
layer.shadowPath = shadowPath.CGPath;
view.layer.mask = layer;
18 ответов:
обратите внимание на то, что если у вас есть ограничения макета, прикрепленные к нему, вы должны обновить это следующим образом в своем подклассе UIView:
func layoutSubviews() { super.layoutSubviews() roundCorners(corners: [.topLeft, .topRight], radius: 3.0) }
Если вы этого не сделаете, он не появится.
и для расширения круглого угла:
extension UIView { func roundCorners(corners: UIRectCorner, radius: CGFloat) { let path = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius)) let mask = CAShapeLayer() mask.path = path.cgPath layer.mask = mask } }
Я не уверен, почему ваше решение не работает, но следующий код работает для меня. Создайте маску Безье и примените ее к своему виду. В моем коде ниже я округлял нижние углы
_backgroundView
с радиусом 3 пикселя.self
обычайUITableViewCell
:UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:self.backgroundImageView.bounds byRoundingCorners:(UIRectCornerBottomLeft | UIRectCornerBottomRight) cornerRadii:CGSizeMake(20, 20) ]; CAShapeLayer *maskLayer = [CAShapeLayer layer]; maskLayer.frame = self.bounds; maskLayer.path = maskPath.CGPath; self.backgroundImageView.layer.mask = maskLayer;
Swift версия с некоторыми улучшениями:
let path = UIBezierPath(roundedRect:viewToRound.bounds, byRoundingCorners:[.TopRight, .BottomLeft], cornerRadii: CGSizeMake(20, 20)) let maskLayer = CAShapeLayer() maskLayer.path = path.CGPath viewToRound.layer.mask = maskLayer
версия Swift 3.0:
let path = UIBezierPath(roundedRect:viewToRound.bounds, byRoundingCorners:[.topRight, .bottomLeft], cornerRadii: CGSize(width: 20, height: 20)) let maskLayer = CAShapeLayer() maskLayer.path = path.cgPath viewToRound.layer.mask = maskLayer
расширение Swift здесь
здесь Свифт версия @JohnnyRockex ответ
extension UIView { 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 } }
view.roundCorners([.topLeft, .bottomRight], radius: 10)
Примечание
если вы используете Автоматический Макет, вам нужно будет подкласс ваш
UIView
и звонокroundCorners
на видlayoutSubviews
для достижения оптимального эффекта.class View: UIView { override func layoutSubviews() { super.layoutSubviews() self.roundCorners([.topLeft, .bottomLeft], radius: 10) } }
пример кода Swift здесь:https://stackoverflow.com/a/35621736/308315
не напрямую. Вам придется:
- создать
CAShapeLayer
- установить его
path
бытьCGPathRef
на основеview.bounds
но только с двумя закругленными углами (возможно, с помощью+[UIBezierPath bezierPathWithRoundedRect:byRoundingCorners:cornerRadii:]
)- задание
view.layer.mask
бытьCAShapeLayer
вот короткий метод, реализованный следующим образом:
- (void)viewDidLoad { [super viewDidLoad]; UIButton *openInMaps = [UIButton new]; [openInMaps setFrame:CGRectMake(15, 135, 114, 70)]; openInMaps = (UIButton *)[self roundCornersOnView:openInMaps onTopLeft:NO topRight:NO bottomLeft:YES bottomRight:NO radius:5.0]; } - (UIView *)roundCornersOnView:(UIView *)view onTopLeft:(BOOL)tl topRight:(BOOL)tr bottomLeft:(BOOL)bl bottomRight:(BOOL)br radius:(float)radius { if (tl || tr || bl || br) { UIRectCorner corner = 0; if (tl) {corner = corner | UIRectCornerTopLeft;} if (tr) {corner = corner | UIRectCornerTopRight;} if (bl) {corner = corner | UIRectCornerBottomLeft;} if (br) {corner = corner | UIRectCornerBottomRight;} UIView *roundedView = view; UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:roundedView.bounds byRoundingCorners:corner cornerRadii:CGSizeMake(radius, radius)]; CAShapeLayer *maskLayer = [CAShapeLayer layer]; maskLayer.frame = roundedView.bounds; maskLayer.path = maskPath.CGPath; roundedView.layer.mask = maskLayer; return roundedView; } return view; }
и наконец... есть CACornerMask в iOS11! С
CACornerMask
Это можно сделать довольно легко:let view = UIView() view.clipsToBounds = true view.layer.cornerRadius = 10 view.layer.maskedCorners = [.layerMaxXMinYCorner, .layerMinXMinYCorner] // Top right corner, Top left corner respectively
попробуйте этот код
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:view.bounds byRoundingCorners:( UIRectCornerTopLeft | UIRectCornerTopRight) cornerRadii:CGSizeMake(5.0, 5.0)]; CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init]; maskLayer.frame = self.view.bounds; maskLayer.path = maskPath.CGPath; view.layer.mask = maskLayer;
Эмма:
.TopRight
и.BottomRight
не работают для вас, возможно, потому, что вызовview.roundCorners
делается перед финаломview bounds
рассчитываются. Обратите внимание, чтоBezier Path
выводится из границ представления в момент его вызова. Например, если автоматическая компоновка сузит вид, круглые углы с правой стороны могут быть вне вида. Попробуйте вызвать его вviewDidLayoutSubviews
, где граница представления является окончательной.
iOS 11, Swift 4
И вы можете попробовать этот код:if #available(iOS 11.0, *) { element.clipsToBounds = true element.layer.cornerRadius = CORNER_RADIUS element.layer.maskedCorners = [.layerMaxXMaxYCorner] } else { // Fallback on earlier versions }
и вы можете использовать это в представлении таблицы ячейки.
способ сделать это программно будет создать
UIView
над верхней частьюUIView
Это имеет закругленные углы. Или вы можете спрятать верхнюю часть под чем-то.
// Create the path (with only the top-left corner rounded) UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:view.bounds byRoundingCorners:(UIRectCornerBottomLeft | UIRectCornerBottomRight) cornerRadii:CGSizeMake(7.0, 7.0)]; // Create the shape layer and set its path CAShapeLayer *maskLayer = [CAShapeLayer layer]; maskLayer.frame = cell.stripBlackImnageView.bounds; maskLayer.path = maskPath.CGPath; // Set the newly created shapelayer as the mask for the image view's layer view.layer.mask = maskLayer;
в swift 4.1 и Xcode 9.4.1 и далее этого кода достаточно
//In viewDidLoad if #available(iOS 11.0, *){ detailsSubView.clipsToBounds = false detailsSubView.layer.cornerRadius = 10 detailsSubView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaXMinYCorner] } else { //For lower versions }
но для более низких версий
let rectShape = CAShapeLayer() rectShape.bounds = detailsSubView.frame rectShape.position = detailsSubView.center rectShape.path = UIBezierPath(roundedRect: detailsSubView.bounds, byRoundingCorners: [.topLeft , .topRight], cornerRadii: CGSize(width: 20, height: 20)).cgPath detailsSubView.layer.mask = rectShape
Если вы используете функциями автоматического изменения в раскадровку писать это в viewDidLayoutSubviews
override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() if #available(iOS 11.0, *){ detailsSubView.clipsToBounds = false detailsSubView.layer.cornerRadius = 10 detailsSubView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner] }else{ let rectShape = CAShapeLayer() rectShape.bounds = detailsSubView.frame rectShape.position = detailsSubView.center rectShape.path = UIBezierPath(roundedRect: detailsSubView.bounds, byRoundingCorners: [.topLeft , .topRight], cornerRadii: CGSize(width: 20, height: 20)).cgPath detailsSubView.layer.mask = rectShape } }
все уже приведенные ответы действительно хороши и действительны (особенно Юнус идея использования
mask
свойства).однако мне нужно было что-то более сложное, потому что мой слой часто менял размеры, что означает, что мне нужно было каждый раз называть эту логику маскировки, и это было немного раздражает.
я использовал swift
extensions
и вычисленные свойства для построения реальногоcornerRadii
свойство, которое заботится об автоматическом обновлении маски при укладке слоя из.Это было достигнуто с помощью Питер Стейнберг большой аспекты библиотека для обжига.
полный код здесь:
extension CALayer { // This will hold the keys for the runtime property associations private struct AssociationKey { static var CornerRect:Int8 = 1 // for the UIRectCorner argument static var CornerRadius:Int8 = 2 // for the radius argument } // new computed property on CALayer // You send the corners you want to round (ex. [.TopLeft, .BottomLeft]) // and the radius at which you want the corners to be round var cornerRadii:(corners: UIRectCorner, radius:CGFloat) { get { let number = objc_getAssociatedObject(self, &AssociationKey.CornerRect) as? NSNumber ?? 0 let radius = objc_getAssociatedObject(self, &AssociationKey.CornerRadius) as? NSNumber ?? 0 return (corners: UIRectCorner(rawValue: number.unsignedLongValue), radius: CGFloat(radius.floatValue)) } set (v) { let radius = v.radius let closure:((Void)->Void) = { let path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: v.corners, cornerRadii: CGSize(width: radius, height: radius)) let mask = CAShapeLayer() mask.path = path.CGPath self.mask = mask } let block: @convention(block) Void -> Void = closure let objectBlock = unsafeBitCast(block, AnyObject.self) objc_setAssociatedObject(self, &AssociationKey.CornerRect, NSNumber(unsignedLong: v.corners.rawValue), .OBJC_ASSOCIATION_RETAIN) objc_setAssociatedObject(self, &AssociationKey.CornerRadius, NSNumber(float: Float(v.radius)), .OBJC_ASSOCIATION_RETAIN) do { try aspect_hookSelector("layoutSublayers", withOptions: .PositionAfter, usingBlock: objectBlock) } catch _ { } } } }
Я написал простой блоге объясняя это.
самый простой способ сделать маску с закругленным углом слой.
CALayer *maskLayer = [CALayer layer]; maskLayer.frame = CGRectMake(0,0,maskWidth ,maskHeight); maskLayer.contents = (__bridge id)[[UIImage imageNamed:@"maskImageWithRoundedCorners.png"] CGImage]; aUIView.layer.mask = maskLayer;
и не забывайте:
#import <QuartzCore/QuartzCore.h>
вот как вы можете установить радиус угла для каждого угла кнопки с Xamarin в C#:
var maskPath = UIBezierPath.FromRoundedRect(MyButton.Bounds, UIRectCorner.BottomLeft | UIRectCorner.BottomRight, new CGSize(10.0, 10.0)); var maskLayer = new CAShapeLayer { Frame = MyButton.Bounds, Path = maskPath.CGPath }; MyButton.Layer.Mask = maskLayer;
Swift 4
extension UIView { func roundTop(radius:CGFloat = 5){ self.clipsToBounds = true self.layer.cornerRadius = radius if #available(iOS 11.0, *) { self.layer.maskedCorners = [.layerMaxXMinYCorner, .layerMinXMinYCorner] } else { // Fallback on earlier versions } } func roundBottom(radius:CGFloat = 5){ self.clipsToBounds = true self.layer.cornerRadius = radius if #available(iOS 11.0, *) { self.layer.maskedCorners = [.layerMaxXMaxYCorner, .layerMinXMaxYCorner] } else { // Fallback on earlier versions } } }
прекрасное расширение для повторного использования Yunus Nedim Mehel solution
Swift 2.3
extension UIView { func roundCornersWithLayerMask(cornerRadii: CGFloat, corners: UIRectCorner) { let path = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: cornerRadii, height: cornerRadii)) let maskLayer = CAShapeLayer() maskLayer.path = path.CGPath layer.mask = maskLayer } }
использование
let view = UIView() view.roundCornersWithLayerMask(10,[.TopLeft,.TopRight])
Swift 4 простой способ в 1 строке
Usage //MARK:- Corner Radius of only two side of UIViews self.roundCorners(view: yourview, corners: [.bottomLeft, .topRight], radius: 12.0) Functin //MARK:- Corner Radius of only two side of UIViews func roundCorners(view :UIView, corners: UIRectCorner, radius: CGFloat){ let path = UIBezierPath(roundedRect: view.bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius)) let mask = CAShapeLayer() mask.path = path.cgPath view.layer.mask = mask }