UIBezierPath не рисует закругленные нижние углы

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

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

bezierPath = [UIBezierPath bezierPathWithRoundedRect:btnView.bounds
                                       byRoundingCorners:UIRectCornerAllCorners
                                             cornerRadii:radius];
CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
    maskLayer.frame = btnView.bounds;
    maskLayer.path = bezierPath.CGPath;
    btnView.layer.mask = maskLayer;

Проблема в том, что он не работает для нижних углов. Если я использую UIRectCornerBottomLeft, ничего не происходит, если я использую UIRectCornerAllCorners, закругляются только верхние углы.

РЕДАКТИРОВАТЬ: я не использую layer.cornerRadius, потому что я просто хочу закруглить нижние углы.

Оказалось, что у меня нет проблем, если я уберу UIViewAutoresizingFlexibleHeight маску автоматического изменения размера из моего представления. Но я хотел бы использовать маску автоматического изменения размера. Возможно ли, если да, то как?

Я уже пробовал устанавливать autoresizingMask до и после установки маски слоя. Не повезло!


person Mert    schedule 23.04.2013    source источник
comment
почему бы вам просто не использовать layer.cornerradius?   -  person Lithu T.V    schedule 23.04.2013
comment
правильно @LithuT.V я опубликую этот ответ, прежде чем опубликовать этот комментарий :)   -  person Paras Joshi    schedule 23.04.2013
comment
@LithuT.V Я обновил свой вопрос.   -  person Mert    schedule 23.04.2013
comment
@ParasJoshi: Да, я разместил комментарий, и в то же время вы поместили его в качестве ответа.   -  person Lithu T.V    schedule 23.04.2013


Ответы (9)


У меня только что была аналогичная проблема, на решение которой ушли часы - ответ был очень простым: переместите мой код из viewDidLoad в viewDidLayoutSubviews: это первый метод, вызываемый после завершения автомакета.... поэтому я подозреваю, что у меня было 4 закругленных угла. но почему-то они были за краем экрана.

person Oliver Dungey    schedule 25.06.2014
comment
В ротации viewDidLayoutSubviews не вызывается и не подходит для автомакета. - person Vahid; 08.11.2016

Пока я не получу другой ответ, если можно использовать autoresizingMask с UIBezierPath, я говорю НЕТ и отмечаю как правильный ответ.

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

person Mert    schedule 23.04.2013
comment
просто попробуйте свой код в dispatch_async(dispatch_get_main_queue(), ^{ // сделать закругленный угол }); - person hzandi; 14.11.2016
comment
любая причина для этого? Я сделал это в viewDidLoad() и viewDidLayoutSubviews(), но нигде это не сработало. Это сработало, когда я применил dispatch_main... это кажется странным. любая причина для этого? - person Paresh Thakor; 30.10.2020

затем вместо этого используйте приведенный ниже код для закругленных углов...

btnView.layer.cornerRadius = 8.0;

просто импортируйте QuartzCore/QuartzCore.h в свой .m, как показано ниже...

#import <QuartzCore/QuartzCore.h>

ОБНОВЛЕНИЕ:

Для этого вы можете использовать различные RoundingCorners свойства UIBezierPath lik ниже....

Например: UIRectCornerBottomLeft,UIRectCornerBottomRight,UIRectCornerTopLeft,UIRectCornerTopRight и UIRectCornerAllCorners.

UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect: btnView.bounds
                                               byRoundingCorners:UIRectCornerBottomLeft
                                                     cornerRadii:CGSizeMake(10.0, 10.0)];

CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.frame = btnView.bounds;
maskLayer.path = maskPath.CGPath;
btnView.layer.mask = maskLayer;
[btnView setNeedsDisplay];
person Paras Joshi    schedule 23.04.2013
comment
@Mert также смотрите эту ссылку со многими ответами. выравнивает только некоторые углы, как"> stackoverflow.com/questions/2264083/ - person Paras Joshi; 23.04.2013
comment
Да, я это знаю и использую, но для нижних углов не работает из-за autoresizingMask. - person Mert; 23.04.2013
comment
@Mert видит, что это ответы такие же, как и ваша проблема. com/questions/4847163/round-two-corners-in-uiview :) - person Paras Joshi; 23.04.2013

Решение:

-(void)roundCorners:(UIRectCorner)corner radius:(float)radius
{   
    _cornerRadius = radius;
    _corner = corner;
    [self setNeedsDisplay];
}

- (void)drawRect:(CGRect)rect {
    // Drawing code
    [super drawRect:rect];

    UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:_corner cornerRadii:CGSizeMake(_cornerRadius, _cornerRadius)];

    CAShapeLayer *maskLayer = [CAShapeLayer layer];
    maskLayer.frame = self.bounds;
    maskLayer.path = maskPath.CGPath;

    self.layer.mask = maskLayer;
}
person Gennadiy Ryabkin    schedule 28.01.2015

Я думаю, вы должны использовать

bezierPath.lineCapStyle = CGLineCap.Round
person wkwyatt    schedule 12.07.2016

вы можете использовать view.layer.cornerRadius, чтобы установить закругленные углы.

Отредактировано: используйте следующее

 layer.mask = MTDContextCreateRoundedMask(layer.bounds, topleftRadius, topRightRadius, bottomLeftRadius,bottomRightRadius);

Это поддерживаемый метод.

static inline UIImage* MTDContextCreateRoundedMask(CGRect rect, CGFloat radius_tl, CGFloat radius_tr, CGFloat radius_bl, CGFloat radius_br)
{
    CGContextRef context;
    CGColorSpaceRef colorSpace;

    colorSpace = CGColorSpaceCreateDeviceRGB();

    context = CGBitmapContextCreate( NULL, rect.size.width, rect.size.height, 8, 0, colorSpace, kCGImageAlphaPremultipliedLast );

    CGColorSpaceRelease(colorSpace);

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


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

    CGImageRef bitmapContext = CGBitmapContextCreateImage( context );
    CGContextRelease( context );

    UIImage *theImage = [UIImage imageWithCGImage:bitmapContext];
    CGImageRelease(bitmapContext);

    return theImage.layer.mask;
}
person AMohan    schedule 23.04.2013
comment
Я получаю неявное объявление функции MTDContextCreateRoundedMask неверно. И я не смог найти ни одного документа о функции, это частный API? - person Mert; 23.04.2013
comment
Я получаю предупреждение о несовместимых типах указателей, назначенных CALayer * из UIImage *, и если я запускаю его, происходит сбой с плохим доступом. - person Mert; 23.04.2013

Пришлось менять углы обзора. не работал с нижними углами в viewDidLoad из-за автоматического изменения размера. Пришлось переместить код в viewDidAppear.

-(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];

CGRect bounds = self.view.bounds;
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:bounds byRoundingCorners:(UIRectCornerTopLeft | UIRectCornerBottomLeft) cornerRadii:CGSizeMake(5.0, 5.0)];

CAShapeLayer *maskLayer = [CAShapeLayer layer];
maskLayer.frame = bounds;
maskLayer.path = maskPath.CGPath;
self.view.layer.mask = maskLayer;

self.view.layer.masksToBounds = YES;
[self.view setNeedsDisplay];
}
person Odd-Arne    schedule 14.04.2015

Наконец я добился успеха, и это действительно работает. Попробуй.

CGRect frame = self.accountBackgroundImage2.frame;
frame.size.height = self.view.bounds.size.height;
UIBezierPath *path=[UIBezierPath bezierPathWithRoundedRect:self.accountBackgroundImage2.bounds byRoundingCorners:(UIRectCornerBottomLeft |UIRectCornerBottomRight) cornerRadii:CGSizeMake(12.5, 12.5)];

CAShapeLayer *shapeLayer = [[CAShapeLayer alloc] init];
shapeLayer.frame = self.accountBackgroundImage2.bounds;
shapeLayer.path  = path.CGPath;
_accountBackgroundImage2.layer.mask = shapeLayer;
self.accountBackgroundImage2.frame = frame;
person Patel Jigar    schedule 21.05.2015

По-другому

Выполнение в "viewWillLayoutSubviews"

- (void)viewWillLayoutSubviews{
[self roundCornersOnView:self.buttonJoin onTopLeft:NO topRight:YES bottomLeft:YES bottomRight:NO radius:10.0];
}

Функция

-(UIButton *)roundCornersOnView:(UIButton *)button onTopLeft:(BOOL)tl topRight:(BOOL)tr bottomLeft:(BOOL)bl bottomRight:(BOOL)br radius:(float)radius {

if (tl || tr || bl || br) {
    UIRectCorner corner = 0; //holds the corner
    //Determine which corner(s) should be changed
    if (tl) {
        corner = corner | UIRectCornerTopLeft;
    }
    if (tr) {
        corner = corner | UIRectCornerTopRight;
    }
    if (bl) {
        corner = corner | UIRectCornerBottomLeft;
    }
    if (br) {
        corner = corner | UIRectCornerBottomRight;
    }

    UIButton *roundedView = button;
    UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:roundedView.bounds byRoundingCorners:corner cornerRadii:CGSizeMake(radius, radius)];
    CAShapeLayer *maskLayer = [CAShapeLayer layer];
    maskLayer.frame = roundedView.bounds;
    maskLayer.path = maskPath.CGPath;
    roundedView.layer.mask = maskLayer;
    return roundedView;
} else {
    return button;
}

}

person Carlos Parada    schedule 04.08.2015