Fügen Sie allen UIImageViews abgerundete Ecken hinzu

78

Ich möchte allen UIImageViews in meinem Projekt einige abgerundete Ecken hinzufügen. Ich habe den Code bereits zum Laufen gebracht, muss ihn aber auf jedes Bild anwenden. sollte ich UIImageView unterordnen, um dies hinzuzufügen? Wenn ja, kann mir jemand Hinweise geben, wie das geht?

Hier ist der Code

- (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;
}
Jack
quelle
Hallo Jack - danke dafür, genau das wollte ich tun. Wenn ich versuche, dies zu verwenden, erhalte ich die Fehlermeldung "Zugriff auf unbekannte" CornerRadius "-Komponente einer Eigenschaft" und dasselbe für masksToBounds usw. Seltsamerweise füllt die Code-Sense-Funktion in xcode diese Eigenschaften für mich hilfreich aus, der Compiler jedoch nicht kompiliere sie. Funktioniert der obige Code für Sie unter iOS 4.0?
Ben Clayton
20
Sie müssen #import <QuartzCore / QuartzCore.h>
vodkhang

Antworten:

25

Sie können eine Kategorie für UIImage verwenden, die eine alternative Methode zum Unterklassen einer Klasse darstellt und manchmal für nur kleine Änderungen einfacher ist.

Fügen Sie beispielsweise eine Methode hinzu, die ein UIImage mit festgelegten Attributen für abgerundete Ecken zurückgibt.

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

Weitere Informationen zu Objective-c-Kategorien finden Sie unter http://macdevelopertips.com/objective-c/objective-c-categories.html

Martinj
quelle
Ausgezeichnet. Vielen Dank, ich werde eine UIImage-Kategorie implementieren - das Tutorial auf macdevelopertips.com ist sehr hilfreich.
Jack
4
Ich wollte beschreiben, wie man Unterklassen erstellt, aber ich mag diesen Ansatz viel mehr.
Kendall Helmstetter Gelner
Ich bin verwirrt. Dann haben 100% aller UIImages dies. Warum nicht UIImage unterordnen, so etwas wie UIFramedImage?
Rob
1
Hier ist der Link für die obige Methode igframework-iphone-static-library-project.googlecode.com/…
Bobj-C
3
@Rob Bei diesem Ansatz haben 0% der UIImages abgerundete Ecken, bis Sie sie ändern, um die neue Methode aufzurufen. Diese Lösung überschreibt keine vorhandenen Methoden (was Sie nicht tun sollten). Dies kann eine sauberere Lösung sein als Unterklassen, da keine vollständige Unterklasse erforderlich ist - was möglicherweise übertrieben ist, da Sie UIImage keine Mitglieder oder neue Funktionen hinzufügen -. Sie möchten lediglich eine abgerundete UIImage-Ecke ohne Codeduplizierung.
Jarsen
114

Überprüfen Sie dies - Abgerundete Ecken auf UIImage

Die Ebenenmodifikation scheint der beste Weg zu sein.

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];
NP Compete
quelle
1
Vielen Dank. Dies ist im Wesentlichen das, was ich bereits getan habe, jedoch habe ich die Punktnotation verwendet, um die Eigenschaften zu ändern. Ich habe mich nur gefragt, ob es einfach ist, dies einer Unterklasse hinzuzufügen, damit ich nicht jede Instanz davon ändern muss, wenn ich den Radius ändern möchte.
Jack
-1 Dies versucht nicht, die Frage zu beantworten, bei der es darum geht, einfach denselben Code auf jede UIImageViewInstanz anzuwenden .
Stuart
16

Anstatt Unterklassen zu erstellen, können Sie durch einfache Kategorien in UIImageView und CALayer leistungsfähigere Funktionen erzielen.

Erstellen Sie eine Kategorie in UIImageView wie folgt:

- (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];
    }
}

Dies ruft eine Kategoriemethode in CALayer auf:

+ (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;
}

Auf diese Weise können Sie eine beliebige Kombination UIRectCornervon Ecken abrunden (siehe ). Dies ist besonders praktisch, wenn Sie ein Bild in einem Gruppenstil platzieren möchten UITableView. Es gibt jedoch eine Einschränkung, wenn Sie dies tun. Da wir keine Unterklassen haben UIImageView, können wir keinen Code einfügen layoutSubviews, was bedeutet, dass die Maskenebene möglicherweise nicht korrekt ist. Tatsächlich werden beim Konfigurieren von Zellen die Grenzen der Bildansicht nicht einmal festgelegt, wenn Sie die Kategoriemethode aufrufen. Daher müssen Sie sicherstellen, dass die Grenzen der Bildansicht festgelegt sind, bevor Sie abgerundete Ecken hinzufügen (außer bei Verwendung UIRectCornersAllCorners).

Hier ist ein Code, der dies tut:

        // 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];
        }

Ich habe eine andere Kategorie, die abgerundete Ecken entfernt - alles, was Sie tun müssen, ist, alle Masken zu entfernen und die cornerRadiusauf 0 zu setzen.

Daniel Thorpe
quelle
1
Tolle Lösung. Aber ich frage mich, ob es nicht besser wäre, eine Klasse zu erstellen, auf die alle Ansichten wie UILabel, UIButton, UIView usw. zugreifen können - eine universelle Methode?
Borut Tomazin
1
Keine Ursache. Ich habe gerade eine UIView-Kategorie erstellt, die alle Arten von Ansichten verarbeitet. Vielen Dank!
Borut Tomazin
1
@BorutTomazin großer Gedanke - Ich dachte an YAGNI, aber das Verschieben der UIImageView-Kategorie nach UIView wäre eine großartige kleine Dienstprogrammfunktion.
Daniel Thorpe
1
Genau das, was ich getan habe. Jetzt kann es für alle Ansichten verwendet werden, dass ihre Eltern UIView sind ...
Borut Tomazin
5

Ja, Sie sollten UIImageView unterklassifizieren und Ihre benutzerdefinierte Unterklasse im gesamten Projekt verwenden.

Ben Gottlieb
quelle
1
Danke, ich dachte das wäre der beste Weg. Kennen Sie gute Tutorials zur Verwendung von Unterklassen? Könnte ich diese Methode mit dem Interface Builder verwenden oder sollte ich meine Schnittstelle in Code umschreiben?
Jack
2
Tatsächlich ist die obige Antwort von Martinj wahrscheinlich einfacher, sodass Sie nicht überall eine benutzerdefinierte Unterklasse verwenden müssen, in Interface Builder usw.
Jakob Borg
4

Sie können UIImageView in Unterklassen unterteilen. Wenn Sie dann die setNeedsDisplay- Methode implementieren, funktionieren die runden Ecken in Unterklassen. (Vergessen Sie nicht, QuartzCore zu importieren)

-(void)setNeedsDisplay {
    self.layer.cornerRadius = 5;
    self.layer.masksToBounds = YES;
    [self.layer setBorderColor:[[UIColor whiteColor] CGColor]];
    [self.layer setBorderWidth: 2.0];
}
Alexey Linkov
quelle
3
Sie dürfen dies nicht tun, setNeedsDisplay plant im Wesentlichen das Neulackieren, und das ist der Zweck. Sie müssen Ihre Ebene in der Init-Methode einrichten.
Pronebird
3

Versuche dies,

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];

das kann dir helfen.

Nithinbemitk
quelle
-1 Dies versucht nicht, die Frage zu beantworten. Bei der Frage geht es nicht darum, wie eine Rundung erzeugt wird UIImageView(dies wird im Code-Snippet der Frage erfolgreich durchgeführt), sondern darum, wie dieser Code effektiv wiederverwendet werden kann.
Stuart