Раунд два угла в UIView - PullRequest
       69

Раунд два угла в UIView

75 голосов
/ 31 января 2011

Некоторое время назад я опубликовал вопрос о округлении только двух углов представления , и получил отличный ответ, но у меня возникли проблемы с его реализацией. Вот мой 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);
}

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

Ответы [ 18 ]

1 голос
/ 31 октября 2012

Путь Безье - ответ, если вам нужен дополнительный код, этот работал для меня: 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 голос
/ 06 февраля 2011

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

Я не уверен, что вы добились такого результата. Также стоит отметить, что если / когда система вызывает 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);    
}
1 голос
/ 24 апреля 2018

Расширяя принятый ответ, давайте добавим к нему обратную совместимость. До 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 и @ P.L :) Я объединил их коды, чтобы сделать его лучше.

1 голос
/ 11 марта 2015

Решение 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 голосов
/ 31 января 2011

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

self.clipsToBounds = YES

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

0 голосов
/ 03 февраля 2011

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

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

Немного хакерский, но относительно простой (без подклассов, маскировки и т. Д.) Способ получить два UIViews.Оба с 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];

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

0 голосов
/ 08 января 2015

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

self.tableView.layer.cornerRadius = 10;

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

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

enter image description here

...