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.


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;

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


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í. :)


¡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()
    }
}

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:


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;

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

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

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

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


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.


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;

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

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
}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.