Круговой UIImageView в UITableView без снижения производительности?


82

У меня есть UIImageViewна каждой из моих UITableViewячеек, которые отображают удаленное изображение (используя SDWebImage). Я сделал некоторые QuartzCoreстили слоя для представления изображения, как таковые:

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

Итак, теперь у меня есть квадрат 50x50 со слабой серой рамкой, но я бы хотел сделать его круглым, а не квадратным. Приложение Hemoglobeиспользует круглые изображения в представлениях таблиц, и я хотел бы добиться именно такого эффекта. Однако я не хочу использовать cornerRadius, так как это ухудшает мой FPS при прокрутке.

Здесь Hemoglobeпоказан циркуляр UIImageViews:

введите описание изображения здесь

Есть ли способ добиться такого эффекта? Благодарю.


1
не cornerRadius влияет на производительность, masksToBounds / clipsToBounds - проблема
Calin Chitu

Ответы:


141

Просто установите cornerRadiusполовину ширины или высоты (при условии, что вид вашего объекта квадратный).

Например, если ширина и высота вашего объекта равны 50:

itemImageView.layer.cornerRadius = 25;

Обновление - как указывает пользователь atulkhatri, это не сработает, если вы не добавите:

itemImageView.layer.masksToBounds = YES;

30
Почему это может быть лучший ответ? Я так не думаю. Использование cornerRadius приводит к снижению производительности в режиме прокрутки, особенно на устройствах iPhone4.
Дэнни Сюй

11
Мне понравился пункт «установить угол радиуса на половину ширины или высоты», но не забудьте добавить «itemImageView.layer.masksToBounds = YES;» иначе это не сработает.
atulkhatri 02

Кстати, как прокомментировал Дэнни Сюй, это снизит производительность прокрутки представления таблицы, поэтому следует избегать использования ячеек представления таблицы.
atulkhatri 02

4
это должно исправить вашу проблему с производительностью прокрутки tableview. self.imageView.layer.shouldRasterize = ДА; self.imageView.layer.rasterizationScale = [UIScreen mainScreen] .scale;
hishboy

Для Swift3: itemImageView.layer.masksToBounds = true;
Лоис Талагранд

38

Добавить границу

self.ImageView.layer.borderWidth = 3.0f;

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

Для круглой формы

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

Обратитесь по этой ссылке

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


14

Используйте этот код .. Это будет полезно ..

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

Он отлично работает для меня. :)


его действительно очень просто использовать этот код !! спасибо @Shivam
Anilkumar iOS - ReactNative

10

Вот более современный метод быстрого использования IBDesignable и IBInspectable для подкласса 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()
    }
}

Мне пришлось добавить следующий код, чтобы он работал у меня (внутри ячейки табличного представления): override func layoutSubviews () {makeRound ()}
herbert

1
+1 для @herbert. У меня это полностью сработало, когда я переопределяю layoutSubviews внутри класса, вам следует обновить код
Абдельрхман

Спасибо!! Я, наконец, сделал это (подкласс, но в Objective-C), чтобы обработать некоторые круговые UIImageViews, которые просто не оставались бы круглыми.
Джон Стюарт

7

Да, можно дать layer.cornerRadius (нужно добавить #import <QuartzCore/QuartzCore.h>)
для создания кругового любого контроля , но в вместо вашего случая набора layerиз UIImageViewэто лучший способ создать свой имидж круговых и добавить его на UIImageViewкаком есть backGroundColorэто ClearColor.

Также обратитесь к этим двум источникам кода.

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

и

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

Это может быть полезно в вашем случае:


4
Наконец, я думаю, что @iPatel - единственный, кто заботится о производительности здесь. Будьте осторожны с cornerRadius, если вам нужна высокая производительность при прокрутке.
Дэнни Сюй

Я немного запутался ... зачем вы разместили ссылку на проект кругового просмотра? Это не имеет ничего общего ни с вопросом, ни с тем ответом, который вы дали.
user717452

@iPatel - обновление: вторая ссылка устарела автором и больше не может быть загружена.
trdavidson

3

Установите одинаковую высоту и ширину UIImageView, например: Height=60& Width = 60, тогда cornerRadiusдолжно быть ровно половина. В моем случае я оставил 30. У меня это сработало.

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

2

Если вы используете автопрокладку и разную высоту ячеек, лучше сделать это так:

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

1

Я использую класс Round Image View ... Поэтому я просто использую его вместо UIImageView, и мне нечего настраивать ...

Этот класс также рисует необязательную границу вокруг круга. Часто вокруг закругленных изображений есть рамка.

Это не подкласс UIImageView, потому что UIImageView имеет собственный механизм отрисовки и не вызывает метод drawRect.

Интерфейс:

#import <UIKit/UIKit.h>

@interface MFRoundImageView : UIView

@property(nonatomic,strong) UIImage* image;

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

@end

Реализация :

#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

Полезное решение при Swiftиспользовании extension:

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

Применение:

self.venueImageView.circleMe()

Не лучше ли применить расширение к UIImageView? Этот код работает, но делает расширение универсальным для любых UIViewобъектов.
swiftcode

UIImageViewуже распространяется с UIView. В некоторых случаях вам может потребоваться обвести несколько кружков UIViews, поэтому этот метод подойдет всем.
Хосам Гариб,

0

Создание кругового представления изображения, и это довольно просто с помощью приведенной ниже ссылки SO, просто создайте настраиваемые ячейки для представления таблицы вместо того, чтобы выделять все элементы в вашем методе cellForRowAtIndexPath.

как сделать кнопку круглой с фоном изображения в IPhone?

Приведенная выше ссылка дает вам пример кнопок, просто используйте ее для просмотра изображений.


0

Если вы показываете изображения поверх сплошного цвета фона, простым решением может быть использование наложенного изображения с прозрачным кружком посередине.

Таким образом, вы по-прежнему можете использовать квадратные изображения и добавлять изображение круга над ними, чтобы получить эффект круга.

Если вам не нужно манипулировать изображениями или отображать их на сложном цвете фона, это может быть простое решение без снижения производительности.


Нет, не знаю. Это просто загрузка, автоматическое кеширование (миниатюра в квадрате) и отображение.
swiftcode

Это действительно тренировка. Я использовал этот хитрый способ раньше. Но сейчас это не подходит для моей новой версии приложения.
Дэнни Сюй

0

Быстро , внутри вашего viewDidLoadметода, с userImageвыходом:

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 используйте это расширение для CircularImageView или 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
    }

}

Применение:

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

0

Для кругового просмотра изображений используйте приведенный ниже код.

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

Не забудьте изменить cornerRadius в методе viewDidLayoutSubviews вашего UIView.

Пример:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    self.imageView.layer.cornerRadius = self.imageView.frame.size.width / 2;
    self.imageView.clipsToBounds = true
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.