objective-c - varias - poligono en r
Esquinas redondeadas solo en la parte superior de una vista (8)
Hola, estoy buscando una solución limpia sin sobrescribir drawRect
o cosas así para crear una UIView
con esquinas redondeadas en la parte superior de la vista . Mi principal problema aquí es crear una solución variable si la vista se redimensiona o algo así. ¿Hay una solución limpia? Apple está haciendo esto también en el primer elemento de la tabla. No puede ser tan difícil hacer esto.
Acabo de probar con Swift 3.0
, Xcode 8.0
:
RECUERDE para configurar su botón en viewDidLayoutSubviews()
o layoutSubViews
como @rob se describe here .
Y cuando quieras cambiar el fondo de tus botones, solo tienes que llamar:
yourButton.backgroundColor = UIColor.someColour
Fuente:
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
}
}
- Aquí está el resultado:
Estado predeterminado:
Estado seleccionado:
¡¡Espero que esto ayude!!
Con Swift 3.0 lo siguiente funcionó para mí
let maskLayer = CAShapeLayer()
maskLayer.path = UIBezierPath(roundedRect: view.bounds, byRoundingCorners: [.topLeft, .topRight], cornerRadii: CGSize(width: 10, height: 10)).cgPath
(imageView.)layer.mask = maskLayer
Importante: asegúrese de que esté en ''layoutSubviews'' no en ''awakeFromNib'' (si está usando TableViewCell) o similares para UIView''s, ¡o solo la esquina superior izquierda está redondeada!
La forma más sencilla de hacerlo sería definir un trazado en la forma que desee y rellenarlo con el color que desee utilizar para el fondo. Puede usar UIBezierPath
o CGPath
para esto. Al usar CGPath
, por ejemplo, puede construir una ruta usando métodos como CGMoveToPoint()
, CGAddLineToPoint()
y CGAddArc()
. Luego lo llenarías con CGContextFillPath()
. Echa un vistazo a la Guía de programación de cuarzo 2D para una discusión completa.
Otra forma sería agregar una subvista con esquinas redondeadas (puede establecer la propiedad cornerRadius de la capa de la subvista), pero deje que un lado de la subvista sea recortado por la vista principal.
Una tercera forma sería agregar una imagen de fondo con la forma deseada. Puede hacer que las esquinas sean transparentes y hacer que el fondo de la vista sea transparente, y obtendrá el efecto deseado. Sin embargo, esto no funcionará tan bien para cambiar el tamaño.
¿Dónde te estás atascando?
Para iOS11 y posteriores puedes usar la propiedad de vista:
@property CACornerMask maskedCorners
Eso define cuál de las cuatro esquinas recibe el enmascaramiento cuando se usa la propiedad cornerRadius . Por defecto a las cuatro esquinas. (Apple doc)
Puedes hacerlo configurando una mask
en la capa de tu vista:
CAShapeLayer * maskLayer = [CAShapeLayer layer];
maskLayer.path = [UIBezierPath bezierPathWithRoundedRect: self.bounds byRoundingCorners: UIRectCornerTopLeft | UIRectCornerTopRight cornerRadii: (CGSize){10.0, 10.}].CGPath;
self.layer.mask = maskLayer;
IMPORTANTE: Debes hacer esto en el método layoutSubviews()
tu vista, para que la vista ya haya sido redimensionada desde el guión gráfico.
En 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
Trabajé esto con la ayuda de Ashley.
En primer lugar, he subclasificado un UIView. Creando un constructor propio para mi clase llamado - (id)initWithContentView:(UIView *)aView forTableView:(UITableView *)table andIndex:(NSIndexPath *)indexPath;
. En este constructor, determino qué tipo de celda de tabla quiero diseñar.
Luego sobrescribo l - (void)layoutSubviews
para crear el CAShapeLayer
y aplicar la máscara de capa.
Código de archivo .h
typedef enum {
tableCellMiddle,
tableCellTop,
tableCellBottom,
tableCellSingle
} tableCellPositionValue;
@interface TableCellBackgrounds : UIView
{
tableCellPositionValue position;
}
- (id)initWithContentView:(UIView *)aView forTableView:(UITableView *)table andIndex:(NSIndexPath *)indexPath;
@end
Código de archivo .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;
}
}
Una extensión para UIView que redondea las esquinas seleccionadas (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
}
}
ejemplo:
ratingView.roundCorners([.topLeft, .topRight, .bottomRight], radius: 6)
CAShapeLayer * maskLayer = [CAShapeLayer layer];
maskLayer.path = [UIBezierPath bezierPathWithRoundedRect: registerbtn.bounds byRoundingCorners: UIRectCornerBottomLeft | UIRectCornerBottomRight cornerRadii: (CGSize){9.0, 12.0}].CGPath;
registerbtn.layer.mask = maskLayer;
Esto hará solo una esquina redondeada.