2009-06-15 2 views

ответ

66

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

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

И затем вызвать CGContextClip (контекст); чтобы скопировать его в прямоугольник. Теперь любой сделанный рисунок, включая рисование изображения, будет привязан к круглой форме прямоугольника.

В качестве примера, предполагая, «образ» является UIImage, и это находится в DrawRect: Метод:

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

до голосования, потому что математика это круто – slf

+0

Это выглядит очень полезно, но я не знаком с библиотеки CG. Если у меня есть UIImageView/UIImage, откуда я оттуда? – erotsppa

+0

Вы бы хотели реализовать метод drawRect на представлении с кодом, который я добавил выше. – NilObject

34

Вот еще проще метод, который доступен в iPhone 3.0 и выше. Каждый объект, основанный на представлении, имеет связанный уровень. Каждый слой может иметь набор углового радиуса, это даст вам только то, что вы хотите:

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

Чтобы использовать эти методы, возможно, потребуется добавить:

#import <QuartzCore/QuartzCore.h> 
+1

Метод CoreGraphics выше, размещенный NilObject быстрее, когда вы имеете дело с анимацией элементов. По-видимому, встроенный угловой радиус не так эффективен. – MagicSeth

+2

Спасибо! Если у кого-то возникают проблемы с этим, убедитесь, что #import в вашем файле реализации, иначе ни один из этих методов не будет летать. –

+1

Здесь вы выделяете объект UIImageView. Это не вариант, когда вы работаете с изображениями в UITableViews. – samvermette

2

Посмотреть этот пост - очень простой ответ

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

Оба метода работают, но различия шо ws up в зависимости от того, где вы его используете.

Для примера: если у вас есть табличный вид с ячейками, показывающими изображение вместе с другими метками и т. Д., И вы используете слой для установки cornerRadius, прокрутка сильно пострадает. Он дергается.

Я столкнулся с этой проблемой, когда использовал Layer для изображения в ячейке таблицы и пытался выяснить причину этой подлости только для того, чтобы обнаружить, что CALayer был виновником.

Использовал первое решение, выполняемое в drawRect, которое объясняется NilObject. Это работает как шарм с прокруткой, гладкой, как шелк.

С другой стороны, если вы хотите использовать это в статических представлениях, таких как popover view и т. Д., Слой - это самый простой способ сделать это.

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

0

Я использую этот метод.

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

В соответствии с правилами управления памятью объект изображения, возвращаемый 'UIGraphicsGetImageFromCurrentImageContext', не нуждается в сохранении, поэтому вы будете пропускать там память. Это вызывающий объект 'imageWithColor', который должен сохранить его. Возможно, вы добавили сохранение из-за 'NSAutoreelasePool' (что также кажется подозрительным)? –

15

Я понимаю, что это не новость, но только, чтобы вскипятить немного вниз:

Есть два возможные вопросы здесь: (1) как я применяю закругленные углы к UIView (например, UIImageView), который будет отображаться на экране, и (2) как скрыть квадратное изображение (то есть UIImage) для создания нового изображения с закругленными углами.

Для (1) проще всего использовать CoreAnimation и установить view.layer.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; 

Для (2), лучший способ заключается в использовании 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(); 

Что сложно о задаче (2) является то, что вы, возможно, думаете, что вы могли бы сделать всю операцию используя свойство view.layer.mask в CoreAnimation. Но вы не можете, потому что метод CALayer renderInContext:, который вы использовали для создания UIImage из скрытого слоя, кажется, игнорирует маску. Хуже того, документация для renderInContext: не упоминает об этом и ссылается только на поведение OSX 10.5.

Дальнейший контекст: вышеприведенный подход к (2) использует обертки UIKit вокруг более базовой функциональности CoreGraphics. Вы можете сделать то же самое, используя прямые вызовы CoreGraphics - это то, что делает выбранный ответ, - но тогда вам нужно построить закругленный прямой bezier-путь вручную из кривых и линий, и вам также необходимо компенсировать тот факт, что CoreGraphics использует рисование системы координат, которая перевернута относительно UIKit's.

+0

Это хорошо работает, зеркалирует изображение по горизонтали. Я удалил CGContextDrawImage ((ctx, imageRect, theImage.CGImage) и заменил его на [theImage drawInRect: CGRectMake (0,0, imageRect.size.width, imageRect.size.height)], и это решило проблему. – zachron

+0

@zachron Спасибо за исправление. Я переписал этот ответ, чтобы полностью избежать сырой CG.Это рекомендуется на основе чтения раздела «Рисование с кварцем и UIKit» в http://developer.apple.com/library/ios/#documentation/2DDrawing/Conceptual/DrawingPrintingiOS/GraphicsDrawingOverview/GraphicsDrawingOverview.html от Apple. – algal

1

Очень простой. self.profileImageView.layer.cornerRadius = self.profileImageView.frame.size.width/2; self.profileImageView.clipsToBounds = YES;

Для каждого вида есть свойство связанного слоя. Таким образом, первая строка приведена выше, чтобы задать угловой радиус объекта слоя (то есть экземпляр класса CALayer). Чтобы сделать круговое изображение из квадрата изображения, радиус устанавливается на половину ширины UIImageView. Например, если ширина квадрата изображения составляет 100 пикселей. Радиус установлен в 50 пикселей. Во-вторых, вы должны установить для свойства clipsToBounds значение YES, чтобы заставить слой работать.

0

Строительство прочь algal, вот пару методов, которые хорошо поставить в категории 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; 
} 
Смежные вопросы