Rectangle 27 7

To draw a solid filled in arc within a particular CGSize, you can define a UIBezierPath like so:

- (UIBezierPath * _Nullable)pathOfArcWithinSize:(CGSize)size {
    if (size.width == 0 || size.height <= 0) return nil;

    CGFloat theta = M_PI - atan2(size.width / 2.0, size.height) * 2.0;
    CGFloat radius = self.bounds.size.height / (1.0 - cos(theta));

    UIBezierPath *path = [UIBezierPath bezierPath];
    [path moveToPoint:CGPointMake(0, 0)];
    [path addArcWithCenter:CGPointMake(size.width / 2.0, -radius + size.height) radius:radius startAngle:M_PI_2 + theta endAngle:M_PI_2 - theta clockwise:false];
    [path closePath];

    return path;
}

That's just using a little trigonometry to calculate the angle and radius for the arc given the height and width of the view.

Once you have that, you can either construct a CAShapeLayer using that path and then add that as a sublayer of a UIView or you can implement your own drawRect method that calls fill on that path. (Or, given that you've tagged this with core-graphics, you could also do a custom drawRect with CoreGraphics calls, but I'm not sure why you'd do that.)

For example, you could define a CurvedView class that uses CAShapeLayer:

//  CurvedView.h

#import <UIKit/UIKit.h>

IB_DESIGNABLE
@interface CurvedView : UIView

@property (nonatomic, strong) IBInspectable UIColor *fillColor;

@end

Or, if you'd rather use the drawRect approach rather than using CAShapeLayer:

//  CurvedView.m

#import "CurvedView.h"

@implementation CurvedView

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        [self configureView];
    }
    return self;
}

- (instancetype _Nullable)initWithCoder:(NSCoder *)coder {
    self = [super initWithCoder:coder];
    if (self) {
        [self configureView];
    }
    return self;
}

- (void)configureView {
    self.fillColor = [UIColor whiteColor];
}

- (void)setFillColor:(UIColor *)fillColor {
    _fillColor = fillColor;

    [self setNeedsDisplay];
}

- (void)drawRect:(CGRect)rect {
    UIBezierPath *path = [self pathOfArcWithinSize:self.bounds.size];
    [self.fillColor setFill];
    [path fill];
}

- (UIBezierPath * _Nullable)pathOfArcWithinSize:(CGSize)size {
    if (size.width == 0 || size.height <= 0) return nil;

    CGFloat theta = M_PI - atan2(size.width / 2.0, size.height) * 2.0;
    CGFloat radius = self.bounds.size.height / (1.0 - cos(theta));

    UIBezierPath *path = [UIBezierPath bezierPath];
    [path moveToPoint:CGPointMake(0, 0)];
    [path addArcWithCenter:CGPointMake(size.width / 2.0, -radius + size.height) radius:radius startAngle:M_PI_2 + theta endAngle:M_PI_2 - theta clockwise:false];
    [path closePath];

    return path;
}

@end

If you want the arc to occupy the bottom of the view, the path would look like:

- (UIBezierPath * _Nullable)pathOfArcWithinSize:(CGSize)size {
    if (size.width == 0 || size.height <= 0) return nil;

    CGFloat theta = M_PI - atan2(size.width / 2.0, size.height) * 2.0;
    CGFloat radius = self.bounds.size.height / (1.0 - cos(theta));

    UIBezierPath *path = [UIBezierPath bezierPath];
    [path moveToPoint:CGPointMake(0, size.height)];
    [path addArcWithCenter:CGPointMake(size.width / 2.0, radius) radius:radius startAngle:M_PI_2 * 3.0 + theta endAngle:M_PI_2 * 3.0 - theta clockwise:false];
    [path closePath];

    return path;
}

Essentially, that's the same theta and radius, but start in lower left corner, set the center to be size.width / 2.0, radius, and arc from M_PI_2 * 3.0 theta:

Thanks rob..you saved me again..i want to learn this..actually dont know how to deal with UIBeizers,i want to learn this,so can you help me from where can i start...thanks...:)

@Elan - For the basics of bezier paths, see Apple documentation (developer.apple.com/library/ios/documentation/2DDrawing/) or google "uibezierpath tutorial". For the maths to achieve the desired path, this is drawing on my old high-school trigonometry from the mists of time. :) Bottom line, just start playing around with building your own UIBezierPath in either custom UIView subclass (like above) or CAShapeLayer and I'm sure you'll pick it up quickly. It's not as hard as it looks.

ios - How to Draw a Bezier Curve in UIView - Stack Overflow

ios objective-c core-graphics uibezierpath
Rectangle 27 9

I have a UIBezierPath inside my custom UIView draw(_ rect: CGRect) function. I would like to fill the path with a gradient color.

Lets say you have an oval path,

let path = UIBezierPath(ovalIn: CGRect(x: 0, y: 0, width: 100, height: 100))

To create a gradient,

let gradient = CAGradientLayer()
gradient.frame = path.bounds
gradient.colors = [UIColor.magenta.cgColor, UIColor.cyan.cgColor]

We need a mask layer for gradient,

let shapeMask = CAShapeLayer()
shapeMask.path = path.cgPath
shapeLayer
mask
gradient
view
subLayer
gradient.mask = shapeMask
yourCustomView.layer.addSublayer(gradient)

Update Create a base layer with stroke and add before creating gradient layer.

let shape = CAShapeLayer()
shape.path = path.cgPath
shape.lineWidth = 2.0
shape.strokeColor = UIColor.black.cgColor
self.view.layer.addSublayer(shape)

let gradient = CAGradientLayer()
gradient.frame = path.bounds
gradient.colors = [UIColor.magenta.cgColor, UIColor.cyan.cgColor]

let shapeMask = CAShapeLayer()
shapeMask.path = path.cgPath
gradient.mask = shapeMask

self.view.layer.addSublayer(gradient)
I need to fill the clip with a gradient color and then stroke the path with black color

As I am overriding UIView, inside draw() func I assume you mean self.layer instead of self.view.layer. I follow all your updated instructions, works pretty close but its only showing borderlines in black. No strokes in the middle of the graph is showing. @Matt

can you show what you exactly want in a picture?

Thanks for your answer. I have just added shape.fillColor = UIColor.clear.cgColor and the problem is solved.

You are welcome

ios - How to fill a bezier path with gradient color - Stack Overflow

ios uiview swift3 core-graphics draw
Rectangle 27 1

Yes , You have to override the drawrect if you want to draw anything.Creating a UIBezierPath can be done anywhere ,But to draw something you have to do it inside the drawrect method

You should be calling setNeedsDisplay if you override drawRect in a subclass of UIView which is basically a custom view drawing something on the screen, like lines,image , rectangle.

ios - Drawing UIBezierPath on code generated UIView - Stack Overflow

ios iphone objective-c uiview uibezierpath
Rectangle 27 1

Yes , You have to override the drawrect if you want to draw anything.Creating a UIBezierPath can be done anywhere ,But to draw something you have to do it inside the drawrect method

You should be calling setNeedsDisplay if you override drawRect in a subclass of UIView which is basically a custom view drawing something on the screen, like lines,image , rectangle.

ios - Drawing UIBezierPath on code generated UIView - Stack Overflow

ios iphone objective-c uiview uibezierpath
Rectangle 27 5

In your UIView+Bubble.h category UIBezierPath tries to draw triangle on a null context. If you want to draw shape using UIBezierPath like above, you have to put this code inside drawRectmethod of a View class.

On the other hand, you could create a new context to draw. You may modify your makeBubble method as follow:

+(UIView *)makeBubble{
   // declare UIimageView, not UIView
   UIImageView *customView = [[UIImageView alloc] init];
   customView.frame=CGRectMake(0, 0, 320, 500);

   // create a new contex to draw
   UIGraphicsBeginImageContextWithOptions(CGSizeMake(200, 200), NO, 0);

   UIBezierPath *triangle = [UIBezierPath bezierPath];
   [triangle moveToPoint:CGPointMake(100, 0)];
   [triangle addLineToPoint:CGPointMake(0, 100)];
   [triangle addLineToPoint:CGPointMake(200, 100)];
   [triangle closePath];
   [[UIColor blackColor] setFill];
   [triangle fill];

   customView.image = UIGraphicsGetImageFromCurrentImageContext();

   UIGraphicsEndImageContext();

   return customView;
}
+(UIView *)makeBubble:(CGRect)rect
customView.frame=rect;
UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0);
UIView *helpBubble=[UIView makeBubble:/*your desire rect*/];

P.S. it will be great if you calculate the points depending on the rect too.

@x4h1d- Thanks, a lot.

you are welcome.

ios - Creating a UIBezierPath in UIView Category. not being shown - St...

ios iphone objective-c uibezierpath objective-c-category
Rectangle 27 34

There is truth in all the other answers, but it is quite possible to draw with clear colour, or so to say erase the existing colours within any path, even with the -[UIBezierPath fill] or similar convenience methods. All you have to do is to set the context blend mode to an appropriate value depending on the effect you are trying to achieve, like so:

CGContextSetBlendMode(context, kCGBlendModeClear);
[[UIColor clearColor] set];
[myArbitraryPolygonPath fill];

There are around two dozen different options you could choose from, take a look around the CGContext reference.

WOW!!! You are my hero, Rage!!! :) Thanks a lot!

You don't even need to set a clear color. The clear blend mode is going to set the premultiplied pixel value to 0 regardless of the source color.

ios - iPhone - Draw transparent rectangle on UIView to reveal view ben...

ios iphone uiview quartz-graphics
Rectangle 27 34

There is truth in all the other answers, but it is quite possible to draw with clear colour, or so to say erase the existing colours within any path, even with the -[UIBezierPath fill] or similar convenience methods. All you have to do is to set the context blend mode to an appropriate value depending on the effect you are trying to achieve, like so:

CGContextSetBlendMode(context, kCGBlendModeClear);
[[UIColor clearColor] set];
[myArbitraryPolygonPath fill];

There are around two dozen different options you could choose from, take a look around the CGContext reference.

WOW!!! You are my hero, Rage!!! :) Thanks a lot!

You don't even need to set a clear color. The clear blend mode is going to set the premultiplied pixel value to 0 regardless of the source color.

ios - iPhone - Draw transparent rectangle on UIView to reveal view ben...

ios iphone uiview quartz-graphics