Circular UIImageView en UITableView sin impacto en el rendimiento?

82

Tengo un UIImageViewen cada una de mis UITableViewceldas, que muestra una imagen remota (usando SDWebImage). He hecho algunos QuartzCoreestilos de capa para la vista de la imagen, como tal:

UIImageView *itemImageView = (UIImageView *)[cell viewWithTag:100];
    itemImageView.layer.borderWidth = 1.0f;
    itemImageView.layer.borderColor = [UIColor concreteColor].CGColor;
    itemImageView.layer.masksToBounds = NO;
    itemImageView.clipsToBounds = YES;

Así que ahora tengo un cuadrado de 50x50 con un borde gris tenue, pero me gustaría hacerlo circular en lugar de cuadrado. La aplicación Hemoglobeusa imágenes circulares en las vistas de tabla, y ese es el efecto que me gustaría lograr. Sin embargo, no quiero usarlo cornerRadius, ya que eso degrada mi FPS de desplazamiento.

Aquí se Hemoglobemuestra circular UIImageViews:

ingrese la descripción de la imagen aquí

¿Hay alguna forma de conseguir este efecto? Gracias.

código SWIFT
fuente
1
not cornerRadius está afectando el rendimiento, masksToBounds / clipsToBounds es el problema
Calin Chitu

Respuestas:

141

Simplemente establezca la cornerRadiusmitad del ancho o alto (asumiendo que la vista de su objeto es cuadrada).

Por ejemplo, si el ancho y el alto de la vista de su objeto son 50:

itemImageView.layer.cornerRadius = 25;

Actualización: como señala el usuario atulkhatri, no funcionará si no agrega:

itemImageView.layer.masksToBounds = YES;
Tagabek
fuente
30
¿Por qué podría ser esta la mejor respuesta? Bueno, no lo creo. El uso de cornerRadius provoca un mal rendimiento en la vista de desplazamiento, especialmente en dispositivos iPhone4.
Danny Xu
11
Me gustó el punto 'establecer cornerRadius a la mitad del ancho o alto', pero no olvide agregar 'itemImageView.layer.masksToBounds = YES;' o de lo contrario no funcionará.
atulkhatri
Por cierto, como comentó Danny Xu, disminuirá el rendimiento de desplazamiento de la vista de tabla, por lo que debe evitarse en las celdas de vista de tabla.
atulkhatri
4
esto debería solucionar el problema de rendimiento de desplazamiento de la vista de tabla. self.imageView.layer.shouldRasterize = YES; self.imageView.layer.rasterizationScale = [UIScreen mainScreen] .scale;
hishboy
Para Swift3: itemImageView.layer.masksToBounds = true;
Loïs Talagrand
38

Para Agregar borde

self.ImageView.layer.borderWidth = 3.0f;

self.ImageView.layer.borderColor = [UIColor whiteColor].CGColor;

Para forma circular

self.ImageView.layer.cornerRadius = self.ImageView.frame.size.width / 2;
self.ImageView.clipsToBounds = YES;

Refiera este enlace

http://www.appcoda.com/ios-programming-circular-image-calayer/

yazh
fuente
14

Use este código ... Esto será útil ...

    UIImage* image = ...;
    UIGraphicsBeginImageContextWithOptions(imageView.bounds.size, NO, 1.0);
    // Add a clip before drawing anything, in the shape of an rounded rect
    [[UIBezierPath bezierPathWithRoundedRect:imageView.bounds
                                cornerRadius:50.0] addClip];
    // Draw your image
    [image drawInRect:imageView.bounds];

    // Get the image, here setting the UIImageView image
    imageView.image = UIGraphicsGetImageFromCurrentImageContext();

    // Lets forget about that we were drawing
    UIGraphicsEndImageContext();

Funciona bien para mí. :)

shivam
fuente
¡Es realmente muy simple usar este código! gracias @Shivam
iOS - ReactNative
10

Aquí hay un método más actualizado en Swift usando IBDesignable e IBInspectable para subclase UIImageView

@IBDesignable class RoundableUIImageView: UIImageView {
    private var _round = false
    @IBInspectable var round: Bool {
        set {
            _round = newValue
            makeRound()
        }
        get {
            return self._round
        }
    }
    override internal var frame: CGRect {
        set {
            super.frame = newValue
            makeRound()
        }
        get {
            return super.frame
        }

    }

    private func makeRound() {
        if self.round == true {
            self.clipsToBounds = true
            self.layer.cornerRadius = (self.frame.width + self.frame.height) / 4
        } else {
            self.layer.cornerRadius = 0
        }
    }

    override func layoutSubviews() {
            makeRound()
    }
}
Antzi
fuente
Tuve que agregar el siguiente código para que me funcionara (dentro de una celda de vista de tabla): anular func layoutSubviews () {makeRound ()}
herbert
1
+ 1 para @herbert. Funcionó totalmente para mí cuando anulé las subvistas de diseño dentro de la clase, debe actualizar el código
Abdoelrhman
¡¡Gracias!! Finalmente hice esto (subclase, pero en Objective-C) para manejar algunos UIImageViews circulares que simplemente no PERMANECÍAN REDONDOS.
John Stewart
7

Sí, es posible dar layer.cornerRadius (necesidad de añadir #import <QuartzCore/QuartzCore.h>)
para crear circular ningún control, pero en su caso, en lugar de un conjunto layerde UIImageViewque es la mejor manera de crear su imagen como circular y agregarlo en UIImageView¿Cuáles tienen backGroundColores ClearColor.

Consulte también estas dos fuentes de código.

https://www.cocoacontrols.com/controls/circleview

y

https://www.cocoacontrols.com/controls/mhlazytableimages

Esto podría ser útil en su caso:

iPatel
fuente
4
Finalmente, creo que @iPatel es el único que se preocupa por el desempeño aquí. Tenga cuidado con cornerRadius si desea un alto rendimiento mientras se desplaza.
Danny Xu
Estoy un poco confundido ... ¿por qué publicaste el enlace del proyecto de vista circular? Eso no tiene nada que ver con la pregunta ni con la respuesta que dio.
user717452
@iPatel - actualización: el segundo enlace ha sido desaprobado por el autor y ya no se puede descargar.
trdavidson
3

Establezca la altura y el ancho del UIImageView para que sean iguales, por ejemplo: Height=60& Width = 60, entonces cornerRadiusdebería ser exactamente la mitad. Lo he mantenido 30 en mi caso. Funcionó para mí.

 self.imageView.layer.cornerRadius = 30;
 self.imageView.layer.borderWidth = 3;
 self.imageView.layer.borderColor = [UIColor whiteColor].CGColor;
 self.imageView.layer.masksToBounds = YES;
Amritansh Upadhyay
fuente
2

Si usa un diseño automático y diferentes alturas de celdas, es mejor que lo haga de esta manera:

   override func layoutSubviews() {
        super.layoutSubviews()
        logo.layer.cornerRadius = logo.frame.size.height / 2;
        logo.clipsToBounds      = true;
    }
Zaporozhchenko Oleksandr
fuente
1

Utilizo una clase de vista de imagen redonda ... Así que la uso en lugar de UIImageView y no tengo nada que modificar ...

Esta clase también dibuja un borde opcional alrededor del círculo. A menudo hay un borde alrededor de las imágenes redondeadas.

No es una subclase de UIImageView porque UIImageView tiene su propio mecanismo de representación y no llama al método drawRect.

Interfaz :

#import <UIKit/UIKit.h>

@interface MFRoundImageView : UIView

@property(nonatomic,strong) UIImage* image;

@property(nonatomic,strong) UIColor* strokeColor;
@property(nonatomic,assign) CGFloat strokeWidth;

@end

Implementación:

#import "MFRoundImageView.h"


@implementation MFRoundImageView

-(void)setImage:(UIImage *)image
{
    _image = image;
    [self setNeedsDisplay];
}

-(void)setStrokeColor:(UIColor *)strokeColor
{
    _strokeColor = strokeColor;
    [self setNeedsDisplay];
}

-(void)setStrokeWidth:(CGFloat)strokeWidth
{
    _strokeWidth = strokeWidth;
    [self setNeedsDisplay];
}

- (void)drawRect:(CGRect)rect {
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    CGPathRef path = CGPathCreateWithEllipseInRect(self.bounds, NULL);
    CGContextAddPath(ctx, path);
    CGContextClip(ctx);
    [self.image drawInRect:rect];

    if ( ( _strokeWidth > 0.0f ) && _strokeColor ) {
        CGContextSetLineWidth(ctx, _strokeWidth*2); // Half border is clipped
        [_strokeColor setStroke];
        CGContextAddPath(ctx, path);
        CGContextStrokePath(ctx);
    }
    CGPathRelease(path);
}

@end
Alce
fuente
1

Solución utilizable en el Swiftuso extension:

extension UIView{
  func circleMe(){
      let radius = CGRectGetWidth(self.bounds) / 2
      self.layer.cornerRadius = radius
      self.layer.masksToBounds = true
  }
}

Uso:

self.venueImageView.circleMe()
Hossam Ghareeb
fuente
¿No sería mejor aplicar la extensión UIImageView? Este código funciona, pero hace que la extensión sea genérica para cualquier UIViewobjeto.
código swift
UIImageViewya se está extendiendo desde UIView. En algunos casos, es posible que deba marcar algunos UIViews, por lo que este método funcionará para todos.
Hossam Ghareeb
0

Crear una vista de imagen circular y eso es bastante fácil con el siguiente enlace SO, solo tenga celdas personalizadas para su vista de tabla en lugar de asignar todo en su método cellForRowAtIndexPath.

¿Cómo hacer un botón redondo con fondo de imagen en iPhone?

El enlace anterior le da un ejemplo de botones, solo utilícelo para las vistas de sus imágenes.

Saify
fuente
0

Si muestra las imágenes sobre un color de fondo sólido, una solución fácil podría ser utilizar una imagen superpuesta con un círculo transparente en el medio.

De esta manera, aún puede usar imágenes cuadradas y agregar la imagen del círculo encima de ellas para obtener el efecto circular.

Si no necesita manipular sus imágenes o mostrarlas en un color de fondo complejo, esta puede ser una solución simple sin impacto en el rendimiento.

Eyal
fuente
No, no lo hago. Es simplemente cargar, almacenar en caché automáticamente (la miniatura cuadrada) y mostrar.
swiftcode
Realmente es un ejercicio. Usé esta forma complicada antes. Pero ahora no es adecuado para mi nueva versión de la aplicación.
Danny Xu
0

Rápidamente , dentro de su viewDidLoadmétodo, con la userImagesalida:

self.userImage.layer.borderWidth = 1;
self.userImage.layer.borderColor = UIColor.whiteColor().CGColor;
self.userImage.layer.cornerRadius = self.userImage.frame.size.width / 2;
self.userImage.clipsToBounds = true;
lifeisfoo
fuente
0

En Swift, use esta extensión para CircularImageView o RoundedImageView:

extension UIView {

    func circular(borderWidth: CGFloat = 0, borderColor: UIColor = UIColor.whiteColor()) {
        let radius = CGRectGetWidth(self.bounds) / 2
        self.layer.cornerRadius = radius
        self.layer.masksToBounds = true

        self.layer.borderWidth = borderWidth
        self.layer.borderColor = borderColor.CGColor
    }

    func roundedCorner(borderWidth: CGFloat = 0, borderColor: UIColor = UIColor.whiteColor()) {
        let radius = CGRectGetWidth(self.bounds) / 2
        self.layer.cornerRadius = radius / 5
        self.layer.masksToBounds = true

        self.layer.borderWidth = borderWidth
        self.layer.borderColor = borderColor.CGColor
    }

}

Uso:

self.ImageView.circular()
self.ImageView.roundedCorner()
Aqib Mumtaz
fuente
0

Para una vista de imagen circular, use el siguiente código.

self.imageView.layer.cornerRadius = self.imageView.frame.size.width / 2;
self.imageView.clipsToBounds = true

No olvide cambiar el método cornerRadius en viewDidLayoutSubviews de su UIView.

Ejemplo:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    self.imageView.layer.cornerRadius = self.imageView.frame.size.width / 2;
    self.imageView.clipsToBounds = true
}
bharathi kumar
fuente