ios cocoa-touch uiview cornerradius

ios - ¿Cómo configurar cornerRadius solo para la esquina superior izquierda y superior derecha de una vista UIV?



cocoa-touch uiview (18)

Aquí está 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 Auto Layout , deberá subclasificar su UIView y llamar a roundCorners en el roundCorners de la vista para un efecto óptimo.

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

¿Hay una manera de establecer cornerRadius solo para la cornerRadius superior izquierda y superior derecha de una vista de UIView ?

Intenté lo siguiente, pero terminó por no ver más la vista.

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;


Aquí hay un método corto 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; }


Así es como puede establecer un radio de esquina para cada esquina de un botón con Xamarin en C # :

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 }



Emma: .TopRight y .BottomRight no están funcionando para usted tal vez porque la llamada a view.roundCorners se realiza ANTES de que se calculen los view bounds final. Tenga en cuenta que la 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 limitará la vista, las esquinas redondeadas en el lado derecho podrían estar fuera de la vista. Intente llamarlo en viewDidLayoutSubviews , donde el límite de la vista es definitivo.


En Swift 4.1 y Xcode 9.4.1 en adelante, este código es suficiente

//In viewDidLoad if #available(iOS 11.0, *){ detailsSubView.clipsToBounds = false detailsSubView.layer.cornerRadius = 10 detailsSubView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaXMinYCorner] } 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: [.topLeft , .topRight], cornerRadii: CGSize(width: 20, height: 20)).cgPath detailsSubView.layer.mask = rectShape

Si está utilizando AutoResizing en el guión gráfico, escríbalo en 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 } }


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

#import <QuartzCore/QuartzCore.h>

Y no te olvides de:

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;


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

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

Extensión rápida here


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;


Swift 4 Easy Way en 1 línea

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


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

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

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

Esto se logró utilizando la gran biblioteca de Aspects Peter Steinberg para 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 entrada de blog explicando esto.


Una extensión encantadora 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])


Una forma de hacer esto mediante programación sería crear una vista UIView sobre la parte superior de la vista UIView que tiene las esquinas redondeadas. O podrías ocultar la parte superior debajo de algo.


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


Swift 4

Preste atención al hecho de que si tiene restricciones de diseño adjuntas, debe actualizar esto de la siguiente manera en su subclase UIView:

func layoutSubviews() { super.layoutSubviews() roundCorners(corners: [.topLeft, .topRight], radius: 3.0) }

Si no lo haces, no aparecerá.

Y para redondear esquinas, utilizar la extensión:

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


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


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 puedes usar esto en la celda de vista de tabla.


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