Додайте закруглені кути до всіх UIImageViews


78

Я хотів би додати кілька закруглених кутів до всіх UIImageViews у своєму проекті. Я вже працюю з кодом, але маю застосовувати його до кожного зображення; чи слід підклас UIImageView додати це? Якщо так, може хтось підкаже мені, як це зробити?

Ось код

- (void)viewDidLoad {
    [super viewDidLoad];
    NSString *mainpath = [[NSBundle mainBundle] bundlePath];
    welcomeImageView.image = [UIImage imageWithContentsOfFile:[mainpath stringByAppendingString:@"/test.png"]];
    welcomeImageView.layer.cornerRadius = 9.0;
    welcomeImageView.layer.masksToBounds = YES;
    welcomeImageView.layer.borderColor = [UIColor blackColor].CGColor;
    welcomeImageView.layer.borderWidth = 3.0;
    CGRect frame = welcomeImageView.frame;
    frame.size.width = 100;
    frame.size.height = 100;
    welcomeImageView.frame = frame;
}

Привіт Джеку - дякую за це, саме те, що я хотів зробити. Коли я намагаюся використовувати це, я отримую помилку "доступу до невідомого компонента" cornerRadius "властивості", і те саме для masksToBounds тощо. Як не дивно функція сенсу коду в xcode корисно заповнює ці властивості для мене, але компілятор не хоче складіть їх. Чи працює наведений вище код для вас на iOS4.0?
Ben Clayton

20
Вам потрібно #import <QuartzCore / QuartzCore.h>
vodkhang

Відповіді:


25

Ви можете використовувати категорію для UIImage, яка є альтернативним способом підкласу класу, а іноді і легшим для невеликих змін.

наприклад, додати метод, який повертає UIImage із встановленими атрибутами закругленого кута.

+(UIImage *)imageWithContentsOfFile:(NSString *)file cornerRadius:(NSInteger)... 

більше інформації про категорії Objective-c можна знайти http://macdevelopertips.com/objective-c/objective-c-categories.html


Відмінно. Велике спасибі, я застосую категорію UIImage - підручник на macdevelopertips.com дуже корисний.
Джек

4
Я збирався описати, як підклас, але мені такий підхід подобається набагато більше.
Kendall Helmstetter Gelner

Я спантеличений. Тоді це матиме 100% всіх зображень UII. Чому б не підклас UIImage, щось на зразок UIFramedImage?
Роб

1
ось посилання для вищевказаного методу igframework-iphone-static-library-project.googlecode.com/…
Bobj-C

3
@Rob насправді, використовуючи цей підхід, 0% UIImages матимуть закруглені кути, поки ви не зміните їх на виклик нового методу. Це рішення не замінює існуючі методи (чого робити не слід). Це може бути чистішим рішенням, ніж підкласування, оскільки для нього не потрібен повний підклас - що може бути надмірним, оскільки ви не додаєте жодних членів або нову функціональність до UIImage - все, що вам потрібно - це округлі кути UIImage без дублювання коду.
Jarsen

114

Перевірте це - Закруглені кути на UIImage

Модифікація шару видається найкращим способом.

UIImageView * roundedView = [[UIImageView alloc] initWithImage: [UIImage imageNamed:@"wood.jpg"]];
// Get the Layer of any view
CALayer * l = [roundedView layer];
[l setMasksToBounds:YES];
[l setCornerRadius:10.0];

1
Дякую. Це, по суті, те, що я вже робив, однак я використовував крапкові позначення для зміни властивостей. Мені просто цікаво, чи легко було додати це до підкласу, щоб, якщо я хочу змінити радіус, мені не довелося б змінювати кожен екземпляр цього.
Джек

-1 Це не намагається відповісти на запитання, яке стосується простого застосування того самого коду до кожного UIImageViewекземпляра.
Стюарт

16

Замість того щоб підкласувати, ви можете досягти більш потужних функціональних можливостей за допомогою простих категорій на UIImageView та CALayer.

Створіть категорію на UIImageView так:

- (void)maskRoundCorners:(UIRectCorner)corners radius:(CGFloat)radius {
    // To round all corners, we can just set the radius on the layer
    if ( corners == UIRectCornerAllCorners ) {
        self.layer.cornerRadius = radius;
        self.layer.masksToBounds = YES;
    } else {
        // If we want to choose which corners we want to mask then
        // it is necessary to create a mask layer.
        self.layer.mask = [CALayer maskLayerWithCorners:corners radii:CGSizeMake(radius, radius) frame:self.bounds];
    }
}

Це викликає метод категорії на CALayer:

+ (id)maskLayerWithCorners:(UIRectCorner)corners radii:(CGSize)radii frame:(CGRect)frame {

    // Create a CAShapeLayer
    CAShapeLayer *mask = [CAShapeLayer layer];

    // Set the frame
    mask.frame = frame;

    // Set the CGPath from a UIBezierPath
    mask.path = [UIBezierPath bezierPathWithRoundedRect:mask.bounds byRoundingCorners:corners cornerRadii:radii].CGPath;

    // Set the fill color
    mask.fillColor = [UIColor whiteColor].CGColor;

    return mask;
}

Отже, це дозволяє округлити будь-яку комбінацію (див. UIRectCorner) Кутів, що особливо зручно, якщо ви хочете розмістити зображення в стилі групи UITableView. Однак це робить одне застереження. Оскільки ми не підкласифікувались UIImageView, ми не можемо ввести будь-який код layoutSubviews, а це означає, що шар маски може бути неправильним. Насправді, під час налаштування комірок межі подання зображення навіть не встановлюються, коли ви викликаєте метод категорії. Отже, перед додаванням закруглених кутів вам потрібно переконатися, що межі подання зображення встановлені (крім випадків, коли використовуєтьсяUIRectCornersAllCorners ).

Ось код, який робить це:

        // Perform corner rounding
        UIRectCorner corners = !UIRectCornerAllCorners;
        if (indexPath.row == 0) 
            corners = UIRectCornerTopLeft;
        if (indexPath.row == numberOfRowsInTheTable)  
            corners |= UIRectCornerBottomLeft;

        if (corners > 0) {
            cell.imageView.bounds = CGRectMake(0.f, 0.f, [self.tableView rowHeight], [self.tableView rowHeight]);
            [cell.imageView maskRoundCorners:corners radius:10.f];
        } else {
            [cell.imageView removeRoundCornersMask];
        }

У мене є ще одна категорія, яка видаляє закруглені кути - все, що потрібно - це видалити будь-які маски та встановити значення cornerRadius0.


1
Чудове рішення. Але мені цікаво, чи не було б краще створити клас, щоб усі представлення могли отримати до нього доступ, як UILabel, UIButton, UIView тощо - такий собі універсальний метод?
Борут Томазін

1
Не зважай. Я щойно створив категорію UIView, яка обробляє всі види переглядів. Дякую!
Борут Томазін

1
Чудова думка @BorutTomazin - я думав про YAGNI, але переміщення категорії UIImageView до UIView було б чудовою маленькою корисною функцією.
Даніель Торп,

1
Саме те, що я зробив. Тепер його можна використовувати на всіх уявленнях, що їхніми батьками є UIView ...
Борут Томазін

5

Так, вам слід підклас UIImageView і використовувати власний підклас протягом усього проекту.


1
Дякую, я думав, що це буде найкращий спосіб. Чи знаєте ви якісь хороші підручники з використання підкласів? Чи можу я використати цей метод із конструктором інтерфейсів чи переписати свій інтерфейс у коді?
Джек

2
Насправді, відповідь Мартіня вище, мабуть, простіша, позбавляючи вас від необхідності користуватися спеціальним підкласом скрізь, у Interface Builder тощо
Якоб Борг

4

Ви можете підклас UIImageView, і тоді, якщо ви реалізуєте метод setNeedsDisplay, круглі кути будуть працювати в підкласах. (не забудьте імпортувати QuartzCore)

-(void)setNeedsDisplay {
    self.layer.cornerRadius = 5;
    self.layer.masksToBounds = YES;
    [self.layer setBorderColor:[[UIColor whiteColor] CGColor]];
    [self.layer setBorderWidth: 2.0];
}

3
Ви не повинні цього робити, setNeedsDisplay по суті планує перефарбовувати, і це його мета. Ви повинні налаштувати свій шар в методі init.
pronebird

3

Спробуйте це,

coverImage.image = [UIImage imageWithContentsOfFile:@"coverImage.png"]; 
coverImage.layer.masksToBounds = YES;
coverImage.layer.cornerRadius = 10.0;
coverImage.layer.borderWidth = 1.0;
coverImage.layer.borderColor = [[UIColor brown] CGColor];

це може вам допомогти.


-1 Це не намагається відповісти на питання. Питання не в тому, як створити округлення UIImageView(це успішно робиться у фрагменті коду запитання), а в тому, як ефективно використовувати цей код повторно.
Стюарт
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.