Circular UIImageView in UITableView ohne Leistungseinbußen?


82

Ich habe UIImageViewauf jeder meiner UITableViewZellen eine, die ein entferntes Bild anzeigt (mit SDWebImage). Ich habe einige QuartzCoreEbenen für die Bildansicht erstellt:

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

Jetzt habe ich ein 50x50-Quadrat mit einem schwachen grauen Rand, aber ich möchte es kreisförmig anstatt quadratisch machen. Die App Hemoglobeverwendet kreisförmige Bilder in Tabellenansichten, und das ist der Effekt, den ich erzielen möchte. Ich möchte es jedoch nicht verwenden cornerRadius, da dies meine Bildlauf-FPS verschlechtert.

Hier ist ein HemoglobeRundschreiben UIImageViews:

Geben Sie hier die Bildbeschreibung ein

Gibt es eine Möglichkeit, diesen Effekt zu erzielen? Vielen Dank.


1
nicht EckeRadius beeinflusst die Leistung, MaskenToBounds / ClipsToBounds ist das Problem
Calin Chitu

Antworten:


141

Stellen Sie einfach die cornerRadiusHälfte der Breite oder Höhe ein (vorausgesetzt, die Ansicht Ihres Objekts ist quadratisch).

Wenn beispielsweise die Breite und Höhe der Ansicht Ihres Objekts 50 beträgt:

itemImageView.layer.cornerRadius = 25;

Update - Wie Benutzer atulkhatri betont, funktioniert es nicht, wenn Sie nicht hinzufügen:

itemImageView.layer.masksToBounds = YES;

30
Warum könnte dies die beste Antwort sein? Das glaube ich nicht. Die Verwendung von CornerRadius führt zu einer schlechten Leistung in der Bildlaufansicht, insbesondere bei iPhone4-Geräten.
Danny Xu

11
Ich mochte den Punkt 'setze den CornerRadius auf die Hälfte der Breite oder Höhe', aber vergiss nicht, 'itemImageView.layer.masksToBounds = YES;' hinzuzufügen. sonst funktioniert es nicht.
Atulkhatri

Übrigens, wie Danny Xu kommentierte, wird dies die Bildlaufleistung der Tabellenansicht verringern. Daher sollte dies in Tabellenansichtszellen vermieden werden.
Atulkhatri

4
Dies sollte das Problem mit der Bildlaufleistung in der Tabellenansicht beheben. self.imageView.layer.shouldRasterize = YES; self.imageView.layer.rasterizationScale = [UIScreen mainScreen] .scale;
Hishboy

Für Swift3: itemImageView.layer.masksToBounds = true;
ソ リ


14

Verwenden Sie diesen Code .. Dies wird hilfreich sein ..

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

Es funktioniert gut für mich. :) :)


Es ist wirklich sehr einfach mit diesem Code! danke @Shivam
Anilkumar iOS - ReactNative

10

Hier ist eine aktuellere Methode in Swift mit IBDesignable und IBInspectable zur Unterklasse von 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()
    }
}

Ich musste den folgenden Code hinzufügen, damit es für mich funktioniert (innerhalb einer Tabellenansichtszelle): überschreiben func layoutSubviews () {makeRound ()}
herbert

1
+ 1 für @herbert. Es hat total funktioniert für mich, wenn ich layoutSubviews innerhalb der Klasse überschreibe. Sie sollten den Code aktualisieren
Abdoelrhman

Danke dir!! Ich habe dies schließlich getan (Unterklasse, aber in Objective-C), um einige kreisförmige UIImageViews zu verarbeiten, die einfach nicht RUND bleiben würden.
John Stewart

7

Ja, ist es möglich , geben layer.cornerRadius (hinzufügen muß #import <QuartzCore/QuartzCore.h>)
für jeden Steuerkreis zu schaffen , aber in Ihrem Fall statt Satz layervon UIImageViewes der beste Weg ist Ihr Bild als Kreis erstellen und fügen Sie sich auf UIImageViewdem backGroundColorist ClearColor.

Verweisen Sie auch auf diese zwei Codequellen.

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

und

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

Dies kann in Ihrem Fall hilfreich sein:


4
Schließlich denke ich, dass @iPatel der einzige ist, der sich um die Leistung hier kümmert. Seien Sie vorsichtig mit CornerRadius, wenn Sie beim Scrollen eine hohe Leistung erzielen möchten.
Danny Xu

Ich bin ein wenig verwirrt ... warum hast du den Projektlink für die Kreisansicht gepostet? Das hat nichts mit der Frage oder der Antwort zu tun, die Sie gegeben haben.
user717452

@iPatel - Update: Der zweite Link ist vom Autor veraltet und kann nicht mehr heruntergeladen werden.
Trdavidson

3

Stellen Sie die Höhe und Breite des UIImageView gleich ein, z. B.: Height=60& Width = 60, Dann cornerRadiussollte das genau die Hälfte sein. Ich habe es in meinem Fall auf 30 gehalten. Es hat bei mir funktioniert.

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

2

Wenn Sie ein Autolayout und unterschiedliche Zellenhöhen verwenden, tun Sie dies besser folgendermaßen:

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

1

Ich verwende eine Round Image View-Klasse… Also verwende ich sie einfach anstelle von UIImageView und habe nichts zu optimieren…

Diese Klasse zeichnet auch einen optionalen Rahmen um den Kreis. Es gibt oft einen Rand um abgerundete Bilder.

Es ist keine UIImageView-Unterklasse, da UIImageView über einen eigenen Rendering-Mechanismus verfügt und die drawRect-Methode nicht aufruft.

Schnittstelle:

#import <UIKit/UIKit.h>

@interface MFRoundImageView : UIView

@property(nonatomic,strong) UIImage* image;

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

@end

Implementierung :

#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

Verwendbare Lösung bei der SwiftVerwendung von extension:

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

Verwendung:

self.venueImageView.circleMe()

Wäre es nicht besser, die Erweiterung auf anzuwenden UIImageView? Dieser Code funktioniert, macht die Erweiterung jedoch für alle UIViewObjekte generisch .
Swiftcode

UIImageViewerstreckt sich bereits von UIView. In einigen Fällen müssen Sie möglicherweise einige umkreisen UIViews, damit diese Methode für alle funktioniert.
Hossam Ghareeb

0

Erstellen Sie eine kreisförmige Bildansicht, und das ist ganz einfach mit dem folgenden SO-Link. Verwenden Sie einfach benutzerdefinierte Zellen für Ihre Tabellenansicht, anstatt alles in Ihrer cellForRowAtIndexPath-Methode zuzuweisen.

Wie mache ich eine Schaltfläche mit Bildhintergrund in IPhone rund?

Der obige Link gibt Ihnen ein Beispiel für Schaltflächen, die Sie nur für Ihre Bildansichten verwenden.


0

Wenn Sie die Bilder über einer festen Hintergrundfarbe anzeigen, besteht eine einfache Lösung darin, ein Überlagerungsbild mit einem transparenten Kreis in der Mitte zu verwenden.

Auf diese Weise können Sie weiterhin quadratische Bilder verwenden und das Kreisbild darüber hinzufügen, um den Kreiseffekt zu erzielen.

Wenn Sie Ihre Bilder nicht bearbeiten oder auf einer komplexen Hintergrundfarbe anzeigen müssen, kann dies eine einfache Lösung ohne Leistungseinbußen sein.


Nein, ich nicht. Es ist einfach zu laden, automatisch zwischenzuspeichern (das quadratische Miniaturbild) und anzuzeigen.
Swiftcode

Es ist wirklich ein Workout. Ich habe diesen kniffligen Weg schon einmal benutzt. Aber es ist jetzt nicht für meine neue Versions-App geeignet.
Danny Xu

0

Im Handumdrehen innerhalb Ihrer viewDidLoadMethode mit der userImageSteckdose:

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

Verwenden Sie in Swift diese Erweiterung für CircularImageView oder 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
    }

}

Verwendung:

self.ImageView.circular()
self.ImageView.roundedCorner()

0

Verwenden Sie für die kreisförmige Bildansicht den folgenden Code.

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

Vergessen Sie nicht, den CornerRadius in der viewDidLayoutSubviews-Methode Ihres UIView zu ändern.

Beispiel:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    self.imageView.layer.cornerRadius = self.imageView.frame.size.width / 2;
    self.imageView.clipsToBounds = true
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.