Я использовал ответ в разделе Как создать UILabel с закругленными углами на iPhone? и код из раздела Как выполняется прямоугольное изображение с закругленными углами и прозрачность на iphone? сделать этот код.
Затем я понял, что ответил на неправильный вопрос (дал округленный UILabel вместо UIImage), поэтому я использовал этот код, чтобы изменить его:
http://discussions.apple.com/thread.jspa?threadID=1683876
Создайте проект iPhone с шаблоном View. В контроллере представления добавьте это:
- (void)viewDidLoad
{
CGRect rect = CGRectMake(10, 10, 200, 100);
MyView *myView = [[MyView alloc] initWithFrame:rect];
[self.view addSubview:myView];
[super viewDidLoad];
}
MyView
это просто UIImageView
подкласс:
@interface MyView : UIImageView
{
}
Я никогда раньше не использовал графические контексты, но мне удалось скомпилировать этот код. Отсутствует код для двух углов. Если вы читаете код, вы можете увидеть, как я это реализовал (удалив некоторые из CGContextAddArc
вызовов и удалив некоторые значения радиуса в коде. Код для всех углов есть, поэтому используйте его как отправную точку и удалите части, которые создают углы, которые вам не нужны. Обратите внимание, что вы можете сделать прямоугольники с 2 или 3 закругленными углами, если хотите.
Код не идеален, но я уверен, что вы сможете его немного привести в порядок.
static void addRoundedRectToPath(CGContextRef context, CGRect rect, float radius, int roundedCornerPosition)
{
// all corners rounded
// CGContextMoveToPoint(context, rect.origin.x, rect.origin.y + radius);
// CGContextAddLineToPoint(context, rect.origin.x, rect.origin.y + rect.size.height - radius);
// CGContextAddArc(context, rect.origin.x + radius, rect.origin.y + rect.size.height - radius,
// radius, M_PI / 4, M_PI / 2, 1);
// CGContextAddLineToPoint(context, rect.origin.x + rect.size.width - radius,
// rect.origin.y + rect.size.height);
// CGContextAddArc(context, rect.origin.x + rect.size.width - radius,
// rect.origin.y + rect.size.height - radius, radius, M_PI / 2, 0.0f, 1);
// CGContextAddLineToPoint(context, rect.origin.x + rect.size.width, rect.origin.y + radius);
// CGContextAddArc(context, rect.origin.x + rect.size.width - radius, rect.origin.y + radius,
// radius, 0.0f, -M_PI / 2, 1);
// CGContextAddLineToPoint(context, rect.origin.x + radius, rect.origin.y);
// CGContextAddArc(context, rect.origin.x + radius, rect.origin.y + radius, radius,
// -M_PI / 2, M_PI, 1);
// top left
if (roundedCornerPosition == 1) {
CGContextMoveToPoint(context, rect.origin.x, rect.origin.y + radius);
CGContextAddLineToPoint(context, rect.origin.x, rect.origin.y + rect.size.height - radius);
CGContextAddArc(context, rect.origin.x + radius, rect.origin.y + rect.size.height - radius,
radius, M_PI / 4, M_PI / 2, 1);
CGContextAddLineToPoint(context, rect.origin.x + rect.size.width,
rect.origin.y + rect.size.height);
CGContextAddLineToPoint(context, rect.origin.x + rect.size.width, rect.origin.y);
CGContextAddLineToPoint(context, rect.origin.x, rect.origin.y);
}
// bottom left
if (roundedCornerPosition == 2) {
CGContextMoveToPoint(context, rect.origin.x, rect.origin.y);
CGContextAddLineToPoint(context, rect.origin.x, rect.origin.y + rect.size.height);
CGContextAddLineToPoint(context, rect.origin.x + rect.size.width,
rect.origin.y + rect.size.height);
CGContextAddLineToPoint(context, rect.origin.x + rect.size.width, rect.origin.y);
CGContextAddLineToPoint(context, rect.origin.x + radius, rect.origin.y);
CGContextAddArc(context, rect.origin.x + radius, rect.origin.y + radius, radius,
-M_PI / 2, M_PI, 1);
}
// add the other corners here
CGContextClosePath(context);
CGContextRestoreGState(context);
}
-(UIImage *)setImage
{
UIImage *img = [UIImage imageNamed:@"my_image.png"];
int w = img.size.width;
int h = img.size.height;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(NULL, w, h, 8, 4 * w, colorSpace, kCGImageAlphaPremultipliedFirst);
CGContextBeginPath(context);
CGRect rect = CGRectMake(0, 0, w, h);
addRoundedRectToPath(context, rect, 50, 1);
CGContextClosePath(context);
CGContextClip(context);
CGContextDrawImage(context, rect, img.CGImage);
CGImageRef imageMasked = CGBitmapContextCreateImage(context);
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
[img release];
return [UIImage imageWithCGImage:imageMasked];
}
альтернативный текст http://nevan.net/skitch/skitched-20100224-092237.png
Не забывайте, что вам понадобится фреймворк QuartzCore, чтобы это работало.
Начиная с iOS 3.2, вы можете использовать функциональность
UIBezierPath
s для создания нестандартного прямоугольника с закругленными углами (где скругляются только углы, которые вы укажете). Затем вы можете использовать это как путь к aCAShapeLayer
и использовать это как маску для слоя вашего представления:И это все - не нужно возиться с ручным определением фигур в Core Graphics или создавать маскирующие изображения в Photoshop. Слой даже не нужно делать недействительным. Применение закругленного угла или изменение нового угла так же просто, как определение нового угла
UIBezierPath
и использование его вCGPath
качестве пути слоя маски.corners
ПараметрbezierPathWithRoundedRect:byRoundingCorners:cornerRadii:
метода представляет собой битовую маску, и поэтому несколько углы могут быть скруглены по ORing их вместе.РЕДАКТИРОВАТЬ: добавление тени
Если вы хотите добавить к этому тень, потребуется немного больше работы.
Поскольку "
imageView.layer.mask = maskLayer
" применяет маску, тень обычно не отображается вне ее. Уловка состоит в том, чтобы использовать прозрачное представление, а затем добавить два подслоя (CALayer
и) к слою представления:shadowLayer
иroundedLayer
. Оба должны использовать расширениеUIBezierPath
. Изображение добавляется как содержимоеroundedLayer
.источник
Я использовал этот код во многих местах своего кода, и он работает на 100% правильно. Вы можете изменить любой уголок, изменив одно свойство «byRoundingCorners: UIRectCornerBottomLeft»
источник
UITableView
-подпредставлениях (например,UITableViewCell
s илиUITableViewHeaderFooterView
s) это приводит к плохой плавности при прокрутке . Другой подход для такого использования - это решение с более высокой производительностью (оно добавляет угловой радиус ко всем углам). Чтобы «показать» только определенные закругленные углы (например, верхний и нижний правые углы), я добавил подпредставление с отрицательным значением на немframe.origin.x
и назначил угловой радиус его слою. Если кто-то нашел лучшее решение, мне интересно.В iOS 11 теперь мы можем закруглить только некоторые углы
источник
Расширение CALayer с синтаксисом Swift 3+
Его можно использовать как:
источник
Пример Стюарта для закругления определенных углов отлично работает. Если вы хотите скруглить несколько углов, например верхний левый и правый, вот как это сделать.
источник
UITableView
-подпредставлениях (например,UITableViewCell
s илиUITableViewHeaderFooterView
s) это приводит к плохой плавности при прокрутке . Другой подход для такого использования - это решение с более высокой производительностью (оно добавляет угловой радиус ко всем углам). Чтобы «показать» только определенные закругленные углы (например, верхний и нижний правые углы), я добавил подпредставление с отрицательным значением на немframe.origin.x
и назначил угловой радиус его слою. Если кто-то нашел лучшее решение, мне интересно.Спасибо, что поделился. Здесь я хотел бы поделиться решением для Swift 2.0 для получения дополнительной информации по этому вопросу. (чтобы соответствовать протоколу UIRectCorner)
источник
есть более простой и быстрый ответ, который может работать в зависимости от ваших потребностей, а также работать с тенями. вы можете установить для maskToBounds на суперслое значение true и сместить дочерние слои так, чтобы 2 их угла выходили за границы суперслоя, эффективно срезая закругленные углы с двух сторон.
конечно, это работает только тогда, когда вы хотите иметь только 2 закругленных угла с одной стороны, и содержимое слоя выглядит одинаково, когда вы отрезаете несколько пикселей с одной стороны. отлично подходит для гистограмм, закругленных только в верхней части.
источник
См. Этот связанный вопрос . Вы должны сделать свой собственный прямоугольник к
CGPath
с некоторыми закругленными углами, добавьтеCGPath
к вашему ,CGContext
а затем клип к нему с помощьюCGContextClip
.Вы также можете нарисовать закругленный прямоугольник с альфа-значениями для изображения, а затем использовать это изображение для создания нового слоя, который вы установили в качестве
mask
свойства вашего слоя ( см. Документацию Apple ).источник
На полдесятилетия позже, но я думаю, что нынешний способ, которым люди это делают, не на 100% верен. Многие люди сталкивались с проблемой того, что использование метода UIBezierPath + CAShapeLayer мешает автоматическому макету, особенно когда он установлен в раскадровке. По этому поводу нет ответов, поэтому я решил добавить свой.
Есть очень простой способ обойти это: нарисуйте закругленные углы в
drawRect(rect: CGRect)
функции.Например, если мне нужны закругленные верхние углы для UIView, я бы создал подкласс UIView, а затем использовал бы этот подкласс там, где это необходимо.
Это лучший способ справиться с проблемой, который не требует времени на адаптацию.
источник
drawRect(_:)
если вы выполняете пользовательский рисунок в своем представлении (например, с помощью Core Graphics), иначе даже пустая реализация может повлиять на производительность. Создавать новый слой маски каждый раз тоже нет необходимости. Все, что вам действительно нужно сделать, это обновитьpath
свойство маскирующего слоя при изменении границ представления, и место для этого находится в пределах переопределенияlayoutSubviews()
метода.Скругление только некоторых углов не будет хорошо работать с автоматическим изменением размера или автоматической компоновкой.
Таким образом, другой вариант - использовать обычный
cornerRadius
и скрыть углы, которые вы не хотите, под другим представлением или за пределами его границ супервизора, убедившись, что он настроен на обрезку его содержимого.источник
Чтобы добавить к ответу и дополнению , я создал простой, многоразовый
UIView
в Swift. В зависимости от вашего варианта использования вы можете захотеть внести изменения (избегать создания объектов в каждом макете и т. Д.), Но я хотел, чтобы это было как можно проще. Расширение позволяет вамUIImageView
проще применить это к другим представлениям (например ), если вам не нравится создание подклассов.Вот как бы вы применили его к
UIViewController
:источник
Завершая ответ Стюарта, вы можете использовать метод закругления угла следующим образом:
Итак, чтобы применить скругление угла, вы просто выполните:
источник
Я предлагаю определить маску слоя. Сама маска должна быть
CAShapeLayer
объектом с выделенным путем. Вы можете использовать следующее расширение UIView (Swift 4.2):источник