Utilicé la respuesta en ¿Cómo creo un UILabel acorralado en el iPhone? y el código de ¿Cómo se hace una vista rectángulo redondeada con transparencia en iphone? para hacer este código
Luego me di cuenta de que había respondido la pregunta incorrecta (le di un UILabel redondeado en lugar de UIImage), así que usé este código para cambiarlo:
http://discussions.apple.com/thread.jspa?threadID=1683876
Haga un proyecto de iPhone con la plantilla Ver. En el controlador de vista, agregue esto:
- (void)viewDidLoad
{
CGRect rect = CGRectMake(10, 10, 200, 100);
MyView *myView = [[MyView alloc] initWithFrame:rect];
[self.view addSubview:myView];
[super viewDidLoad];
}
MyView
es solo una UIImageView
subclase:
@interface MyView : UIImageView
{
}
Nunca antes había usado contextos gráficos, pero me las arreglé para crear este código. Falta el código para dos de las esquinas. Si lees el código, puedes ver cómo implementé esto (eliminando algunas de las CGContextAddArc
llamadas y eliminando algunos de los valores de radio en el código. El código para todas las esquinas está ahí, así que úsalo como punto de partida y elimina el partes que crean esquinas que no necesita. Tenga en cuenta que también puede hacer rectángulos con 2 o 3 esquinas redondeadas si lo desea.
El código no es perfecto, pero estoy seguro de que puedes arreglarlo un poco.
static void addRoundedRectToPath(CGContextRef context, CGRect rect, float radius, int roundedCornerPosition)
{
// all corners rounded
// CGContextMoveToPoint(context, rect.origin.x, rect.origin.y + radius);
// CGContextAddLineToPoint(context, rect.origin.x, rect.origin.y + rect.size.height - radius);
// CGContextAddArc(context, rect.origin.x + radius, rect.origin.y + rect.size.height - radius,
// radius, M_PI / 4, M_PI / 2, 1);
// CGContextAddLineToPoint(context, rect.origin.x + rect.size.width - radius,
// rect.origin.y + rect.size.height);
// CGContextAddArc(context, rect.origin.x + rect.size.width - radius,
// rect.origin.y + rect.size.height - radius, radius, M_PI / 2, 0.0f, 1);
// CGContextAddLineToPoint(context, rect.origin.x + rect.size.width, rect.origin.y + radius);
// CGContextAddArc(context, rect.origin.x + rect.size.width - radius, rect.origin.y + radius,
// radius, 0.0f, -M_PI / 2, 1);
// CGContextAddLineToPoint(context, rect.origin.x + radius, rect.origin.y);
// CGContextAddArc(context, rect.origin.x + radius, rect.origin.y + radius, radius,
// -M_PI / 2, M_PI, 1);
// top left
if (roundedCornerPosition == 1) {
CGContextMoveToPoint(context, rect.origin.x, rect.origin.y + radius);
CGContextAddLineToPoint(context, rect.origin.x, rect.origin.y + rect.size.height - radius);
CGContextAddArc(context, rect.origin.x + radius, rect.origin.y + rect.size.height - radius,
radius, M_PI / 4, M_PI / 2, 1);
CGContextAddLineToPoint(context, rect.origin.x + rect.size.width,
rect.origin.y + rect.size.height);
CGContextAddLineToPoint(context, rect.origin.x + rect.size.width, rect.origin.y);
CGContextAddLineToPoint(context, rect.origin.x, rect.origin.y);
}
// bottom left
if (roundedCornerPosition == 2) {
CGContextMoveToPoint(context, rect.origin.x, rect.origin.y);
CGContextAddLineToPoint(context, rect.origin.x, rect.origin.y + rect.size.height);
CGContextAddLineToPoint(context, rect.origin.x + rect.size.width,
rect.origin.y + rect.size.height);
CGContextAddLineToPoint(context, rect.origin.x + rect.size.width, rect.origin.y);
CGContextAddLineToPoint(context, rect.origin.x + radius, rect.origin.y);
CGContextAddArc(context, rect.origin.x + radius, rect.origin.y + radius, radius,
-M_PI / 2, M_PI, 1);
}
// add the other corners here
CGContextClosePath(context);
CGContextRestoreGState(context);
}
-(UIImage *)setImage
{
UIImage *img = [UIImage imageNamed:@"my_image.png"];
int w = img.size.width;
int h = img.size.height;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(NULL, w, h, 8, 4 * w, colorSpace, kCGImageAlphaPremultipliedFirst);
CGContextBeginPath(context);
CGRect rect = CGRectMake(0, 0, w, h);
addRoundedRectToPath(context, rect, 50, 1);
CGContextClosePath(context);
CGContextClip(context);
CGContextDrawImage(context, rect, img.CGImage);
CGImageRef imageMasked = CGBitmapContextCreateImage(context);
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
[img release];
return [UIImage imageWithCGImage:imageMasked];
}
texto alternativo http://nevan.net/skitch/skitched-20100224-092237.png
No olvides que necesitarás tener el framework QuartzCore para que esto funcione.
A partir de iOS 3.2, puede usar la funcionalidad de
UIBezierPath
s para crear un rectángulo redondeado listo para usar (donde solo se redondean las esquinas que especifique). Luego puede usar esto como la ruta de acceso de aCAShapeLayer
, y usar esto como una máscara para la capa de su vista:Y eso es todo: no perder el tiempo definiendo formas manualmente en Core Graphics, sin crear imágenes de enmascaramiento en Photoshop. La capa ni siquiera necesita invalidarse. Aplicar la esquina redondeada o cambiar a una nueva esquina es tan simple como definir una nueva
UIBezierPath
y usarlaCGPath
como la ruta de la capa de máscara. Elcorners
parámetro delbezierPathWithRoundedRect:byRoundingCorners:cornerRadii:
método es una máscara de bits, por lo que se pueden redondear varias esquinas orándolas juntas.EDITAR: Agregar una sombra
Si está buscando agregar una sombra a esto, se requiere un poco más de trabajo.
Como "
imageView.layer.mask = maskLayer
" aplica una máscara, normalmente no se mostrará una sombra fuera de ella. El truco consiste en utilizar una vista transparente y luego agregar dos subcapasCALayer
a la capa de la vista:shadowLayer
yroundedLayer
. Ambos necesitan hacer uso deUIBezierPath
. La imagen se agrega como contenido deroundedLayer
.fuente
He usado este código en muchos lugares de mi código y funciona 100% correctamente. Puede cambiar cualquier cable cambiando una propiedad "byRoundingCorners: UIRectCornerBottomLeft"
fuente
UITableView
subvistas (p. Ej.UITableViewCell
S oUITableViewHeaderFooterView
s), se produce una suavidad incorrecta al desplazarse . Otro enfoque para ese uso es esta solución con un mejor rendimiento (agrega un cornerRadius a todos los rincones). Para 'mostrar' solo las esquinas específicas redondeadas (como las esquinas superior e inferior derecha) agregué una subvista con un valor negativoframe.origin.x
y asigné el cornerRadius a su capa. Si alguien encuentra una mejor solución, estoy interesado.En iOS 11, ahora solo podemos redondear algunas esquinas
fuente
Extensión CALayer con sintaxis Swift 3+
Se puede usar como:
fuente
El ejemplo de Stuarts para redondear esquinas específicas funciona muy bien. Si desea redondear varias esquinas, como arriba a la izquierda y derecha, así es cómo hacerlo
fuente
UITableView
subvistas (p. Ej.UITableViewCell
S oUITableViewHeaderFooterView
s), se produce una suavidad incorrecta al desplazarse . Otro enfoque para ese uso es esta solución con un mejor rendimiento (agrega un cornerRadius a todos los rincones). Para 'mostrar' solo las esquinas específicas redondeadas (como las esquinas superior e inferior derecha) agregué una subvista con un valor negativoframe.origin.x
y asigné el cornerRadius a su capa. Si alguien encuentra una mejor solución, estoy interesado.Gracias por compartir. Aquí me gustaría compartir la solución en swift 2.0 para obtener más información sobre este tema. (para conformar el protocolo de UIRectCorner)
fuente
Hay una respuesta más fácil y rápida que puede funcionar dependiendo de sus necesidades y también funciona con sombras. puede establecer maskToBounds en la supercapa en verdadero y compensar las capas secundarias para que 2 de sus esquinas estén fuera de los límites de la supercapa, cortando efectivamente las esquinas redondeadas en 2 lados.
por supuesto, esto solo funciona cuando desea tener solo 2 esquinas redondeadas en el mismo lado y el contenido de la capa se ve igual cuando corta unos pocos píxeles de un lado. funciona muy bien para tener gráficos de barras redondeados solo en la parte superior.
fuente
Ver esta pregunta relacionada . Tendrás que dibujar tu propio rectángulo
CGPath
con unas esquinas redondeadas, agregarloCGPath
a tuCGContext
y luego recortarlo usandoCGContextClip
.También puede dibujar el rectángulo redondeado con valores alfa en una imagen y luego usar esa imagen para crear una nueva capa que establezca como
mask
propiedad de su capa ( consulte la documentación de Apple ).fuente
Media década tarde, pero creo que la forma actual en que las personas hacen esto no es 100% correcta. Muchas personas han tenido el problema de que usar el método UIBezierPath + CAShapeLayer interfiere con el diseño automático, especialmente cuando está configurado en el Storyboard. No hay respuestas sobre esto, así que decidí agregar la mía.
Hay una manera muy fácil de evitar eso: dibuja las esquinas redondeadas en la
drawRect(rect: CGRect)
función.Por ejemplo, si quisiera las esquinas redondeadas superiores para una UIView, subclase UIView y luego use esa subclase cuando corresponda.
Esta es la mejor manera de conquistar el problema y no requiere tiempo para adaptarse.
fuente
drawRect(_:)
si está haciendo un dibujo personalizado en su vista (por ejemplo, con Core Graphics), de lo contrario, incluso una implementación vacía puede afectar el rendimiento. Crear una nueva capa de máscara cada vez es innecesario también. Todo lo que realmente necesita hacer es actualizar lapath
propiedad de la capa de máscara cuando cambian los límites de la vista, y el lugar para hacerlo está dentro de una anulación dellayoutSubviews()
método.Redondear solo algunas esquinas no funcionará bien con el cambio de tamaño automático o el diseño automático.
Entonces, otra opción es usar regular
cornerRadius
y ocultar las esquinas que no desea debajo de otra vista o fuera de los límites de la supervista asegurándose de que esté configurado para recortar su contenido.fuente
Para agregar a la respuesta y la adición , creé un simple, reutilizable
UIView
en Swift. Dependiendo de su caso de uso, es posible que desee realizar modificaciones (evite crear objetos en cada diseño, etc.), pero quería que fuera lo más simple posible. La extensión le permite aplicar esto a otras vistas (ej.UIImageView
) Más fácilmente si no le gusta la subclase.Así es como lo aplicaría a
UIViewController
:fuente
Para concluir la respuesta de Stuart, puede tener el método de redondeo de la siguiente manera:
Entonces, para aplicar el redondeo de esquina, simplemente debes hacer:
fuente
Sugeriría definir la máscara de una capa. La máscara en sí misma debe ser un
CAShapeLayer
objeto con una ruta dedicada. Puede usar la próxima extensión UIView (Swift 4.2):fuente