UITableView'da performans artışı olmadan Dairesel UIImageView?


82

Bir var UIImageViewbenim her biri üzerinde UITableViewekran bir uzak görüntü (kullanarak o, hücreler SDWebImage). QuartzCoreResim görünümüne bazı katman stillerini uyguladım, örneğin:

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

Şimdi soluk gri kenarlıklı 50x50'lik bir karem var, ancak kare yerine dairesel yapmak istiyorum. Uygulama Hemoglobe, tablo görünümlerinde dairesel görüntüler kullanıyor ve elde etmek istediğim etki bu. Ancak, cornerRadiuskaydırma FPS'mi düşürdüğü için kullanmak istemiyorum .

İşte Hemoglobedairesel gösteriliyor UIImageViews:

görüntü açıklamasını buraya girin

Bu etkiyi almanın bir yolu var mı? Teşekkürler.


1
köşe değilRadius performansı etkiliyor, masksToBounds / clipsToBounds sorun
Calin Chitu

Yanıtlar:


141

Basitçe cornerRadiusgenişliğin veya yüksekliğin yarısına ayarlayın (nesnenizin görünümünün kare olduğunu varsayarak).

Örneğin, nesnenizin görünümünün hem genişliği hem de yüksekliği 50 ise:

itemImageView.layer.cornerRadius = 25;

Güncelleme - Atulkhatri kullanıcısının belirttiği gibi, şunları eklemezseniz çalışmaz:

itemImageView.layer.masksToBounds = YES;

30
Bu neden en iyi cevap olabilir? Ben öyle düşünmüyorum. CornerRadius'un kullanılması özellikle iPhone4 cihazlarında kaydırma görünümünde kötü bir performansa neden olur.
Danny Xu

11
'CornerRadius'u genişliğin veya yüksekliğin yarısına ayarlayın' noktasını beğendim, ancak 'itemImageView.layer.masksToBounds = YES;' eklemeyi unutmayın. yoksa işe yaramaz.
atulkhatri

Bu arada, Danny Xu'nun yorumladığı gibi, tablo görünümü kaydırma performansını düşürecektir. Bu nedenle, tablo görünümü hücrelerinde kaçınılmalıdır.
atulkhatri

4
bu, tablo görünümü kaydırma performansı sorununuzu çözmelidir. self.imageView.layer.shouldRasterize = YES; self.imageView.layer.rasterizationScale = [UIScreen mainScreen] .scale;
hishboy

Swift3 için: itemImageView.layer.masksToBounds = true;
Loïs Talagrand


14

Bu kodu kullanın .. Bu yardımcı olacaktır ..

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

Benim için iyi çalışıyor. :)


Bu kodu kullanarak gerçekten çok basit !! teşekkürler @Shivam
Anilkumar iOS - ReactNative

10

İşte, IBDesignable ve IBInspectable'ı UIImageView alt sınıfına kullanarak swift'te daha güncel bir yöntem.

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

Benim için çalışmasını sağlamak için aşağıdaki kodu eklemem gerekiyordu (bir tablo görüntüleme hücresi içinde): geçersiz kıl func layoutSubviews () {makeRound ()}
herbert

1
@Herbert için +1. Sınıf içindeki düzenleri geçersiz kıldığım zaman tamamen işe yaradı, kodu güncellemelisiniz
Abdoelrhman

Teşekkür ederim!! Sonunda bunu (alt sınıf, ancak Objective-C'de) YUVARLAK KALMAYACAK bazı dairesel UIImageViews işlemek için yaptım.
John Stewart

7

Evet, vermek mümkündür layer.cornerRadius (eklenti ihtiyacını #import <QuartzCore/QuartzCore.h>)
herhangi bir kontrol dairesel oluşturmak için değil, senin durumunda yerine sette layerarasında UIImageViewdairesel olarak Kişisel Resim Oluşturma ve üzerinde eklemek için en iyi yol olduğunu UIImageViewhangi sahip backGroundColorolduğunu ClearColor.

Ayrıca bu İki Kod kaynağına bakın.

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

ve

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

Bu, sizin durumunuzda yardımcı olabilir:


4
Son olarak, buradaki performansı önemseyen tek kişinin @iPatel olduğunu düşünüyorum. Kaydırma sırasında yüksek performans istiyorsanız, cornerRadius'a dikkat edin.
Danny Xu

Biraz kafam karıştı ... Neden çevre görünümü proje bağlantısını gönderdin? Bunun ne soruyla ne de verdiğin yanıtla ilgisi yok.
user717452

@iPatel - güncelleme: ikinci bağlantı yazar tarafından kullanımdan kaldırıldı ve artık indirilemez.
trdavidson

3

UIImageView'ın yüksekliğini ve genişliğini aynı olacak şekilde ayarlayın, örneğin: Height=60& Width = 60, sonra cornerRadiustam olarak yarısı olmalıdır. 30'u benim durumumda tuttum, benim için çalıştı.

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

2

Bazı otomatik düzen ve farklı hücre yükseklikleri kullanıyorsanız, şu şekilde yapsanız iyi olur:

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

1

Round Image View sınıfı kullanıyorum… Yani onu UIImageView yerine kullanıyorum ve ayarlayacak hiçbir şeyim yok…

Bu sınıf ayrıca dairenin etrafına isteğe bağlı bir sınır çizer. Genellikle yuvarlak resimlerin etrafında bir sınır vardır.

Bir UIImageView alt sınıfı değildir çünkü UIImageView kendi oluşturma mekanizmasına sahiptir ve drawRect yöntemini çağırmaz ..

Arayüz :

#import <UIKit/UIKit.h>

@interface MFRoundImageView : UIView

@property(nonatomic,strong) UIImage* image;

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

@end

Uygulama:

#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

SwiftKullanmada kullanılabilir çözüm extension:

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

Kullanım:

self.venueImageView.circleMe()

Uzantıyı uygulamak daha iyi olmaz UIImageViewmı? Bu kod çalışır, ancak uzantıyı herhangi bir UIViewnesne için jenerik yapar .
swiftcode

UIImageViewzaten dan uzanıyor UIView. Bazı durumlarda bazılarını daire içine almanız gerekebilir UIViews, bu nedenle bu yöntem herkes için işe yarayacaktır.
Hossam Ghareeb


0

Görüntüleri düz bir arka plan rengi üzerinde gösteriyorsanız, ortada şeffaf bir daire bulunan bir bindirme görüntüsü kullanmak kolay bir çözüm olabilir.

Bu şekilde, kare görüntüleri kullanmaya devam edebilir ve dairesel efekti elde etmek için üstlerine daire resmi ekleyebilirsiniz.

Görüntülerinizi işlemeniz veya karmaşık bir arka plan renginde göstermeniz gerekmiyorsa, bu, performans açısından bir darbe olmadan basit bir çözüm olabilir.


Hayır yok. Bu sadece basit yükleme, otomatik olarak önbelleğe alma (kare küçük resim) ve gösterme.
swiftcode

Gerçekten işe yarıyor. Daha önce bu zor yolu kullandım. Ancak şu anda yeni sürüm uygulamam için uygun değil.
Danny Xu

0

Hızla , viewDidLoadyönteminizin içinde , userImagepriz ile:

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

Swift'de bu Uzantıyı CircularImageView veya RoundedImageView için kullanın:

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
    }

}

Kullanım:

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

0

Dairesel görüntü görünümü için aşağıdaki kodu kullanın.

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

UIView'unuzun viewDidLayoutSubviews yönteminde cornerRadius'u değiştirmeyi unutmayın.

Misal:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    self.imageView.layer.cornerRadius = self.imageView.frame.size.width / 2;
    self.imageView.clipsToBounds = true
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.