Agregue esquinas redondeadas a todos los UIImageViews

78

Me gustaría agregar algunas esquinas redondeadas a todos los UIImageViews en mi proyecto. Ya tengo el código funcionando, pero tengo que aplicarlo a cada imagen; ¿Debo subclase UIImageView para agregar esto? Si es así, ¿alguien puede darme algunos consejos sobre cómo hacer esto?

Aqui esta el codigo

- (void)viewDidLoad {
    [super viewDidLoad];
    NSString *mainpath = [[NSBundle mainBundle] bundlePath];
    welcomeImageView.image = [UIImage imageWithContentsOfFile:[mainpath stringByAppendingString:@"/test.png"]];
    welcomeImageView.layer.cornerRadius = 9.0;
    welcomeImageView.layer.masksToBounds = YES;
    welcomeImageView.layer.borderColor = [UIColor blackColor].CGColor;
    welcomeImageView.layer.borderWidth = 3.0;
    CGRect frame = welcomeImageView.frame;
    frame.size.width = 100;
    frame.size.height = 100;
    welcomeImageView.frame = frame;
}
Jack
fuente
Hola Jack, gracias por esto, es exactamente lo que quería hacer. Cuando trato de usar esto, aparece un error 'accediendo al componente desconocido' cornerRadius 'de una propiedad', y lo mismo para masksToBounds, etc. Curiosamente, la función de sentido de código en xcode completa estas propiedades para mí, pero el compilador no compilarlos. ¿El código anterior funciona para usted en iOS4.0?
Ben Clayton
20
Debes #importar <QuartzCore / QuartzCore.h>
vodkhang

Respuestas:

25

Puede usar una categoría para UIImage, que es una forma alternativa de subclasificar una clase y, a veces, más fácil para solo pequeños cambios.

por ejemplo, agregue un método que devuelva un UIImage con el conjunto de atributos de esquina redondeada.

+(UIImage *)imageWithContentsOfFile:(NSString *)file cornerRadius:(NSInteger)... 

Puede encontrar más información sobre las categorías de Objective-c http://macdevelopertips.com/objective-c/objective-c-categories.html

Martinj
fuente
Excelente. Muchas gracias, implementaré una categoría UIImage; el tutorial en macdevelopertips.com es muy útil.
Jack
4
Iba a describir cómo crear una subclase, pero me gusta mucho más este enfoque.
Kendall Helmstetter Gelner
Estoy confundido. Entonces, el 100% de todos los UIImages tendrán esto. ¿Por qué no subclase UIImage, algo como UIFramedImage?
Rob
1
aquí está el enlace para el método anterior igframework-iphone-static-library-project.googlecode.com/…
Bobj-C
3
@Rob en realidad, al usar este enfoque, el 0% de UIImages tendrá esquinas redondeadas, hasta que las cambie para llamar al nuevo método. Esta solución no anula los métodos existentes (lo que no debería hacer). Esta puede ser una solución más limpia que la subclase porque no requiere una subclase completa, lo que puede ser excesivo ya que no está agregando ningún miembro o nueva funcionalidad a UIImage, todo lo que desea es un UIImage esquinas redondeadas sin duplicación de código.
Jarsen
114

Compruebe esto: esquinas redondeadas en UIImage

La modificación de la capa parece ser la mejor forma.

UIImageView * roundedView = [[UIImageView alloc] initWithImage: [UIImage imageNamed:@"wood.jpg"]];
// Get the Layer of any view
CALayer * l = [roundedView layer];
[l setMasksToBounds:YES];
[l setCornerRadius:10.0];
NP Competir
fuente
1
Gracias. Esto es esencialmente lo que ya hice, sin embargo, usé la notación de puntos para cambiar las propiedades. Solo me preguntaba si era fácil agregar esto a una subclase para que si quisiera cambiar el radio no tuviera que cambiar cada instancia de esto.
Jack
-1 Esto no intenta responder la pregunta, que trata de aplicar fácilmente el mismo código a cada UIImageViewinstancia.
Stuart
16

En lugar de subclasificar, puede lograr una funcionalidad más poderosa a través de categorías simples en UIImageView y CALayer.

Cree una categoría en UIImageView como esta:

- (void)maskRoundCorners:(UIRectCorner)corners radius:(CGFloat)radius {
    // To round all corners, we can just set the radius on the layer
    if ( corners == UIRectCornerAllCorners ) {
        self.layer.cornerRadius = radius;
        self.layer.masksToBounds = YES;
    } else {
        // If we want to choose which corners we want to mask then
        // it is necessary to create a mask layer.
        self.layer.mask = [CALayer maskLayerWithCorners:corners radii:CGSizeMake(radius, radius) frame:self.bounds];
    }
}

Esto llama a un método de categoría en CALayer:

+ (id)maskLayerWithCorners:(UIRectCorner)corners radii:(CGSize)radii frame:(CGRect)frame {

    // Create a CAShapeLayer
    CAShapeLayer *mask = [CAShapeLayer layer];

    // Set the frame
    mask.frame = frame;

    // Set the CGPath from a UIBezierPath
    mask.path = [UIBezierPath bezierPathWithRoundedRect:mask.bounds byRoundingCorners:corners cornerRadii:radii].CGPath;

    // Set the fill color
    mask.fillColor = [UIColor whiteColor].CGColor;

    return mask;
}

Entonces, esto le permite redondear cualquier combinación (ver UIRectCorner) de esquinas, lo cual es especialmente útil si desea colocar una imagen en un estilo de grupo UITableView. Sin embargo, hay una advertencia al hacer esto. Debido a que no hemos subclasificado UIImageView, no podemos inyectar ningún código layoutSubviews, lo que significa que la capa de máscara puede no ser correcta. De hecho, al configurar celdas, los límites de la vista de imagen ni siquiera se establecerán cuando llame al método de categoría. Por lo tanto, debe asegurarse de que los límites de la vista de imagen estén establecidos antes de agregar esquinas redondeadas (excepto si se usa UIRectCornersAllCorners).

Aquí hay un código que hace esto:

        // Perform corner rounding
        UIRectCorner corners = !UIRectCornerAllCorners;
        if (indexPath.row == 0) 
            corners = UIRectCornerTopLeft;
        if (indexPath.row == numberOfRowsInTheTable)  
            corners |= UIRectCornerBottomLeft;

        if (corners > 0) {
            cell.imageView.bounds = CGRectMake(0.f, 0.f, [self.tableView rowHeight], [self.tableView rowHeight]);
            [cell.imageView maskRoundCorners:corners radius:10.f];
        } else {
            [cell.imageView removeRoundCornersMask];
        }

Tengo otra categoría que elimina las esquinas redondeadas; todo lo que hace es eliminar las máscaras y establecer el valor cornerRadiusen 0.

Daniel Thorpe
fuente
1
Gran solucion Pero me pregunto si no sería mejor crear una clase a la que todas las vistas puedan acceder como UILabel, UIButton, UIView, etc. - ¿Es un método universal?
Borut Tomazin
1
No importa. Acabo de crear la categoría UIView que maneja todo tipo de vistas. ¡Gracias!
Borut Tomazin
1
@BorutTomazin gran pensamiento: estaba pensando en YAGNI, pero mover la categoría UIImageView a UIView sería una gran función de utilidad.
Daniel Thorpe
1
Exactamente lo que hice. Ahora se puede usar en todas las vistas que su padre es UIView ...
Borut Tomazin
5

Sí, debe subclase UIImageView y usar su subclase personalizada en todo su proyecto.

Ben Gottlieb
fuente
1
Gracias, pensé que sería la mejor manera. ¿Conoce algún buen tutorial sobre el uso de subclases? ¿Puedo usar este método con el constructor de interfaces o debo reescribir mi interfaz en código?
Jack
2
En realidad, la respuesta de Martinj anterior es probablemente más fácil, lo que le evita tener que usar una subclase personalizada en todas partes, en Interface Builder, etc.
Jakob Borg
4

Puede crear una subclase de UIImageView y luego, si implementa su método setNeedsDisplay , las esquinas redondeadas funcionarán en las subclases. (no olvide importar QuartzCore)

-(void)setNeedsDisplay {
    self.layer.cornerRadius = 5;
    self.layer.masksToBounds = YES;
    [self.layer setBorderColor:[[UIColor whiteColor] CGColor]];
    [self.layer setBorderWidth: 2.0];
}
Alexey Linkov
fuente
3
No debe hacer esto, setNeedsDisplay esencialmente programa el repintado, y ese es su propósito. Debe configurar su capa en el método init.
pronebird
3

Prueba esto,

coverImage.image = [UIImage imageWithContentsOfFile:@"coverImage.png"]; 
coverImage.layer.masksToBounds = YES;
coverImage.layer.cornerRadius = 10.0;
coverImage.layer.borderWidth = 1.0;
coverImage.layer.borderColor = [[UIColor brown] CGColor];

esto puede ayudarte.

Nithinbemitk
fuente
-1 Esto no intenta responder la pregunta. La pregunta no es sobre cómo producir un redondeo UIImageView(esto se hace con éxito en el fragmento de código de la pregunta), sino sobre cómo reutilizar ese código de manera efectiva.
Stuart