Как замаскировать квадратное изображение в изображение с закругленными углами в iOS? - PullRequest
34 голосов
/ 15 июня 2009

Как можно замаскировать квадратное изображение в изображение с закругленными углами?

Ответы [ 8 ]

67 голосов
/ 15 июня 2009

Вы можете использовать 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 (context); чтобы обрезать его к пути прямоугольника. Теперь любой сделанный рисунок, включая рисунок, будет обрезан до круглой прямоугольной формы.

В качестве примера, предположим, что «изображение» является UIImage, а это в drawRect: method:

CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
addRoundedRectToPath(context, self.frame, 10, 10);
CGContextClip(context);
[image drawInRect:self.frame];
CGContextRestoreGState(context);
34 голосов
/ 20 августа 2009

Вот еще более простой метод, который доступен в 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>
15 голосов
/ 14 декабря 2012

Я понимаю, что это старые новости, но просто немного свести их к минимуму:

Здесь есть два возможных вопроса: (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 напрямую - это то, что делает выбранный ответ, - но тогда вам нужно вручную построить округленный прямоугольный путь Безье из кривых и линий, а также необходимо компенсировать тот факт, что CoreGraphics использует система координат рисования, которая перевернута относительно UIKit.

2 голосов
/ 09 декабря 2011

Смотрите это сообщение - Очень простой ответ

Как установить закругленные углы в изображениях пользовательского интерфейса в 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];
1 голос
/ 08 июля 2014

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

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

0 голосов
/ 29 октября 2014

Построение из водорослей , вот пара методов, которые приятно поместить в категорию 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;
}
0 голосов
/ 16 мая 2012

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

+ (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;
    }
0 голосов
/ 17 февраля 2012

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

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

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...