2009-06-15 18 views

Odpowiedz

66

Można użyć CoreGraphics aby utworzyć ścieżkę dla okrągłej prostokąta z tym fragmencie kodu:

static void addRoundedRectToPath(CGContextRef context, CGRect rect, float ovalWidth, float ovalHeight) 
{ 
    float fw, fh; 
    if (ovalWidth == 0 || ovalHeight == 0) { 
     CGContextAddRect(context, rect); 
     return; 
    } 
    CGContextSaveGState(context); 
    CGContextTranslateCTM (context, CGRectGetMinX(rect), CGRectGetMinY(rect)); 
    CGContextScaleCTM (context, ovalWidth, ovalHeight); 
    fw = CGRectGetWidth (rect)/ovalWidth; 
    fh = CGRectGetHeight (rect)/ovalHeight; 
    CGContextMoveToPoint(context, fw, fh/2); 
    CGContextAddArcToPoint(context, fw, fh, fw/2, fh, 1); 
    CGContextAddArcToPoint(context, 0, fh, 0, fh/2, 1); 
    CGContextAddArcToPoint(context, 0, 0, fw/2, 0, 1); 
    CGContextAddArcToPoint(context, fw, 0, fw, fh/2, 1); 
    CGContextClosePath(context); 
    CGContextRestoreGState(context); 
} 

a następnie zadzwonić CGContextClip (kontekstowe); aby przypiąć go do ścieżki prostokąta. Teraz każdy rysunek, łącznie z rysowaniem obrazu, zostanie przycięty do okrągłego prostokąta.

Jako przykład, zakładając, „obraz” jest UIImage, i to jest w drawRect: metoda:

CGContextRef context = UIGraphicsGetCurrentContext(); 
CGContextSaveGState(context); 
addRoundedRectToPath(context, self.frame, 10, 10); 
CGContextClip(context); 
[image drawInRect:self.frame]; 
CGContextRestoreGState(context); 
+8

się głosowanie, ponieważ matematyka jest cool – slf

+0

To wygląda bardzo przydatny, ale nie jestem zaznajomiony z biblioteka CG. Jeśli mam UIImageView/UIImage, gdzie mam przejść? – erotsppa

+0

Użytkownik chciałby zaimplementować metodę drawRect w widoku z kodem dodanym powyżej. – NilObject

34

Tutaj jest jeszcze łatwiejszy sposób, który jest dostępny w iPhone 3.0 i up. Każdy obiekt oparty na widoku ma powiązaną warstwę. Każda warstwa może mieć zestaw promień rogu, to daje tylko to, co chcesz:

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

// You can even add a border 
[layer setBorderWidth:4.0]; 
[layer setBorderColor:[[UIColor blueColor] CGColor]]; 

Aby korzystać z tych metod może trzeba dodać:

#import <QuartzCore/QuartzCore.h> 
+1

Powyższa metoda CoreGraphics opublikowana przez NilObject jest szybsza w przypadku animowania przedmiotów. Wygląda na to, że wbudowany promień narożnika nie jest tak wydajny. – MagicSeth

+2

Dzięki! Jeśli ktokolwiek wpadnie w kłopoty z tym, upewnij się, że #import w twoim pliku implementacyjnym, w przeciwnym razie żadna z tych metod nie poleci. –

+1

Tutaj przydzielasz obiekt UIImageView. Nie jest to opcja, gdy mamy do czynienia z obrazami w widoku UITableViews. – samvermette

2

Zobacz ten post - Bardzo prosta odpowiedź

How to set round corners in UI images in iphone

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

Obie metody działają ale różnice sho ws up w zależności od tego, gdzie go używasz.

Dla Ex: Jeśli masz widok tabeli z komórkami pokazującymi obraz wraz z innymi etykietami itp., A do ustawienia rogu Radius użyjesz warstwy, przewijanie przyjmie duże trafienie. Robi się nierówno.

Stawiałem czoła temu problemowi, gdy używałem warstwy dla obrazu w komórce widoku tabeli i próbowałem znaleźć przyczynę tego szarpnięcia, aby stwierdzić, że CALayer był winowajcą.

Używane pierwsze rozwiązanie do robienia rzeczy w drawRect wyjaśnione przez NilObject. To działa jak urok, a przewijanie jest gładkie jak jedwab.

Z drugiej strony, jeśli chcesz użyć tego w widokach statycznych, takich jak widok popover, itp., Warstwa jest najprostszym sposobem, aby to zrobić.

Tak jak powiedziałem, obie metody działają dobrze, wystarczy, że zdecydujesz w oparciu o to, gdzie chcesz go użyć.

0

Używam tej metody.

+ (UIImage *)imageWithColor:(UIColor *)color andSize:(CGSize)size; 
    { 
     UIImage *img = nil; 


     CGRect rect = CGRectMake(0, 0, size.width, size.height); 
     UIGraphicsBeginImageContext(rect.size); 
     CGContextRef context = UIGraphicsGetCurrentContext(); 
     CGContextSetFillColorWithColor(context, 
            color.CGColor); 
     CGContextFillRect(context, rect); 
     img = UIGraphicsGetImageFromCurrentImageContext(); 

     UIGraphicsEndImageContext(); 


     return img; 
    } 
+2

Zgodnie z regułami zarządzania pamięcią obiekt obrazu zwrócony przez 'UIGraphicsGetImageFromCurrentImageContext' nie musi być zachowywany, więc będzie tam wyciekać pamięć. Jest to wywoływacz 'imageWithColor', który musi go zachować. Może dodałeś zatrzymanie ze względu na 'NSAutoreelasePool' (który również wydaje się podejrzany)? –

15

Zdaję sobie sprawę, jest to stare dzieje, ale po prostu gotować go nieco w dół:

Istnieje dwa ewentualne pytania tutaj: (1) w jaki sposób mogę ubiegać zaokrąglone narożniki do UIView (takich jak UIImageView), który będzie wyświetlany na ekranie, oraz (2) jak zamaskować kwadratowy obraz (to znaczy UIImage), aby utworzyć nowy obraz z zaokrąglonymi narożnikami.

Dla (1) najprostszym sposobem jest użycie CoreAnimation i ustawienie view.layer.Nieruchomość cornerRadius

// Because we're using CoreAnimation, we must include QuartzCore.h 
// and link QuartzCore.framework in a build phases 
#import <QuartzCore/QuartzCore.h> 

// start with an image 
UIImage * fooImage = [UIImage imageNamed:@"foo.png"]; 
// put it in a UIImageView 
UIView * view = [UIImageView alloc] initWithImage:fooImage]; 
// round its corners. This mask now applies to the view's layer's *background* 
view.layer.cornerRadius = 10.f 
// enable masksToBounds, so the mask applies to its foreground, the image 
view.layer.masksToBounds = YES; 

Do (2), najlepszym sposobem jest użycie operacji graficznych UIKit:

// start with an image 
UIImage * fooImage = [UIImage imageNamed:@"foo.png"]; 
CGRect imageRect = CGRectMake(0, 0, fooImage.size.width, fooImage.size.height); 
// set the implicit graphics context ("canvas") to a bitmap context for images 
UIGraphicsBeginImageContextWithOptions(imageRect.size,NO,0.0); 
// create a bezier path defining rounded corners 
UIBezierPath * path = [UIBezierPath bezierPathWithRoundedRect:imageRect cornerRadius:10.f]; 
// use this path for clipping in the implicit context 
[path addClip]; 
// draw the image into the implicit context 
[fooImage drawInRect:imageRect]; 
// save the clipped image from the implicit context into an image 
UIImage *maskedImage = UIGraphicsGetImageFromCurrentImageContext(); 
// cleanup 
UIGraphicsEndImageContext(); 

Co jest trudne o problemu (2) stanowi, że można by pomyśleć, można zrobić całą operację za pomocą właściwości view.layer.mask w programie CoreAnimation. Ale nie możesz, ponieważ metoda CALayer renderInContext:, której używasz do generowania UIImage z zamaskowanej warstwy, wydaje się ignorować maskę. Co gorsza, dokumentacja dla renderInContext: nie wspomina o tym i odnosi się tylko do zachowania dla OSX 10.5.

Pewien dodatkowy kontekst: powyższe podejście do (2) polega na użyciu owijaczy UIKit wokół bardziej podstawowej funkcjonalności CoreGraphics. Możesz zrobić to samo, używając wywołań CoreGraphics bezpośrednio - to właśnie robi wybrana odpowiedź - ale musisz ręcznie zbudować zaokrągloną ścieżkę beziera ręcznie z krzywych i linii, a także musisz zrekompensować fakt, że CoreGraphics używa rysunek układu współrzędnych odwrócony względem UIKit.

+0

Ta operacja działa dobrze, odzwierciedla obraz w poziomie. usunąłem CGContextDrawImage ((ctx, imageRect, theImage.CGImage) i zastąpiłem go [theImage drawInRect: CGRectMake (0,0, imageRect.size.width, imageRect.size.height)] i to rozwiązało problem. – zachron

+0

@Zachron dziękuję za poprawkę. Ponownie napisałem tę odpowiedź, aby całkowicie uniknąć surowego CG.Wydaje się to zalecane w oparciu o sekcję "Rysowanie za pomocą kwarcu i UIKit" w witrynie Apple http://developer.apple.com/library/ios/#documentation/2DDrawing/Conceptual/DrawingPrintingiOS/GraphicsDrawingOverview/GraphicsDrawingOverview.html – algal

1

Bardzo proste. self.profileImageView.layer.cornerRadius = self.profileImageView.frame.size.width/2; self.profileImageView.clipsToBounds = YES;

Dla każdego widoku istnieje powiązana właściwość warstwy. Tak więc pierwszą linią powyższego jest ustawienie promienia naroża obiektu warstwy (tj. Instancji klasy CALayer). Aby utworzyć okrągły obraz z kwadratu, promień jest ustawiony na połowę szerokości UIImageView. Na przykład, jeśli szerokość kwadratu wynosi 100 pikseli. Promień jest ustawiony na 50 pikseli. Po drugie, musisz ustawić właściwość clipsToBounds na YES, aby warstwa działała.

0

budynku off algal, oto kilka sposobów, które są ładne, aby umieścić w kategorii UIImage:


- (UIImage *) roundedCornerImageWithRadius:(CGFloat)radius 
{ 
    CGRect imageRect = CGRectMake(0, 0, self.size.width, self.size.height); 
    UIGraphicsBeginImageContextWithOptions(imageRect.size,NO,0.0); //scale 0 yields better results 

    //create a bezier path defining rounded corners and use it for clippping 
    UIBezierPath * path = [UIBezierPath bezierPathWithRoundedRect:imageRect cornerRadius:radius]; 
    [path addClip]; 

    // draw the image into the implicit context 
    [self drawInRect:imageRect]; 

    // get image and cleanup 
    UIImage *roundedCornerImage = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 
    return roundedCornerImage; 
} 

+ (UIImage *)imageWithColor:(UIColor *)color size:(CGSize)size andCornerRadius:(CGFloat)radius 
{ 
    UIImage *image = nil; 
    if (size.width == 0 || size.height == 0) { 
     size = CGSizeMake(1.0, 1.0); 
    } 
    CGRect rect = CGRectMake(0.0f, 0.0f, size.width, size.height); 
    UIGraphicsBeginImageContextWithOptions(rect.size,NO,0.0); //yields sharper results than UIGraphicsBeginImageContext(rect.size) 
    CGContextRef context = UIGraphicsGetCurrentContext(); 
    if (context) 
    { 
     CGContextSetFillColorWithColor(context, [color CGColor]); 
     if (radius > 0.0) { 
      //create a bezier path defining rounded corners and use it for clippping 
      UIBezierPath * path = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:radius]; 
      [path addClip]; 
      CGContextAddPath(context, path.CGPath); 
     } 
     CGContextFillRect(context, rect); 
     image = UIGraphicsGetImageFromCurrentImageContext(); 
     UIGraphicsEndImageContext(); 
    } 
    return image; 
} 
Powiązane problemy