UIImageView tròn trong UITableView mà không đạt hiệu suất?


82

Tôi có một UIImageViewtrên mỗi ô của mình UITableView, hiển thị một hình ảnh từ xa (sử dụng SDWebImage). Tôi đã thực hiện một số QuartzCoretạo kiểu lớp cho chế độ xem hình ảnh, chẳng hạn như:

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

Vì vậy, bây giờ tôi có một hình vuông 50x50 với đường viền màu xám mờ, nhưng tôi muốn làm cho nó hình tròn thay vì hình vuông. Ứng dụng Hemoglobesử dụng hình ảnh tròn trong chế độ xem bảng và đó là hiệu ứng mà tôi muốn đạt được. Tuy nhiên, tôi không muốn sử dụng cornerRadius, vì điều đó làm giảm FPS cuộn của tôi.

Đây là Hemoglobevòng tròn hiển thị UIImageViews:

nhập mô tả hình ảnh ở đây

Có cách nào để có được hiệu ứng này? Cảm ơn.


1
không cornerRadius đang tác động đến hiệu quả hoạt động, masksToBounds / clipsToBounds là vấn đề
Calin Chitu

Câu trả lời:


141

Chỉ cần đặt thành cornerRadiusmột nửa chiều rộng hoặc chiều cao (giả sử chế độ xem đối tượng của bạn là hình vuông).

Ví dụ: nếu chiều rộng và chiều cao của chế độ xem đối tượng của bạn đều là 50:

itemImageView.layer.cornerRadius = 25;

Cập nhật - Như người dùng atulkhatri đã chỉ ra, nó sẽ không hoạt động nếu bạn không thêm:

itemImageView.layer.masksToBounds = YES;

30
Tại sao đây có thể là câu trả lời tốt nhất? Tôi không nghĩ vậy. Sử dụng angleRadius gây ra hiệu suất kém trong chế độ xem cuộn, đặc biệt là trong các thiết bị iPhone4.
Danny Xu

11
Tôi thích điểm 'đặt angleRadius bằng một nửa chiều rộng hoặc chiều cao' nhưng đừng quên thêm 'itemImageView.layer.masksToBounds = YES;' nếu không nó sẽ không hoạt động.
atulkhatri

Nhân tiện như Danny Xu đã nhận xét, nó sẽ làm giảm hiệu suất cuộn của chế độ xem bảng, Vì vậy, nên tránh sử dụng trong các ô trong chế độ xem bảng.
atulkhatri

4
điều này sẽ khắc phục sự cố hiệu suất cuộn chế độ xem bảng của bạn. self.imageView.layer.shouldRasterize = CÓ; self.imageView.layer.rasterizationScale = [UIScreen mainScreen] .scale;
hishboy

Đối với Swift3: itemImageView.layer.masksToBounds = true;
Loïs Talagrand

38

Để thêm đường viền

self.ImageView.layer.borderWidth = 3.0f;

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

Đối với hình dạng tròn

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

Tham khảo liên kết này

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


14

Sử dụng mã này .. Điều này sẽ hữu ích ..

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

Việc này ổn với tôi. :)


nó thực sự rất đơn giản bằng cách sử dụng mã này !! cảm ơn @Shivam
Anilkumar iOS - ReactNative

10

Đây là một phương pháp cập nhật nhanh chóng hơn bằng cách sử dụng IBDesignable và IBInspectable để phân lớp 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()
    }
}

Tôi phải thêm đoạn mã sau để làm cho nó làm việc cho tôi (bên trong một tế bào xem bảng): layoutSubviews override func () {makeRound ()}
Herbert

1
+ 1 cho @herbert. Nó hoàn toàn làm việc cho tôi khi tôi ghi đè layoutSubviews bên trong lớp, bạn nên cập nhật mã
Abdoelrhman

Cảm ơn bạn!! Cuối cùng tôi đã thực hiện điều này (lớp con, nhưng trong Objective-C) để xử lý một số UIImageViews hình tròn mà sẽ không NGƯNG TRÒN.
John Stewart

7

Vâng, nó có thể cung cấp cho layer.cornerRadius (cần phải add #import <QuartzCore/QuartzCore.h>)
cho tạo hình tròn bất kỳ kiểm soát nhưng trong trường hợp của bạn thay vì thiết lập layercủa UIImageViewnó là cách tốt nhất để tạo hình ảnh của bạn như hình tròn và thêm nó vào UIImageViewnào có backGroundColorClearColor .

Cũng tham khảo Hai Nguồn mã này.

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

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

Điều này có thể hữu ích trong trường hợp của bạn:


4
Cuối cùng, tôi nghĩ @iPatel là người duy nhất quan tâm đến hiệu suất ở đây. Hãy cẩn thận với angleRadius nếu bạn muốn có hiệu suất cao khi cuộn.
Danny Xu

Mình hơi bối rối ... sao bạn lại đăng link dự án circle view? Điều đó không liên quan gì đến câu hỏi, cũng như câu trả lời bạn đã đưa ra.
user717452

@iPatel - update: liên kết thứ hai đã bị tác giả không dùng nữa và không thể tải xuống được nữa.
trdavidson

3

Đặt chiều cao và chiều rộng của UIImageView giống nhau, ví dụ: Height=60& Width = 60, sau đó cornerRadiusphải bằng một nửa. Tôi đã giữ nó là 30 trong trường hợp của tôi. Nó phù hợp với tôi.

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

2

Nếu sử dụng một số tự động thanh toán và các độ cao ô khác nhau, bạn nên làm theo cách này:

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

1

Tôi sử dụng lớp Round Image View… Vì vậy, tôi chỉ sử dụng nó thay vì UIImageView và không có gì để chỉnh sửa…

Lớp này cũng vẽ một đường viền tùy chọn xung quanh hình tròn. Thường có một đường viền xung quanh các hình ảnh tròn.

Nó không phải là một lớp con của UIImageView vì UIImageView có cơ chế kết xuất riêng và không gọi phương thức drawRect ..

Giao diện:

#import <UIKit/UIKit.h>

@interface MFRoundImageView : UIView

@property(nonatomic,strong) UIImage* image;

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

@end

Thực hiệ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

Giải pháp hữu ích trong Swiftviệc sử dụng extension:

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

Sử dụng:

self.venueImageView.circleMe()

Sẽ tốt hơn nếu áp dụng phần mở rộng cho UIImageView? Mã này hoạt động, nhưng nó làm cho tiện ích mở rộng chung cho bất kỳ UIViewđối tượng nào .
mã swiftcode

UIImageViewđã được mở rộng từ UIView. Trong một số trường hợp, bạn có thể cần khoanh tròn một số UIViews, vì vậy phương pháp này sẽ hoạt động cho tất cả.
Hossam Ghareeb

0

Tạo chế độ xem hình ảnh tròn và điều đó khá dễ dàng với liên kết SO bên dưới, chỉ cần có các ô tùy chỉnh cho chế độ xem bảng của bạn thay vì phân bổ mọi thứ trong phương thức cellForRowAtIndexPath của bạn.

Làm thế nào để làm cho nút tròn với nền hình ảnh trong iPhone?

Liên kết trên cung cấp cho bạn ví dụ về các nút chỉ sử dụng nó cho các chế độ xem hình ảnh của bạn.


0

Nếu bạn hiển thị hình ảnh trên một màu nền đồng nhất, một giải pháp dễ dàng có thể là sử dụng hình ảnh lớp phủ có vòng tròn trong suốt ở giữa.

Bằng cách này, bạn vẫn có thể sử dụng hình ảnh vuông và thêm hình ảnh hình tròn lên trên chúng để có được hiệu ứng hình tròn.

Nếu bạn không cần xử lý hình ảnh của mình hoặc hiển thị chúng trên một màu nền phức tạp, đây có thể là một giải pháp đơn giản mà không ảnh hưởng đến hiệu suất.


Không, tôi không. Nó chỉ là tải đơn giản, tự động lưu vào bộ nhớ cache (hình thu nhỏ bình phương) và hiển thị.
swiftcode

Nó thực sự hiệu quả, tôi đã sử dụng cách khó khăn này trước đây. Nhưng nó không phù hợp với ứng dụng phiên bản mới của tôi bây giờ.
Danny Xu

0

Nhanh chóng , bên trong viewDidLoadphương pháp của bạn , với userImageổ cắm:

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

Trong Swift, hãy sử dụng Phần mở rộng này cho CircularImageView hoặc 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
    }

}

Sử dụng:

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

0

Đối với chế độ xem hình ảnh tròn, hãy sử dụng mã bên dưới.

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

Đừng quên thay đổi angleRadius trong phương thức viewDidLayoutSubviews của UIView của bạn.

Thí dụ:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    self.imageView.layer.cornerRadius = self.imageView.frame.size.width / 2;
    self.imageView.clipsToBounds = true
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.