Обведіть два кути в 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]

FYI Посилання:


Це виглядає ідіоматичним способом зробити це зараз. Хороший улов!
Джумгін,

3
Зверніть увагу, що ширина / висота вигляду все одно повинна бути принаймні вдвічі більше радіуса кута, або з’являються дивні артефакти наприклад, заокруглення лише нижніх кутів, радіус 20 і висота лише 30 призводять до помітно вужчої комірки (на піксель або два).
Грем Перкс

Зверніть увагу, що це правильний спосіб, якщо ваш вигляд змінює свій фрейм (можливо через розширення UITextView, як у моєму випадку - stackoverflow.com/questions/50926215/… ). Якщо ви встановите UIBezierPath, він не оновлюватиметься автоматично при зміні кадру.
Томерс

Відзначено, що він доступний лише для iOS 11 і новіших if #available(iOS 11.0, *) { }
Tri Ngo Minh

2
Чудова відповідь. Виявляється, установка clipsToBoundsна trueнемає необхідності. Ви можете замаскувати кути і додати тінь до шару, коли він clipsToBoundsє false. Пригодився мені.
Au Ris

72


наскільки мені відомо, якщо вам також потрібно замаскувати підпрограми, ви можете використати CALayerмаскування. Є 2 способи зробити це. Перший трохи елегантніший, другий - обхідний шлях :-) але це також швидко. Обидва засновані на 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];
}

Сподіваюся, це допомагає. Цао!


Нарешті запрацював! Дуже дякую! У чому перевага одного над іншим?
Джумін

У будь-якому випадку навіть рішення CAShapeLayer є ідеальним. Ви можете намалювати CGPath, використовуючи UIBezierPath (для цього потрібно 3.2+), або просто за допомогою методів CGPath (CGPathMoveToPoint, CGPathAddQuadCurveToPoint тощо)
lomanf

1
Як змусити маску автоматично змінити розмір після повороту з портретного на альбомний?
chourobin

Не забудьте додати layer.masksToBounds = ТАК
Дмитро Сальников

як це зробити, щоб заокруглити лише верхній і нижній правий кути?
ПЛУГ

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

Чи можливо це при додаванні рамки?
Unome

2
Мені довелося помістити виклик функції в DispatchQueue.main.async {}, тому що лише один кут закруглився ...
Максим Князєв

1
@MaksimKniazev так, це потрібно викликати з основного потоку (UI). Це правило застосовується до будь-яких дій, що стосуються інтерфейсу користувача, їх потрібно викликати з основного потоку, інакше можуть статися якісь дивні речі.
PL

1
тільки один кут здається круглим. спробував @MaksimKniazev рішення теж не спрацювало.
Gustavo_fringe

У мене така сама проблема, як @Gustavo_fringe, де правий верхній кут не обрізаний / маскований, щоб обмежувати всередині (змінено розмір) представлення xib, я ще не знаю, як це виправити.
CyberMew

57

Я не міг вмістити це все у коментарі до відповіді @ lomanf. Тож я додаю це як відповідь.

Як сказав @lomanf, вам потрібно додати маску шару, щоб запобігти малюванню підшарів поза межами вашого шляху. Однак зараз це набагато простіше. Поки ви націлюєтесь на iOS 3.2 або новішої версії, вам не потрібно створювати зображення за допомогою кварцу та встановлювати його як маску. Ви можете просто створити за CAShapeLayerдопомогою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, маскування є відносно повільною операцією. Кожна маска вимагає додаткового пропуску. Тому використовуйте маски економно.

Однією з найкращих частин цього підходу є те, що вам більше не потрібно створювати власні UIViewта замінювати drawRect:. Це має зробити ваш код простішим і, можливо, навіть швидшим.


Здається багатообіцяючим, але вигляд не з’являється. Будь-які ідеї чому?
Джумін

10
Ви використовуєте maskLayer.bounds для розміру UIBezierPath, але значення меж - CGRectZero. Вам потрібно додати другий рядок коду (негайно після ініціалізації CAShapeLayer), наприклад maskLayer.frame = self.view.bounds;
lomanf

1
Так, ви праві. Я витягнув цей код з іншого прикладу, де шар фігури вже існував. Вибач за це.
Натан Ерор,

Це працює perfectl! Додавання maskLayer.frame = self.view.bounds, як зазначено вище, make - це робота. Інакше погляди не відображаються.
Даніель Рібейро,

+1 Це працює досить добре. Насправді, я вважаю, що віддаю перевагу цьому методу, ніж рішення №2 Ломанфа. Цей метод дозволяє легко додавати дуги до протилежних кутів (наприклад: вгорі праворуч + знизу вліво), і він, безумовно, коротший за перше рішення lomanf. Чудовий код Натане!
FreeAsInBeer

30

Я взяв приклад Натана і створив категорію UIView щоб дозволити дотримуватися принципів СУХОГО. Без зайвого галасу:

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

2
Не забудьте імпортувати <QuartzCore / QuatzCore.h> у файл .m, а також додати QuartzCore.framework до проекту
DEzra

+1 Чудовий матеріал, хоча одне питання, яка мета видалення / повторного додавання подання до його суперпрегляду?
eladleb

@eladleb: Основний код тут був від Натана, я просто трохи його оптимізував. З мого проведеного дослідження я не можу знайти поважної причини для видалення подання перед застосуванням маски шару. Тому я вважаю, що безпечно опустити цей код.
FreeAsInBeer

@FreeAsInBeer - я згоден, тоді я би проголосував за його видалення, це насправді змінює подання z-порядку і може створити більше проблем ..
eladleb

Вирішив проблему, з якою я стикався з додаванням закруглених кутів до TableView: я додав верхній колонтитул, закруглені кути перекриття та додав нижній колонтитул із закругленими нижніми кутами. Дякую.
виправлено ніч

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
Радий бачити, що моя відповідь все ще допомагає людям!
неван-король

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

Я розробив подання із закругленими кутами, але не можу змусити його відсікати будь-який із своїх підпрозорів. Якщо я розміщу подання з квадратними кутами на краю свого перегляду, він все одно закриває закруглені кути свого супервигляду. Будь-яка ідея, чому це відбувається?
Джумін

Оскільки відсікання -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 має бути встановлено ТАК
  2. непрозорий повинен бути НІ
  3. backgroundColor повинен бути "clearColor" (я не впевнений у цьому)
  4. contentMode має бути "UIContentModeRedraw", оскільки drawRect не часто викликається, якщо це не так
  5. [super drawRect: rect] потрібно викликати після CGContextClip
  6. Ваш подання може не містити довільних підпроектів (не впевнений у цьому)
  7. Обов’язково принаймні один раз встановіть "needsDisplay:", щоб активувати ваш витяг

0

Я розумію, що ви намагаєтеся закруглити два верхні кути UITableView, але чомусь я виявив, що найкращим рішенням є використання:

self.tableView.layer.cornerRadius = 10;

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

Сподіваюся, це допоможе!

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


1
Якщо це не округлення всіх кутів, UITableViewтоді в іншому місці повинен бути код, який робить, UITableViewщо внизу немає закруглених кутів, або, можливо, навіть, UIViewабо UILabelякий охоплює нижню частину UITableView.
Джош Вальдівієсо,

-1

Ймовірно, вам доведеться обмежуватися. Додайте рядок

self.clipsToBounds = YES

десь у коді, щоб встановити цю властивість.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.