Circular UIImageView w UITableView bez spadku wydajności?

82

Mam UIImageViewna każdej z moich UITableViewkomórek, które wyświetlają zdalny obraz (używając SDWebImage). Zrobiłem kilka QuartzCorestylizacji warstw w widoku obrazu, na przykład:

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

Więc teraz mam kwadrat 50x50 z delikatną szarą obwódką, ale chciałbym, aby był okrągły, a nie kwadratowy. Aplikacja Hemoglobeużywa okrągłych obrazów w widokach tabel i właśnie taki efekt chciałbym osiągnąć. Jednak nie chcę tego używać cornerRadius, ponieważ obniża to mój przewijany FPS.

Oto Hemoglobepokazujący okrągły UIImageViews:

wprowadź opis obrazu tutaj

Czy jest sposób, aby uzyskać taki efekt? Dzięki.

kod SWIFT
źródło
1
not cornerRadius wpływa na wydajność, masksToBounds / clipsToBounds to problem
Calin Chitu

Odpowiedzi:

141

Po prostu ustaw cornerRadiuspołowę szerokości lub wysokości (zakładając, że widok twojego obiektu jest kwadratowy).

Na przykład, jeśli szerokość i wysokość widoku obiektu to 50:

itemImageView.layer.cornerRadius = 25;

Aktualizacja - jak wskazuje użytkownik atulkhatri, nie zadziała, jeśli nie dodasz:

itemImageView.layer.masksToBounds = YES;
tagabek
źródło
30
Dlaczego to może być najlepsza odpowiedź? Cóż, nie sądzę. Korzystanie z cornerRadius powoduje słabą wydajność w widoku przewijania, szczególnie w urządzeniach iPhone4.
Danny Xu
11
Podobał mi się punkt „ustaw cornerRadius na połowę szerokości lub wysokości”, ale po prostu nie zapomnij dodać „itemImageView.layer.masksToBounds = YES;” inaczej to nie zadziała.
atulkhatri
Nawiasem mówiąc, jak skomentował Danny Xu, zmniejszy to wydajność przewijania widoku tabeli, dlatego należy tego unikać w komórkach widoku tabeli.
atulkhatri
4
powinno to rozwiązać problem z wydajnością przewijania widoku tabeli. self.imageView.layer.shouldRasterize = TAK; self.imageView.layer.rasterizationScale = [UIScreen mainScreen] .scale;
hishboy
Dla Swift3: itemImageView.layer.masksToBounds = true;
Loïs Talagrand
38

Aby dodać obramowanie

self.ImageView.layer.borderWidth = 3.0f;

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

Do okrągłego kształtu

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

Skorzystaj z tego łącza

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

tak
źródło
14

Użyj tego kodu .. To będzie pomocne ...

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

U mnie działa dobrze. :)

shivam
źródło
jego naprawdę bardzo proste używanie tego kodu !! dzięki @Shivam
Anilkumar iOS - ReactNative
10

Oto bardziej aktualna metoda wykorzystująca IBDesignable i IBInspectable do podklasy 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
źródło
Musiałem dodać następujący kod, aby działał dla mnie (wewnątrz komórki widoku tabeli): override func layoutSubviews () {makeRound ()}
herbert
1
+ 1 dla @herbert. Całkowicie zadziałało, kiedy nadpisuję layoutSubviews wewnątrz klasy, powinieneś zaktualizować kod
Abdoelrhman
Dziękuję Ci!! W końcu zrobiłem to (podklasa, ale w Objective-C), aby obsłużyć niektóre okrągłe UIImageViews, które po prostu nie STAY ROUND.
John Stewart
7

Tak, to jest możliwe, aby dać layer.cornerRadius (trzeba dodać #import <QuartzCore/QuartzCore.h>)
do tworzenia okrągły żadnej kontroli, ale w Twoim przypadku zamiast zestawu layerz UIImageViewto jest najlepszy sposób, aby stworzyć swój wizerunek jako okrągłe i dodać go na UIImageViewktóre mają backGroundColorto ClearColor.

Odnieś się również do tego Two Source of code.

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

i

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

Może to być pomocne w Twoim przypadku:

iPatel
źródło
4
Wreszcie wydaje mi się, że tylko @iPatel dba o wydajność. Uważaj na cornerRadius, jeśli chcesz uzyskać wysoką wydajność podczas przewijania.
Danny Xu
Jestem trochę zdezorientowany ... dlaczego opublikowałeś link do projektu z widokiem kręgu? To nie ma nic wspólnego z pytaniem ani odpowiedzią, której udzieliłeś.
user717452
@iPatel - aktualizacja: drugi link został wycofany przez autora i nie można go już pobrać.
trdavidson
3

Ustaw wysokość i szerokość UIImageView, aby były takie same, np .: Height=60& Width = 60, wtedy cornerRadiuspowinno być dokładnie połowę. W moim przypadku zostawiłem 30. Zadziałało dla mnie.

 self.imageView.layer.cornerRadius = 30;
 self.imageView.layer.borderWidth = 3;
 self.imageView.layer.borderColor = [UIColor whiteColor].CGColor;
 self.imageView.layer.masksToBounds = YES;
Amritansh Upadhyay
źródło
2

Jeśli używasz jakiegoś autoukładu i różnych wysokości komórek, lepiej zrób to w ten sposób:

   override func layoutSubviews() {
        super.layoutSubviews()
        logo.layer.cornerRadius = logo.frame.size.height / 2;
        logo.clipsToBounds      = true;
    }
Zaporozhchenko Oleksandr
źródło
1

Używam klasy Round Image View… Więc po prostu używam jej zamiast UIImageView i nie mam nic do poprawiania…

Ta klasa rysuje również opcjonalną ramkę wokół koła. Często wokół okrągłych zdjęć znajduje się ramka.

Nie jest to podklasa UIImageView, ponieważ UIImageView ma własny mechanizm renderowania i nie wywołuje metody drawRect.

Interfejs:

#import <UIKit/UIKit.h>

@interface MFRoundImageView : UIView

@property(nonatomic,strong) UIImage* image;

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

@end

Realizacja :

#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
Łoś
źródło
1

Użyteczne rozwiązanie w Swiftużyciu extension:

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

Stosowanie:

self.venueImageView.circleMe()
Hossam Ghareeb
źródło
Czy nie byłoby lepiej zastosować rozszerzenie UIImageView? Ten kod działa, ale sprawia, że ​​rozszerzenie jest ogólne dla wszystkich UIViewobiektów.
swiftcode
UIImageViewjuż sięga od UIView. W niektórych przypadkach może być konieczne zakreślenie niektórych UIViews, więc ta metoda będzie działać dla wszystkich.
Hossam Ghareeb
0

Tworzenie okrągłego widoku obrazu, co jest dość łatwe dzięki poniższemu linkowi SO, wystarczy mieć niestandardowe komórki dla widoku tabeli zamiast przydzielać wszystko w metodzie cellForRowAtIndexPath.

jak zrobić okrągły przycisk z tłem obrazu w iPhonie?

Powyższy link daje przykład przycisków, po prostu użyj go do widoków obrazów.

Saify
źródło
0

Jeśli wyświetlasz obrazy na jednolitym kolorze tła, prostym rozwiązaniem może być użycie obrazu nakładki z przezroczystym okręgiem pośrodku.

W ten sposób nadal możesz używać kwadratowych obrazów i dodawać nad nimi okrągły obraz, aby uzyskać okrągły efekt.

Jeśli nie musisz manipulować obrazami ani wyświetlać ich na złożonym kolorze tła, może to być proste rozwiązanie bez spadku wydajności.

Eyal
źródło
Nie, ja nie. To tylko proste ładowanie, automatyczne buforowanie (kwadratowa miniatura) i wyświetlanie.
swiftcode
To naprawdę wyszło. Używałem wcześniej tego trudnego sposobu. Ale teraz nie jest odpowiedni dla mojej nowej wersji aplikacji.
Danny Xu
0

Szybko , w Twojej viewDidLoadmetodzie, z userImagegniazdem:

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
źródło
0

W języku Swift użyj tego rozszerzenia dla CircularImageView lub 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
    }

}

Stosowanie:

self.ImageView.circular()
self.ImageView.roundedCorner()
Aqib Mumtaz
źródło
0

W przypadku okrągłego widoku obrazu użyj poniższego kodu.

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

Nie zapomnij zmienić cornerRadius w metodzie viewDidLayoutSubviews twojego UIView.

Przykład:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    self.imageView.layer.cornerRadius = self.imageView.frame.size.width / 2;
    self.imageView.clipsToBounds = true
}
bharathi kumar
źródło