I am trying to draw a circle with vertical dashed line in border of circle.
I have tried like this, but it making dots in circle.
CAShapeLayer *circle = [CAShapeLayer layer];
circle.path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, 2.0*radius, 2.0*radius) cornerRadius:radius].CGPath;
circle.fillColor = [UIColor clearColor].CGColor;
circle.strokeColor = [UIColor redColor].CGColor;
circle.lineWidth = 1;
circle.lineDashPattern = #[#2, #3];
[[self.view layer] addSublayer:circle];
Please try using this below code, it worked for me.
1) Take UIView subClass, and in .h file implement below code
#import <UIKit/UIKit.h>
#interface ViewClass : UIView
#property (nonatomic) NSUInteger numberOfGraduations;
#property (nonatomic) CGFloat arcDegreeStart;
#property (nonatomic) CGFloat arcDegreeEnd;
#property (nonatomic) CGPoint arcCenter;
#property (nonatomic) CGFloat arcRadius;
#property (nonatomic) CGFloat deltaArc;
-(void)drawGraduation:(CGPoint )center Radius:(CGFloat)radius Angle:(CGFloat)angle Length:(CGFloat)length Width:(CGFloat)width colorWithRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue;
#end
2) Now in your.m file, implement below code
#import "ViewClass.h"
#implementation ViewClass
{
CGContextRef c;
}
-(void)drawGraduation:(CGPoint )center Radius:(CGFloat)radius Angle:(CGFloat)angle Length:(CGFloat)length Width:(CGFloat)width colorWithRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue{
c = UIGraphicsGetCurrentContext();
CGFloat radius2 = radius+length; // The radius of the end points of the graduations
CGPoint p1 = (CGPoint){cos(angle)*radius+center.x, sin(angle)*radius+center.y}; // the start point of the graduation
CGPoint p2 = (CGPoint){cos(angle)*radius2+center.x, sin(angle)*radius2+center.y}; // the end point of the graduation
CGContextMoveToPoint(c, p1.x, p1.y);
CGContextAddLineToPoint(c, p2.x, p2.y);
CGContextSetLineCap(c, kCGLineCapRound);
CGContextSetRGBStrokeColor(c, red, green, blue, 1.0);
CGContextSetLineWidth(c, width);
CGContextSetBlendMode(c,kCGBlendModeNormal);
CGContextStrokePath(c);
}
3) Below is the drawRect method..
- (void)drawRect:(CGRect)rect {
[super drawRect:rect];
CGRect r = self.bounds;
_numberOfGraduations = 31;
_arcCenter = (CGPoint){r.size.width*0.5, r.size.height*0.5}; // center of arc
_arcRadius = (r.size.width*0.5)-20; // radius of arc
CGFloat maxGraduationWidth = 1.0;
CGFloat maxGraduationWidthAngle = maxGraduationWidth/_arcRadius; // the maximum graduation width angle (used to prevent the graduations from being stroked outside of the main arc)
_arcDegreeStart =-M_PI*0.2;
_arcDegreeEnd = -M_PI*0.8;
// draw graduations
_deltaArc = (_arcDegreeEnd-_arcDegreeStart+maxGraduationWidthAngle)/(_numberOfGraduations-1); // the change in angle of the arc
for (int i = 0; i < _numberOfGraduations; i++) {
[self drawGraduation:_arcCenter Radius:_arcRadius Angle:_arcDegreeStart+(i*_deltaArc) Length:14 Width:1 colorWithRed:0.0 green:0.0 blue:1.0];
}
}
Related
I have implemented a basic line drawing animation for a progress bar.The line has a round cap edge.When I moving the slider the line drawing the ending of line is having a rounded cap but in the starting its a square. below is the code I am using am i missing anything??
Image Attached: expected output
Below Code I tried
#interface ViewController ()
{
CGPoint center;
CGFloat radius;
}
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
center = CGPointMake(200.0, 200.0);
self.view.layer.backgroundColor = [[UIColor grayColor] CGColor];
}
- (IBAction)greenSlider:(UISlider *)sender {
[self.view.layer addSublayer:[self drawArcAtCenter:center startAngle:sender.minimumValue endAngle:sender.value radius:100.0 withColor:[UIColor greenColor]]];
}
- (IBAction)blueSlider:(UISlider *)sender {
int value = (int)sender.value;
if (value > 360) {
value = value % 90;
}
[self.view.layer addSublayer:[self drawArcAtCenter:center startAngle:sender.minimumValue endAngle:(float)value radius:100 withColor:[UIColor blueColor]]];
}
- (CAShapeLayer *) drawArcAtCenter:(CGPoint)newCenter startAngle:(CGFloat)sAngle endAngle:(CGFloat)bAngle radius:(CGFloat) radious withColor:(UIColor*) color
{
CGFloat begAngle = sAngle * 3.1459 / 180.0;
CGFloat endAngle = bAngle * 3.1459 / 180.0;
CAShapeLayer *layer = [CAShapeLayer layer];
UIBezierPath *path = [UIBezierPath bezierPath];
[path addArcWithCenter:newCenter radius:radious startAngle:begAngle endAngle:endAngle clockwise:YES];
layer.path = [path CGPath];
layer.strokeColor = [color CGColor];
layer.fillColor = [[UIColor clearColor] CGColor];;
layer.lineWidth = 50.0;
layer.strokeEnd = 50.0f;
layer.lineCap = kCALineCapRound;
layer.cornerRadius = 30.0f;
return layer;
}
I've subclassed UILabel class to override drawRect: method. The label in IB is connected with the created subclass. It appears on the screen, but it doesn't show any text, whether it it is set in IB or programmatically. The label itself appears on the screen, when I'm logging it's text property, it shows OK.
Here's my code:
MyLabel.h
#import <UIKit/UIKit.h>
#interface MyLabel : UILabel
#end
MyLabel.m
#import "MyLabel.h"
#import <QuartzCore/QuartzCore.h>
#implementation MyLabel
- (void)drawRect:(CGRect)rect {
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = UIGraphicsGetCurrentContext();
UIColor *borderColor = [UIColor colorWithWhite: .1f alpha: 5.f];
UIColor *topColor = [UIColor colorWithWhite: .3f alpha: 5.f];
UIColor *bottomColor = [UIColor colorWithWhite: .5f alpha: 5.f];
UIColor *innerGlow = [UIColor colorWithWhite: 1.f alpha: .25f];
NSArray *gradientColors = #[(id)topColor.CGColor, (id)bottomColor.CGColor];
CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef) gradientColors, NULL);
CGFloat bWidth = self.frame.size.width;
CGFloat bHeight = self.frame.size.height;
UIBezierPath *roundedRectanglePath = [UIBezierPath bezierPathWithRoundedRect: CGRectMake(0, 0, bWidth, bHeight)
cornerRadius: 0];
[roundedRectanglePath addClip];
CGGradientRef background = gradient;
CGContextDrawLinearGradient(context, background, CGPointMake(bWidth / 2.f, 0), CGPointMake(bWidth / 2.f, bHeight), 0);
[borderColor setStroke];
roundedRectanglePath.lineWidth = 6;
[roundedRectanglePath stroke];
CGFloat glowRadius = 3.f;
UIBezierPath *innerGlowRect = [UIBezierPath bezierPathWithRoundedRect: CGRectMake(glowRadius, glowRadius, bWidth - 2 * glowRadius, bHeight - 2 * glowRadius) cornerRadius: 0];
[innerGlow setStroke];
innerGlowRect.lineWidth = 3;
[innerGlowRect stroke];
CGGradientRelease(gradient);
CGColorSpaceRelease(colorSpace);
}
#end
Maybe I need to override drawTextInRect: method, but I don't know how.
Thanks for help!
You need to call:
[super drawRect:rect];
At the top or your drawRect: method. If you need more control over how the string looks you'll need to draw it your self with the NSString string drawing methods.
I have to draw a black line on a transparent UIView, but despite having set the alpha of the line equal to 1, however this takes the degree of transparency of UIView. how can I do?
#import <UIKit/UIKit.h>
#interface FinalAlgView : UIView{
#private
//....
CGFloat lineWidth;
UIColor *lineColor;
UIImage *curImage;
CGMutablePathRef path;
}
#property (nonatomic, retain) UIColor *lineColor;
#property (readwrite) CGFloat lineWidth;
#property (assign, nonatomic) BOOL empty;
in implementation
#define DEFAULT_COLOR [UIColor colorWithRed:127.0/255.0 green:255.0/255.0 blue:0/255.0 alpha:0.6];
#define DEFAULT_WIDTH 20.0f
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.frame = CGRectMake(0, 0, 1024, 768);
self.lineWidth = DEFAULT_WIDTH;
self.lineColor = DEFAULT_COLOR;
self.empty = YES;
path = CGPathCreateMutable();
self.alpha=0.3;
self.opaque = NO;
}
return self;
}
- (void)drawRect:(CGRect)rect {
[[UIColor grayColor] set];
UIRectFill(rect);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextAddPath(context, path);
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetLineWidth(context, self.lineWidth);
CGContextSetStrokeColorWithColor(context, self.lineColor.CGColor);
CGContextStrokePath(context);
self.empty = NO;
}
you have to put the setting the alpha of UIView in drawRect and not in initWithFrame
NO
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.alpha=0.3;
}
return self;
}
YES
- (void)drawRect:(CGRect)rect {
[[UIColor colorWithRed:200.0/225.0 green:200.0/255.0 blue:200.0/255.0 alpha:0.0]set];
}
This question already has answers here:
What's the best approach to draw lines between views?
(2 answers)
Closed 9 years ago.
I have a very simple (well hopefully very simple) question. In Objective-C, how do you draw a line between two points and add it to a UIView? I have tried using a UIImageView and manipulating its Transform property, but that ends up turning the line into a square or a rectangle when using the following code:
[[self tline] setFrame:CGRectMake(start.x, start.y, width, 5)];
[[self tline] setTransform:CGAffineTransformMakeRotation(angle)];
I have two CGPoints, start and end, and I would like to draw a dynamic 5px line between the two points and add it to my subview.
BK:
The point start is the point where the user begins touching the screen, and the point end is the point where the user's finger is currently. Obviously this will move a lot during gameplay. I need to be able to move this line to connect these two points.
I am using the touchesBegan:, Moved:, and Ended: methods to create, move, and destroy the line.
CoreGraphics
I have the following code; how do I add this line to self.view?
CGContextRef c = UIGraphicsGetCurrentContext();
CGFloat color[4] = {1.0f, 1.0f, 1.0f, 0.6f};
CGContextSetStrokeColor(c, color);
CGContextBeginPath(c);
CGContextMoveToPoint(c, start.x, start.y);
CGContextAddLineToPoint(c, end.x, end.y);
CGContextSetLineWidth(c, 5);
CGContextSetLineCap(c, kCGLineCapRound);
CGContextStrokePath(c);
Custom UIView:
#import <UIKit/UIKit.h>
#interface DrawingView : UIView
#property (nonatomic) CGPoint start;
#property (nonatomic) CGPoint end;
- (void)drawRect:(CGRect)rect;
#end
#import "DrawingView.h"
#implementation DrawingView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
CGContextSetLineCap(context, kCGLineCapSquare);
CGContextSetStrokeColorWithColor(context, [UIColor whiteColor].CGColor); //change color here
CGFloat lineWidth = 5.0; //change line width here
CGContextSetLineWidth(context, lineWidth);
CGPoint startPoint = [self start];
CGPoint endPoint = [self end];
CGContextMoveToPoint(context, startPoint.x + lineWidth/2, startPoint.y + lineWidth/2);
CGContextAddLineToPoint(context, endPoint.x + lineWidth/2, endPoint.y + lineWidth/2);
CGContextStrokePath(context);
CGContextRestoreGState(context);
NSLog(#"%f",_end.x);
}
- (void)setEnd:(CGPoint)end
{
_end = end;
[self setNeedsDisplay];
}
#end
drawRect: is only called when I initialize the view...
Draw method in UIViewController:
- (void)drawTLine:(CGPoint)start withEndPoint:(CGPoint)end
{
[[self dview] setStart:start];
[[self dview] setEnd:end];
[[self dview] drawRect:[self dview].frame];
}
This is how I add the drawing view:
DrawingView* dview = [[DrawingView alloc] initWithFrame:self.view.frame];
[dview setBackgroundColor:[UIColor clearColor]];
[self.view addSubview:dview];
Subclass UIView and perform custom drawing using the drawRect: method
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
CGContextSetLineCap(context, kCGLineCapSquare);
CGContextSetStrokeColorWithColor(context, [UIColor blackColor].CGColor); //change color here
CGFloat lineWidth = 1.0; //change line width here
CGContextSetLineWidth(context, lineWidth);
CGPoint startPoint = rect.origin; //change start point here
CGPoint endPoint = {.x = CGRectGetMaxX(rect), .y = startPoint.y} //change end point here
CGContextMoveToPoint(context, startPoint.x + lineWidth/2, startPoint.y + lineWidth/2);
CGContextAddLineToPoint(context, endPoint.x + lineWidth/2, endPoint.y + lineWidth/2);
CGContextStrokePath(context);
CGContextRestoreGState(context);
}
This will draw a black 1px line at the top of your UIView.
If you need to update the line you can just use some properties like
#property (nonatomic) CGPoint startPoint;
and provide a custom implementation for the setter like
- (void)setStartPoint:(CGPoint)point {
_point = point;
[self setNeedsDisplay]; // this will cause drawRect: to be called again
}
Do that for every property that you wish to control and make your drawRect: use such properties for drawing.
you can create and UIBezierPath like this
UIBezierPath path = [[UIBezierPath alloc] init]
[path moveToPoint: CGPoint(x,y)] // X and Y, start point
[path addLineToPoint:CGPoint(x2,y2) // X2 and Y2, end point
if you want to create a shape you can put more points with addLineToPoint: method and finish use
closePath method
I hope help you
I would like to draw textured button in iOS app. I would not use Photoshop rather CoreGraphics because I want a general solution that works with buttons that has different size. What is the basic principle of it? What technology do I need?
My first step was to subclass a UIButton, but how can I add i.e. bevel effect to it?
The best approach will be subclassing you button class(your new class must inherit from UIButton). by doing this you can give some customized details too to your button.. Below is a sample ..
//interface of custom button class
#interface myButton : UIButton
{
int orderNo;
CAGradientLayer *gradientLayer;
CALayer *wrapperLayer;
CGColorRef _borderColor;
}
#property (assign) int orderNo;
#property (nonatomic) CGColorRef _borderColor;
#property (nonatomic, retain) CALayer *wrapperLayer;
#property (nonatomic, retain) CAGradientLayer *gradientLayer;
- (void)setBorderColor:(CGColorRef)color;
- (void)setCornerRadius:(float)radius;
The implementation..
#import "Button.h"
#implementation Button
#synthesize orderNo,wrapperLayer,_borderColor,gradientLayer;
- (id)initWithFrame:(CGRect)frame
{if ((self = [super initWithFrame:frame])) {
CGFloat radius = self.bounds.size.width / 2;
CGFloat borderWidth = self.bounds.size.width / 10;
self.layer.backgroundColor = [[UIColor blackColor] CGColor];
self.layer.borderColor = [[UIColor whiteColor] CGColor];
self.layer.borderWidth = borderWidth;
self.layer.cornerRadius = radius;
if ([self.layer respondsToSelector:#selector(setShadowOffset:)])
self.layer.shadowOffset = CGSizeMake(0.25, 0.25);
if ([self.layer respondsToSelector:#selector(setShadowColor:)])
self.layer.shadowColor = [[UIColor blackColor] CGColor];
if ([self.layer respondsToSelector:#selector(setShadowRadius:)])
self.layer.shadowRadius = borderWidth;
if ([self.layer respondsToSelector:#selector(setShadowOpacity:)])
self.layer.shadowOpacity = 0.75;
[self setNeedsDisplay];
}
return self;
}
- (void)drawRect:(CGRect)rect {
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSetShouldAntialias(ctx, true);
CGFloat xsize = self.bounds.size.width / 6;
CGFloat borderWidth = self.bounds.size.width / 10;
CGContextSaveGState(ctx);
CGContextSetLineCap(ctx, kCGLineCapRound);
CGContextSetLineWidth(ctx, borderWidth);
CGContextSetStrokeColorWithColor(ctx, [[UIColor whiteColor] CGColor]);
CGFloat width = self.bounds.size.width;
CGPoint start1 = CGPointMake(width / 2 - xsize, width / 2 - xsize);
CGPoint end1 = CGPointMake(width / 2 + xsize, width / 2 + xsize);
CGPoint start2 = CGPointMake(width / 2 + xsize, width / 2 - xsize);
CGPoint end2 = CGPointMake(width / 2 - xsize, width / 2 + xsize);
CGContextBeginPath(ctx);
CGContextMoveToPoint(ctx, start1.x, start1.y);
CGContextAddLineToPoint(ctx, end1.x, end1.y);
CGContextStrokePath(ctx);
CGContextBeginPath(ctx);
CGContextMoveToPoint(ctx, start2.x, start2.y);
CGContextAddLineToPoint(ctx, end2.x, end2.y);
CGContextStrokePath(ctx);
CGContextRestoreGState(ctx);
}
- (void)setBorderColor:(CGColorRef)color
{
[[self layer] setBorderColor:color];
[[self layer] setNeedsDisplay];
}
- (void)setCornerRadius:(float)radius
{
[[self layer] setCornerRadius:radius];
// and get the wrapper for the gradient layer too
[wrapperLayer setCornerRadius:radius];
}
#end