Я хочу создать произвольную форму в UIView, нарисовав ее сам с помощью объекта UIBezierPath и отрендерив в drawRect:. Пока мне удалось создать фигуру и обвести ее так, чтобы она отображалась на экране именно такой, какой я хочу. Однако я не могу его правильно заполнить. Вот код на данный момент:

- (void)drawRect:(CGRect)rect {
    CGContextRef context = UIGraphicsGetCurrentContext();

    CGContextSetLineWidth(context, 2.f);
    CGContextSetLineJoin(context, kCGLineJoinRound);
    CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor);
    CGContextSetFillColorWithColor(context, [UIColor redColor].CGColor);

    UIBezierPath *path = [UIBezierPath bezierPath];
    [path setLineWidth:2.f];
    [path setLineJoinStyle:kCGLineJoinRound];

    // Stroke top left arc
    //[path moveToPoint:CGPointMake(20.f, 2.f)];
    [path addArcWithCenter:CGPointMake(10.f, 10.f) radius:5.f startAngle:3*M_PI/2 endAngle:M_PI clockwise:0];

    // Stroke bottom left arc
    [path addArcWithCenter:CGPointMake(10.f, 50.f) radius:5.f startAngle:M_PI endAngle:M_PI/2 clockwise:0];

    // Stroke bottom line
    [path moveToPoint:CGPointMake(10.f, 55.f)];
    [path addLineToPoint:CGPointMake(60.f, 55.f)];

    // Stroke bottom arc
    [path moveToPoint:CGPointMake(80.f, 55.f)];
    [path addArcWithCenter:CGPointMake(71.f, 65.f) radius:15.f startAngle:degreesToRadians(315) endAngle:degreesToRadians(215) clockwise:1];

    // Stroke bottom right arc
    [path moveToPoint:CGPointMake(80.f, 55.f)];
    [path addArcWithCenter:CGPointMake(80.f, 50.f) radius:5.f startAngle:M_PI/2 endAngle:0 clockwise:0];

    // Stroke top right arc
    [path addArcWithCenter:CGPointMake(80.f, 10.f) radius:5.f startAngle:0 endAngle:3*M_PI/2 clockwise:0];

    // Close path
    [path moveToPoint:CGPointMake(80.f, 5.f)];
    [path addLineToPoint:CGPointMake(10.f, 5.f)];

    [path stroke];
    [path fill];
}

Обводка работает должным образом, но заливка заполняет только части на path, а не целиком path. Что-то мне не хватает?

Заранее спасибо!

2
TeodorC 31 Май 2014 в 16:38
Попробуйте изменить свойство usesEvenOddFillRule вашего пути
 – 
Gonzo
31 Май 2014 в 16:48
@ Гонзо, нет, не работает.
 – 
TeodorC
31 Май 2014 в 16:56

3 ответа

Лучший ответ

Я понял. Просто нужно избавиться от вызовов moveToPoint :, поскольку они создают подпути, поэтому заполнение будет влиять только на новые подпути. И, наконец, вызвал closePath.

Теперь мой путь непрерывный, и заливка работает для всей формы.

Отредактированный код:

- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor);
CGContextSetFillColorWithColor(context, [UIColor redColor].CGColor);

UIBezierPath *path = [UIBezierPath bezierPath];
[path setLineWidth:2.f];
[path setLineJoinStyle:kCGLineJoinRound];

// Stroke top left arc
[path addArcWithCenter:CGPointMake(10.f, 10.f) radius:5.f startAngle:3*M_PI/2 endAngle:M_PI clockwise:0];

// Stroke bottom left arc
[path addArcWithCenter:CGPointMake(10.f, 50.f) radius:5.f startAngle:M_PI endAngle:M_PI/2 clockwise:0];

// Stroke bottom arc
[path addArcWithCenter:CGPointMake(71.f, 65.f) radius:15.f startAngle:degreesToRadians(215) endAngle:degreesToRadians(315) clockwise:0];

// Stroke bottom right arc
[path addArcWithCenter:CGPointMake(80.f, 50.f) radius:5.f startAngle:M_PI/2 endAngle:0 clockwise:0];

// Stroke top right arc
[path addArcWithCenter:CGPointMake(80.f, 10.f) radius:5.f startAngle:0 endAngle:3*M_PI/2 clockwise:0];

// Close path
[path closePath];

[path fill];
[path stroke];

}

2
TeodorC 31 Май 2014 в 17:09

Удалите все свои

- (void)moveToPoint:(CGPoint)point

Методы, кроме первого, потому что это непрерывный путь, который вам не нужен.

Настоятельно рекомендуется закрыть путь, вызвав метод - (void)closePath, потому что у вас разрыв в 3 пикселя.

3
Goppinath 31 Май 2014 в 17:24

Просто вызовите метод

- (void)closePath

В конце, чтобы закрыть свой UIBezierPath.

0
Goppinath 31 Май 2014 в 17:30
Это не дает ответа на вопрос. Чтобы критиковать или запросить разъяснения у автора, оставьте комментарий под своим постом.
 – 
frogatto
31 Май 2014 в 17:16
@ABFORCE, что является ответом, потому что человек не закрывает путь и имеет зазор в 3 пикселя. Поэтому он / она должен закрыть его.
 – 
Goppinath
31 Май 2014 в 17:23
Ответ должен содержать больше объяснений и разъяснять проблему. Это ТАКОЕ правило!
 – 
frogatto
31 Май 2014 в 17:26