Закругление двух углов в UIView

83

Некоторое время назад я разместил вопрос об округлении только двух углов обзора и получил отличный ответ, но у меня возникли проблемы с его реализацией. Вот мой метод drawRect:

- (void)drawRect:(CGRect)rect {
    //[super drawRect:rect]; <------Should I uncomment this?
    int radius = 5;
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextBeginPath(context);
    CGContextAddArc(context, rect.origin.x + radius, rect.origin.y + rect.size.height - radius, radius, M_PI, M_PI / 2, 1);
    CGContextAddArc(context, rect.origin.x + rect.size.width - radius, rect.origin.y + rect.size.height - radius, radius, M_PI / 2, 0.0f, 1);
    CGContextClosePath(context);
    CGContextClip(context);
}

Метод вызывается, но, похоже, не влияет на результат просмотра. Есть идеи, почему?

Джамхин
источник

Ответы:

104

CACornerMask, представленный в iOS 11, помогает определять верхний левый, верхний правый, нижний левый, нижний правый угол в слое просмотра. Ниже приведен пример использования.

Здесь я стараюсь закруглить только два верхних угла:

myView.clipsToBounds = true
myView.layer.cornerRadius = 10
myView.layer.maskedCorners = [.layerMinXMinYCorner,.layerMaxXMinYCorner]

К вашему сведению:

Сачин против Сачина
источник
Это похоже на идиоматический способ сделать это сейчас. Хороший улов!
Jumhyn 04
3
Обратите внимание, что ширина / высота вида по-прежнему должна быть как минимум в два раза больше радиуса угла, иначе появляются странные артефакты. например, округление только нижних углов, радиус 20 и высота только 30 приводят к заметно более узкой ячейке (на пиксель или два).
Грэм Перкс
Обратите внимание, что это правильный способ, если ваше представление меняет свой фрейм (возможно, из-за расширяющегося UITextView, как в моем случае - stackoverflow.com/questions/50926215/… ). Если вы установите UIBezierPath, он не будет обновляться автоматически при изменении кадра.
thomers
Отметил, что это доступно только с iOS 11 и вышеif #available(iOS 11.0, *) { }
Три Нго Минь
2
Отличный ответ. Оказывается, установка clipsToBoundsна trueнет необходимости. Вы можете замаскировать углы и добавить тень к слою, когда clipsToBoundsесть false. Пригодился мне.
Au Ris
72


Насколько я знаю, если вам также нужно замаскировать подвиды, вы можете использовать CALayerмаскировку. Это можно сделать двумя способами. Первый вариант немного элегантнее, второй - обходной путь :-), но он также быстрый. Оба основаны на CALayerмаскировке. В прошлом году я использовал оба метода в паре проектов, и надеюсь, вы найдете что-нибудь полезное.

Решение 1

Прежде всего, я создал эту функцию для генерации маски изображения на лету ( UIImage) с нужным мне скругленным углом. Эта функция по существу требует 5 параметров: границы изображения и 4 радиуса угла (верхний левый, верхний правый, нижний левый и нижний правый).


static inline UIImage* MTDContextCreateRoundedMask( CGRect rect, CGFloat radius_tl, CGFloat radius_tr, CGFloat radius_bl, CGFloat radius_br ) {  

    CGContextRef context;
    CGColorSpaceRef colorSpace;

    colorSpace = CGColorSpaceCreateDeviceRGB();

    // create a bitmap graphics context the size of the image
    context = CGBitmapContextCreate( NULL, rect.size.width, rect.size.height, 8, 0, colorSpace, kCGImageAlphaPremultipliedLast );

    // free the rgb colorspace
    CGColorSpaceRelease(colorSpace);    

    if ( context == NULL ) {
        return NULL;
    }

    // cerate mask

    CGFloat minx = CGRectGetMinX( rect ), midx = CGRectGetMidX( rect ), maxx = CGRectGetMaxX( rect );
    CGFloat miny = CGRectGetMinY( rect ), midy = CGRectGetMidY( rect ), maxy = CGRectGetMaxY( rect );

    CGContextBeginPath( context );
    CGContextSetGrayFillColor( context, 1.0, 0.0 );
    CGContextAddRect( context, rect );
    CGContextClosePath( context );
    CGContextDrawPath( context, kCGPathFill );

    CGContextSetGrayFillColor( context, 1.0, 1.0 );
    CGContextBeginPath( context );
    CGContextMoveToPoint( context, minx, midy );
    CGContextAddArcToPoint( context, minx, miny, midx, miny, radius_bl );
    CGContextAddArcToPoint( context, maxx, miny, maxx, midy, radius_br );
    CGContextAddArcToPoint( context, maxx, maxy, midx, maxy, radius_tr );
    CGContextAddArcToPoint( context, minx, maxy, minx, midy, radius_tl );
    CGContextClosePath( context );
    CGContextDrawPath( context, kCGPathFill );

    // Create CGImageRef of the main view bitmap content, and then
    // release that bitmap context
    CGImageRef bitmapContext = CGBitmapContextCreateImage( context );
    CGContextRelease( context );

    // convert the finished resized image to a UIImage 
    UIImage *theImage = [UIImage imageWithCGImage:bitmapContext];
    // image is retained by the property setting above, so we can 
    // release the original
    CGImageRelease(bitmapContext);

    // return the image
    return theImage;
}  

Теперь вам просто нужно несколько строк кода. Я положил вещи в моем ViewController viewDidLoadметод , потому что это быстрее , но вы можете использовать его также в пользовательских UIViewс layoutSubviewsметодом примера.



- (void)viewDidLoad {

    // Create the mask image you need calling the previous function
    UIImage *mask = MTDContextCreateRoundedMask( self.view.bounds, 50.0, 50.0, 0.0, 0.0 );
    // Create a new layer that will work as a mask
    CALayer *layerMask = [CALayer layer];
    layerMask.frame = self.view.bounds;       
    // Put the mask image as content of the layer
    layerMask.contents = (id)mask.CGImage;       
    // set the mask layer as mask of the view layer
    self.view.layer.mask = layerMask;              

    // Add a backaground color just to check if it works
    self.view.backgroundColor = [UIColor redColor];
    // Add a test view to verify the correct mask clipping
    UIView *testView = [[UIView alloc] initWithFrame:CGRectMake( 0.0, 0.0, 50.0, 50.0 )];
    testView.backgroundColor = [UIColor blueColor];
    [self.view addSubview:testView];
    [testView release];

    [super viewDidLoad];
}

Решение 2

Это решение более «грязное». По сути, вы можете создать маскирующий слой с нужным вам закругленным углом (все углы). Затем следует увеличить высоту маскирующего слоя на значение радиуса угла. Таким образом, скругленные нижние углы будут скрыты, и вы сможете увидеть только верхний закругленный угол. Я поставил код только в viewDidLoadметоде , потому что это быстрее , но вы можете использовать его также в пользовательском UIViewс layoutSubviewsметодом примера.

  

- (void)viewDidLoad {

    // set the radius
    CGFloat radius = 50.0;
    // set the mask frame, and increase the height by the 
    // corner radius to hide bottom corners
    CGRect maskFrame = self.view.bounds;
    maskFrame.size.height += radius;
    // create the mask layer
    CALayer *maskLayer = [CALayer layer];
    maskLayer.cornerRadius = radius;
    maskLayer.backgroundColor = [UIColor blackColor].CGColor;
    maskLayer.frame = maskFrame;

    // set the mask
    self.view.layer.mask = maskLayer;

    // Add a backaground color just to check if it works
    self.view.backgroundColor = [UIColor redColor];
    // Add a test view to verify the correct mask clipping
    UIView *testView = [[UIView alloc] initWithFrame:CGRectMake( 0.0, 0.0, 50.0, 50.0 )];
    testView.backgroundColor = [UIColor blueColor];
    [self.view addSubview:testView];
    [testView release];

    [super viewDidLoad];
}

Надеюсь это поможет. Чао!

Ломанф
источник
Наконец то заработало! Спасибо! В чем преимущество одного перед другим?
Jumhyn
В любом случае даже решение CAShapeLayer идеально. Вы можете нарисовать CGPath с помощью UIBezierPath (для которого требуется 3.2+) или просто с помощью методов CGPath (CGPathMoveToPoint, CGPathAddQuadCurveToPoint и т. Д.)
lomanf
1
Как заставить маску автоматически изменять размер после поворота с книжной на альбомную?
chourobin
Не забудьте добавить layer.masksToBounds = YES
Дмитрий Сальников
как сделать так, чтобы он закруглял только верхний и нижний правые углы?
PLOW
69

Расчесывать через несколько ответов и комментариев, я узнал, что использование UIBezierPath bezierPathWithRoundedRectи CAShapeLayerсамый простой и прямой путь. Возможно, это не подходит для очень сложных случаев, но для периодического скругления углов он работает для меня быстро и плавно.

Я создал упрощенный помощник, который устанавливает соответствующий угол в маске:

-(void) setMaskTo:(UIView*)view byRoundingCorners:(UIRectCorner)corners
{
    UIBezierPath* rounded = [UIBezierPath bezierPathWithRoundedRect:view.bounds byRoundingCorners:corners cornerRadii:CGSizeMake(10.0, 10.0)];

    CAShapeLayer* shape = [[CAShapeLayer alloc] init];
    [shape setPath:rounded.CGPath];

    view.layer.mask = shape;
}

Чтобы использовать его, просто вызовите соответствующее перечисление UIRectCorner, например:

[self setMaskTo:self.photoView byRoundingCorners:UIRectCornerTopLeft|UIRectCornerBottomLeft];

Обратите внимание, что для меня я использую его для закругления углов фотографий в сгруппированном UITableViewCell, радиус 10.0 отлично подходит для меня, если нужно просто изменить значение соответствующим образом.

РЕДАКТИРОВАТЬ: просто обратите внимание на предыдущий ответ, очень похожий на этот ( ссылка ). Вы все еще можете использовать этот ответ как дополнительную удобную функцию, если это необходимо.


EDIT: тот же код, что и расширение UIView в Swift 3

extension UIView {
    func maskByRoundingCorners(_ masks:UIRectCorner, withRadii radii:CGSize = CGSize(width: 10, height: 10)) {
        let rounded = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: masks, cornerRadii: radii)

        let shape = CAShapeLayer()
        shape.path = rounded.cgPath

        self.layer.mask = shape
    }
}

Чтобы воспользоваться им, просто позвоните maskByRoundingCornerпо любому UIView:

view.maskByRoundingCorners([.topLeft, .bottomLeft])
PL
источник
Возможно ли это при добавлении границы?
Unome
2
Мне пришлось поместить вызов функции в DispatchQueue.main.async {}, потому что закруглялся только один угол ...
Максим Князев
1
@MaksimKniazev: да, это нужно вызывать из основного (UI) потока. Это правило применяется к любым действиям, касающимся пользовательского интерфейса, они должны вызываться из основного потока, иначе могут произойти некоторые странные вещи.
PL
1
только один угол кажется закругленным. попробовал решение @MaksimKniazev, тоже не сработало.
Gustavo_fringe
У меня та же проблема, что и у @Gustavo_fringe, где верхний правый угол не обрезан / замаскирован до границ внутри (измененного размера) представления xib, пока не знаю, как это исправить.
CyberMew
57

Я не мог вместить все это в комментарий к ответу @lomanf. Я добавляю это как ответ.

Как сказал @lomanf, вам нужно добавить маску слоя, чтобы подслои не отображались за пределами вашего пути. Однако сейчас это сделать намного проще. Пока вы ориентируетесь на iOS 3.2 или выше, вам не нужно создавать изображение с кварцем и устанавливать его в качестве маски. Вы можете просто создать с CAShapeLayerпомощью a UIBezierPathи использовать его как маску.

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

CAShapeLayer *maskLayer = [CAShapeLayer layer];
UIBezierPath *roundedPath = 
  [UIBezierPath bezierPathWithRoundedRect:maskLayer.bounds
                        byRoundingCorners:UIRectCornerTopLeft |
                                          UIRectCornerBottomRight
                              cornerRadii:CGSizeMake(16.f, 16.f)];    
maskLayer.fillColor = [[UIColor whiteColor] CGColor];
maskLayer.backgroundColor = [[UIColor clearColor] CGColor];
maskLayer.path = [roundedPath CGPath];

//Don't add masks to layers already in the hierarchy!
UIView *superview = [self.view superview];
[self.view removeFromSuperview];
self.view.layer.mask = maskLayer;
[superview addSubview:self.view];

Из-за того, как работает рендеринг Core Animation, маскирование - относительно медленная операция. Каждая маска требует дополнительного прохода рендеринга. Так что используйте маски экономно.

Одна из лучших частей этого подхода заключается в том, что вам больше не нужно создавать custom UIViewи override drawRect:. Это должно сделать ваш код проще и, возможно, даже быстрее.

Натан Эрор
источник
Выглядит многообещающе, но вид не появляется. Есть идеи, почему?
Jumhyn
10
Вы используете maskLayer.bounds для определения размера UIBezierPath, но значение границ - CGRectZero. Вам нужно добавить вторую строку кода (сразу после инициализации CAShapeLayer), например, maskLayer.frame = self.view.bounds;
lomanf
1
Да, ты прав. Я извлек этот код из другого примера, где слой формы уже существовал. Прости за это.
Натан Эрор
Работает отлично! Добавление maskLayer.frame = self.view.bounds, как указано выше, делает работу make. В противном случае просмотры не отображаются.
Даниэль Рибейро,
+1 Это неплохо работает. На самом деле я думаю, что предпочитаю этот метод решению lomanf # 2. Этот метод легко позволяет вам добавлять дуги к противоположным углам (например: верхний правый + нижний левый), и он, безусловно, короче, чем первое решение lomanf. Отличный код Натан!
FreeAsInBeer
30

Я взял пример Натана и создал категорию, UIViewпозволяющую придерживаться принципов DRY. Без дальнейших церемоний:

UIView + Roundify.h

#import <UIKit/UIKit.h>

@interface UIView (Roundify)

-(void)addRoundedCorners:(UIRectCorner)corners withRadii:(CGSize)radii;
-(CALayer*)maskForRoundedCorners:(UIRectCorner)corners withRadii:(CGSize)radii;

@end

UIView + Roundify.m

#import "UIView+Roundify.h"

@implementation UIView (Roundify)

-(void)addRoundedCorners:(UIRectCorner)corners withRadii:(CGSize)radii {
    CALayer *tMaskLayer = [self maskForRoundedCorners:corners withRadii:radii];
    self.layer.mask = tMaskLayer;
}

-(CALayer*)maskForRoundedCorners:(UIRectCorner)corners withRadii:(CGSize)radii {
    CAShapeLayer *maskLayer = [CAShapeLayer layer];
    maskLayer.frame = self.bounds;

    UIBezierPath *roundedPath = [UIBezierPath bezierPathWithRoundedRect:
        maskLayer.bounds byRoundingCorners:corners cornerRadii:radii];
    maskLayer.fillColor = [[UIColor whiteColor] CGColor];
    maskLayer.backgroundColor = [[UIColor clearColor] CGColor];
    maskLayer.path = [roundedPath CGPath];

    return maskLayer;
}

@end

Звонить:

[myView addRoundedCorners:UIRectCornerBottomLeft | UIRectCornerBottomRight
                withRadii:CGSizeMake(20.0f, 20.0f)];
FreeAsInBeer
источник
2
Не забудьте импортировать <QuartzCore / QuatzCore.h> в файл .m, а также добавить QuartzCore.framework в проект
DEzra
+1 Отличный материал, один вопрос, какова цель удаления / чтения представления в его супервизоре?
eladleb
@eladleb: Базовый код здесь был от Натана, я просто немного его оптимизировал. Из проведенного мной исследования я не могу найти вескую причину для удаления представления перед применением маски слоя. Поэтому я считаю, что этот код можно не указывать.
FreeAsInBeer
@FreeAsInBeer - Я согласен, тогда я бы проголосовал за его удаление, это фактически меняет z-порядок представления и может создать больше проблем ..
eladleb
Решена проблема, с которой я столкнулся с добавлением закругленных углов в TableView: я добавил заголовок, закругленные верхние углы и добавил нижний колонтитул с закругленными нижними углами. Благодарю.
nightfix зафиксирован
24

Чтобы немного расширить ответ PL, я переписал метод так, чтобы он не округлял определенные объекты, например UIButtonправильно

- (void)setMaskTo:(id)sender byRoundingCorners:(UIRectCorner)corners withCornerRadii:(CGSize)radii
{
    // UIButton requires this
    [sender layer].cornerRadius = 0.0;

    UIBezierPath *shapePath = [UIBezierPath bezierPathWithRoundedRect:[sender bounds]
                                                byRoundingCorners:corners
                                                cornerRadii:radii];

    CAShapeLayer *newCornerLayer = [CAShapeLayer layer];
    newCornerLayer.frame = [sender bounds];
    newCornerLayer.path = shapePath.CGPath;
    [sender layer].mask = newCornerLayer;
}

И назови это

[self setMaskTo:self.continueButton byRoundingCorners:UIRectCornerBottomLeft|UIRectCornerBottomRight withCornerRadii:CGSizeMake(3.0, 3.0)];
Джош Вальдивьесо
источник
12

Если вы хотите сделать это в Swift, вы можете использовать расширение UIView. Таким образом, все подклассы смогут использовать следующий метод:

import QuartzCore

extension UIView {
    func roundCorner(corners: UIRectCorner, radius: CGFloat) {
        let maskPath = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
        let maskLayer = CAShapeLayer()
        maskLayer.frame = bounds
        maskLayer.path = maskPath.CGPath
        layer.mask = maskLayer
    }
}    

Пример использования:

self.anImageView.roundCorner(.topRight, radius: 10)
Кевин Делорд
источник
3

Расширяя принятый ответ, добавим к нему обратную совместимость. До iOS 11 view.layer.maskedCorners недоступен. Итак, мы можем сделать это

if #available(iOS 11.0, *) {
    myView.layer.maskedCorners = [.layerMinXMinYCorner,.layerMaxXMinYCorner]
} else {
    myView.maskByRoundingCorners([.topLeft, .topRight])
}

extension UIView{
    func maskByRoundingCorners(_ masks:UIRectCorner, withRadii radii:CGSize = CGSize(width: 10, height: 10)) {
        let rounded = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: masks, cornerRadii: radii)

        let shape = CAShapeLayer()
        shape.path = rounded.cgPath

        self.layer.mask = shape
    }
}

Мы написали maskByRoundingCorners как расширение UIView, чтобы улучшить повторное использование кода.

Благодарности @SachinVsSachin и @PL :) Я объединил их коды, чтобы сделать это лучше.

Ризван Ахмед
источник
2
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(5, 5, self.bounds.size.width-10, self.bounds.size.height-10)
                                               byRoundingCorners:UIRectCornerAllCorners
                                                     cornerRadii:CGSizeMake(12.0, 12.0)];

измените "AllCorners" в соответствии с вашими потребностями.

Уманг
источник
так что вам нужно сделать это в UIView или это можно сделать в UIViewController? Что вы будете делать с UIBezierPath после его создания? Благодарю.
StoneBreaker
2

Все представленные решения достигают цели. Но UIConstraintsиногда это может взорвать.

Например, нужно скруглить нижние углы. Если ограничение высоты или нижнего интервала установлено на UIView, который необходимо округлить, фрагменты кода, которые округляют углы, необходимо переместить в viewDidLayoutSubviewsметод.

Выделение:

UIBezierPath *maskPath = [UIBezierPath
    bezierPathWithRoundedRect:roundedView.bounds byRoundingCorners:
    (UIRectCornerTopRight | UIRectCornerBottomRight) cornerRadii:CGSizeMake(16.0, 16.0)];

Приведенный выше фрагмент кода будет закруглен только в правом верхнем углу, если этот код установлен viewDidLoad. Потому roundedView.boundsчто он изменится после обновления ограничений UIView.

хасан
источник
1

Создайте маску и установите ее на слой представления.

Стив Риггинс
источник
Как мне это сделать? Я немного неуверен в том, что касается управления представлениями нижнего уровня.
Jumhyn
1
stackoverflow.com/questions/2264083/… может вам помочь
Стив Риггинс,
1
Рад видеть, что мой ответ до сих пор помогает людям!
Nevan King 05
1

Начиная со своего кода, вы можете использовать что-то вроде фрагмента ниже.

Я не уверен, что вам нужен именно такой результат. Также стоит отметить, что если / когда система снова вызывает drawRect: с запросом на перерисовку только части прямоугольника, это будет вести себя очень странно. Подход Невана , упомянутый выше, может быть лучшим выходом.

 // make sure the view's background is set to [UIColor clearColor]
- (void)drawRect:(CGRect)rect
{
    CGFloat radius = 10.0;
    CGContextRef context = UIGraphicsGetCurrentContext();

    CGContextTranslateCTM(context, rect.size.width/2, rect.size.height/2);
    CGContextRotateCTM(context, M_PI); // rotate so image appears right way up
    CGContextTranslateCTM(context, -rect.size.width/2, -rect.size.height/2);

    CGContextBeginPath(context);

    CGContextMoveToPoint(context, rect.origin.x, rect.origin.y);
    CGContextAddArc(context, rect.origin.x + radius, rect.origin.y + rect.size.height - radius, radius, M_PI, M_PI / 2, 1);
    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);
    CGContextClip(context); 

    // now do your drawing, e.g. draw an image
    CGImageRef anImage = [[UIImage imageNamed:@"image.jpg"] CGImage];
    CGContextDrawImage(context, rect, anImage);    
}
Наискось
источник
Я разработал вид с закругленными углами, но не могу заставить его обрезать ни одно из его подвидов. Если я помещаю вид с квадратными углами на краю своего вида, он все равно закрывает закругленные углы своего супервизора. Есть идеи, почему это происходит?
Jumhyn
Поскольку обрезка -drawRect:влияет только на вид, который вы рисуете. Его подвиды отрисовываются независимо после завершения рисования.
Джонатан Гринспан,
1

Слегка хакерский, но относительно простой (без подклассов, маскирования и т. Д.) Способ - иметь два UIView. Оба с clipToBounds = YES. Задайте закругленные углы на дочернем виде, затем поместите его в родительский вид, чтобы углы, которые вы хотите прямые, были обрезаны.

UIView* parent = [[UIView alloc] initWithFrame:CGRectMake(10,10,100,100)];
parent.clipsToBounds = YES;

UIView* child = [[UIView alloc] new];
child.clipsToBounds = YES;
child.layer.cornerRadius = 3.0f;
child.backgroundColor = [UIColor redColor];
child.frame = CGRectOffset(parent.bounds, +4, -4);


[parent addSubView:child];

Не подходит для случая, когда нужно скруглить два противоположных по диагонали угла.

Уильям Деннисс
источник
1

Путь Безье - это ответ, если вам нужен дополнительный код, который работал у меня: https://stackoverflow.com/a/13163693/936957

UIBezierPath *maskPath;
maskPath = [UIBezierPath bezierPathWithRoundedRect:_backgroundImageView.bounds 
                                 byRoundingCorners:(UIRectCornerBottomLeft | UIRectCornerBottomRight) 
                                       cornerRadii:CGSizeMake(3.0, 3.0)];

CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
maskLayer.frame = self.bounds;
maskLayer.path = maskPath.CGPath;
_backgroundImageView.layer.mask = maskLayer;
[maskLayer release];
Юнус Недим Мехел
источник
1

Решение UIBezierPath.

- (void) drawRect:(CGRect)rect {

    [super drawRect:rect];

    //Create shape which we will draw. 
    CGRect rectangle = CGRectMake(2, 
                                  2, 
                                  rect.size.width - 4,
                                  rect.size.height - 4);

    //Create BezierPath with round corners
    UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:rectangle 
                                                   byRoundingCorners:UIRectCornerTopLeft | UIRectCornerTopRight 
                                                         cornerRadii:CGSizeMake(10.0, 10.0)];

    //Set path width
    [maskPath setLineWidth:2];

    //Set color
    [[UIColor redColor] setStroke];

    //Draw BezierPath to see it
    [maskPath stroke];
}
Алексей Бондарчук
источник
0

Это может работать, только если некоторые вещи настроены правильно:

  1. clipsToBounds должно быть установлено в YES
  2. непрозрачный должен быть НЕТ
  3. backgroundColor должен быть clearColor (я не совсем уверен в этом)
  4. contentMode должен иметь значение «UIContentModeRedraw», поскольку drawRect не вызывается часто, если это не так.
  5. [super drawRect: rect] должен вызываться после CGContextClip
  6. Ваше представление может не содержать произвольных подвидов (не уверен в этом)
  7. Обязательно установите "needsDisplay:" хотя бы один раз, чтобы активировать отрисовку.
Dunkelstern
источник
0

Я понимаю, что вы пытаетесь округлить два верхних угла UITableView, но по какой-то причине я обнаружил, что лучшим решением является использование:

self.tableView.layer.cornerRadius = 10;

Программно он должен закруглить все четыре угла, но по какой-то причине округляет только два верхних. ** Пожалуйста, посмотрите снимок экрана ниже, чтобы увидеть эффект от кода, который я написал выше.

Надеюсь, это поможет!

введите описание изображения здесь

Адам Купер
источник
1
Если он не закругляет все углы, UITableViewто в другом месте должен быть код, который заставляет UITableViewне иметь закругленных углов внизу, или, может быть, даже UIViewили UILabel, закрывающий нижнюю часть UITableView.
Джош Вальдивьесо,
-1

Вам, вероятно, придется обрезаться до предела. Добавьте строку

self.clipsToBounds = YES

где-нибудь в коде, чтобы установить это свойство.

Нед
источник