cómo configurar cornerRadius para solo la esquina superior izquierda y la esquina superior derecha de una UIView?

¿Hay alguna manera de configurar cornerRadius para solo la cornerRadius superior izquierda y la esquina superior derecha de UIView ?

EDITAR:

Intenté lo siguiente, pero terminó sin ver la vista nunca más. ¿Hay algún problema con el código a continuación?

 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; 

Preste atención al hecho de que si tiene restricciones de diseño asociadas, debe actualizar esto de la siguiente manera:

  override public func layoutSubviews() { super.layoutSubviews() roundCorners(corners: [.bottomLeft, .bottomRight], radius: 3.0) } 

Si no haces eso, no aparecerá.

No estoy seguro de por qué su solución no funcionó, pero el siguiente código me funciona. Crea una máscara bezier y aplícala a tu vista. En mi código a continuación, estaba redondeando las esquinas inferiores de _backgroundView con un radio de 3 píxeles. self es una UITableViewCell personalizada:

 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; 

Versión Swift con algunas mejoras:

 let path = UIBezierPath(roundedRect:viewToRound.bounds, byRoundingCorners:[.TopRight, .BottomLeft], cornerRadii: CGSizeMake(20, 20)) let maskLayer = CAShapeLayer() maskLayer.path = path.CGPath viewToRound.layer.mask = maskLayer 

Versión de 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 extensión aquí

Aquí hay una versión Swift de @JohnnyRockex respuesta

 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) 

Nota

Si está utilizando Diseño automático , deberá UIView una subclase de su UIView y llamar a roundCorners en las vistas de layoutSubviews la vista para layoutSubviews un efecto óptimo.

 class View: UIView { override func layoutSubviews() { super.layoutSubviews() self.roundCorners([.topLeft, .bottomLeft], radius: 10) } } 

Ejemplo de código Swift aquí: https://stackoverflow.com/a/35621736/308315


No directamente. Tendras que:

  1. Crea una CAShapeLayer
  2. Establezca su path para ser un CGPathRef basado en view.bounds pero con solo dos esquinas redondeadas (probablemente usando +[UIBezierPath bezierPathWithRoundedRect:byRoundingCorners:cornerRadii:] )
  3. Establezca view.layer.mask como CAShapeLayer

Aquí hay un método breve implementado así:

 - (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; } 

Y finalmente … ¡hay CACornerMask en iOS11! Con CACornerMask se puede hacer bastante fácil:

 let view = UIView() view.clipsToBounds = true view.layer.cornerRadius = 10 view.layer.maskedCorners = [.layerMaxXMinYCorner, .layerMinXMinYCorner] // Top right corner, Top left corner respectively 

Prueba este código,

 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; 

Emma: .TopRight y .BottomRight no funcionan para ti porque la llamada a view.roundCorners se hace ANTES de calcular los view bounds final. Tenga en cuenta que Bezier Path deriva de los límites de la vista en el momento en que se llama. Por ejemplo, si el diseño automático reducirá la vista, las esquinas redondeadas en el lado derecho podrían estar fuera de la vista. Intenta llamarlo en viewDidLayoutSubviews , donde el límite de la vista es final.

iOS 11, Swift 4
Y puedes probar este código:

 if #available(iOS 11.0, *) { element.clipsToBounds = true element.layer.cornerRadius = CORNER_RADIUS element.layer.maskedCorners = [.layerMaxXMaxYCorner] } else { // Fallback on earlier versions } 

Y puede usar esto en la celda de vista de tabla.

Una forma de hacerlo mediante progtwigción sería crear una UIView en la parte superior de UIView que tenga las esquinas redondeadas. O podrías esconder la parte superior debajo de algo.

  // 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; 

Todas las respuestas ya dadas son realmente buenas y válidas (especialmente la idea de Yunus de usar la propiedad de la mask ).

Sin embargo, necesitaba algo un poco más complejo porque mi capa a menudo podía cambiar de tamaño, lo que significaba que necesitaba llamar a esa lógica de enmascaramiento cada vez y esto era un poco molesto.

Utilicé extensions rápidas y propiedades calculadas para construir una propiedad cornerRadii real que se encarga de actualizar automáticamente la máscara cuando se distribuye la capa.

Esto se logró usando la gran biblioteca de Aspectos de Peter Steinberg para el swizzling.

El código completo está aquí:

 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 _ { } } } } 

Escribí una simple publicación en el blog explicando esto.

Para iOS 11 en adelante, este código es suficiente

 //In viewDidLoad if #available(iOS 11.0, *){ detailsSubView.clipsToBounds = false detailsSubView.layer.cornerRadius = 10 detailsSubView.layer.maskedCorners = [.layerMaxXMaxYCorner, .layerMinXMaxYCorner] } else { //For lower versions } 

Pero para versiones inferiores

 let rectShape = CAShapeLayer() rectShape.bounds = detailsSubView.frame rectShape.position = detailsSubView.center rectShape.path = UIBezierPath(roundedRect: detailsSubView.bounds, byRoundingCorners: [.bottomLeft , .bottomRight], cornerRadii: CGSize(width: 20, height: 20)).cgPath detailsSubView.layer.mask = rectShape 

Si está utilizando AutoResizing en el guión gráfico, escriba esto en viewDidLayoutSubviews

 override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() if #available(iOS 11.0, *){ detailsSubView.clipsToBounds = false detailsSubView.layer.cornerRadius = 10 detailsSubView.layer.maskedCorners = [.layerMaxXMaxYCorner, .layerMinXMaxYCorner] }else{ let rectShape = CAShapeLayer() rectShape.bounds = detailsSubView.frame rectShape.position = detailsSubView.center rectShape.path = UIBezierPath(roundedRect: detailsSubView.bounds, byRoundingCorners: [.bottomLeft , .bottomRight], cornerRadii: CGSize(width: 20, height: 20)).cgPath detailsSubView.layer.mask = rectShape } } 

La manera más fácil sería hacer una máscara con una capa de esquina redondeada.

 CALayer *maskLayer = [CALayer layer]; maskLayer.frame = CGRectMake(0,0,maskWidth ,maskHeight); maskLayer.contents = (__bridge id)[[UIImage imageNamed:@"maskImageWithRoundedCorners.png"] CGImage]; aUIView.layer.mask = maskLayer; 

Y no te olvides de:

 #import  

Así es como puedes establecer un radio de esquina para cada esquina de un botón con Xamarin en 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 } } } 

Una hermosa extensión para reutilizar la solución de Yunus Nedim Mehel

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 } } 

Uso

 let view = UIView() view.roundCornersWithLayerMask(10,[.TopLeft,.TopRight])