Change color of UIBezierPath in Swift - swift

I am working on a form of design project. In this project, you select an object and can change the color or size, or move.
Started a prototype of the app.
I will use UIBezierPath to draw the ways of the shapes, and will use CAShapeLayer to add to a sublayer of UIView.
This code draw one shape for example:
let insetRect = CGRect(x: 20, y: 20, width: 100, height: 100)
let path = UIBezierPath(roundedRect: insetRect, cornerRadius: 30)
UIColor.redColor().setFill()
path.fill()
path.lineWidth = 100
UIColor.blackColor().setStroke()
path.stroke()
let shapeLayer = CAShapeLayer()
shapeLayer.path = path.CGPath
shapeLayer.lineWidth = 1.0
self.view.layer.addSublayer(shapeLayer)
When the app starts, the shape is created without problems.
I wish I could click on the screen and automatically change the color (random) from shape.
Another problem: The shapes are random, and they rectangle, ellipse, rounded square. And due to these forms, I can not directly create on a View (reason for use the UIBezierPath).
Some can help me? I am trying to solve this for a few hours, and so far, found nothing.

Instead of adding bezierPath as sub layer, you can use a custom view. Pass a bezier path coordinates and color to the view. Keep instance of bezier path at class level and draw in DrawRect: method.
When user touches view in controller, pass custom view message to change color and redraw it.
You can simply change bezier path color by using:
yourColor.setStroke();
You can force your view to redraw bezier with changed color using:
customView.setNeedsDisplay();
EDIT
CustomView.m
-(id) initWithPath:(UIBezierPath *) path color:(UIColor *) color
{
if(self = [super init])
{
bezierPath = path;
pathColor = color;
}
return self;
}
- (void)drawRect:(CGRect)rect
{
[bezierPath stroke];
}
In controller, you can initialize as,
CustomView *customView = [[CustomView alloc] initWithPath:yourBezierPath color:[UIColor redColor];
customView.frame = yourFrame;
[self.view addSubview:customView];
To change color,
[customView setPathColor:[UIColor greenColor];
[customView setNeedsDisplay];
Hope it helps!

Related

How to create an oval shape UIButton

I have to draw an oval shape button, i don't want to set the image in oval shape.
I have read that you can draw different shaper with UIBezierPath but i am unable to draw a proper oval shape.
Here is the code is am using to create a circular shape.
self.layer.borderWidth=1.0;
self.clipsToBounds = YES;
[self setTitleColor:ktextColor forState:UIControlStateNormal];
self.layer.cornerRadius = self.bounds.size.width/2;//half of the width
self.layer.borderColor=[[UIColor whiteColor]CGColor];
Any help is appreciated !!
You can set the delegate for your button's layer and implement the delegate method `displayLayer:'
-(void)displayLayer:(CALayer *)layer
{
UIGraphicsBeginImageContext(layer.frame.size);
CGContextRef context = UIGraphicsGetCurrentContext();
UIBezierPath* ovalPath = [UIBezierPath bezierPathWithOvalInRect: CGRectMake(0.0, 0.0, CGRectGetWidth(layer.frame), CGRectGetHeight(layer.frame))];
[[UIColor whiteColor] setFill];
[ovalPath fill];
[[UIColor blackColor] setStroke];
ovalPath.lineWidth = 1;
[ovalPath stroke];
UIImage *imageBuffer = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
layer.contents = (id)[imageBuffer CGImage];
}
You can also create a CAShapelayer and than add gesture to the layer as below:
-(void)generateOvalWithSize:(CGSize)size origin:(CGPoint)origin {
CAShapeLayer ovalLayer = [CAShapeLayer layer];
CGMutablePathRef ovalPath = CGPathCreateMutable();
CGPathAddEllipseInRect(ovalPath, NULL, CGRectMake(origin.x, origin.y, size.width, size.height));
CGPathCloseSubpath(ovalPath);
ovalLayer.path = ovalPath;
// Configure the apperence of the circle
ovalLayer.fillColor = [UIColor whiteColor].CGColor;
ovalLayer.strokeColor = [UIColor whiteColor].CGColor;
ovalLayer.lineWidth = 2;
// Add to parent layer
[[self layer] addSublayer:ovalLayer];
}
i have been using these two functions for a while, i haven't come across any issues yet, but if someone sees an issue please let me know.
you can pass anything that is a subclass of UIView (ie. UIButton, UICollectionViewCell, etc.)
+ (void)setCornerRadius:(CGFloat)radius forView:(UIView*)view
{
[view.layer setCornerRadius:radius];
[view.layer setMasksToBounds:YES];
}
+ (void)setBordersForView:(UIView*)view width:(CGFloat)width color:(UIColor*)color
{
view.layer.borderColor = color.CGColor;
view.layer.borderWidth = width;
}
the above yields me the effect below in a collection view:
the collection view cell has a single button which is bound all the way around the edges (auto layout) and takes up the full height and width of the cell.
then i pass in the entire cell (or self.viewForBaseLineLayout if calling from within the cell) as the view parameter in both functions listed above.
for the radius parameter i am passing 20.0f.
(but this value will vary depending on the size the view you are passing; you just have to play around with it)
i know this post is old, but maybe it will help someone new : )
You can use the OBShapedButton class Download Here

How to hide a subframe of a UIView?

lets say i have a UIImageView with a frame (0,0,100,30)
.that imageView was assigned an image.
whats the simplest way to show only part of the image?
for example: only what appears in points 30-60 (width) and 0-30 (height). that means that the left and right edges of the image should be hidden.
just to clarify, i don't want to move the view nor change it's size, i just want to hide a subrect of it's frame.
You could always set a mask.
CALayer *maskLayer = [CALayer layer];
maskLayer.backgroundColor = [UIColor blackColor].CGColor;
maskLayer.frame = CGRectmake(30.0, 0.0, 30.0, 30.0);
view.layer.mask = maskLayer;
Masks can be any type of layer, so you could even use a CAShapeLayer for complex masks and do some really cool stuff.
i've found this solution works for me, https://stackoverflow.com/a/39917334/3192115
func mask(withRect rect: CGRect, inverse: Bool = false) {
let path = UIBezierPath(rect: rect)
let maskLayer = CAShapeLayer()
if inverse {
path.append(UIBezierPath(rect: self.view.bounds))
maskLayer.fillRule = kCAFillRuleEvenOdd
}
maskLayer.path = path.cgPath
imageView?.layer.mask = maskLayer
}
I believe masking the image is the best option. But if you were to rotate, transform, animate or want a clear background you can do something like this:
Create a sub view which is the size of the image you want to show. Make sure it has clipsToBounds to true and position the image accordingly.
UIView *mainView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 30)];
//this is the part of the image you wish to see
UIView *imageWindow = [[UIView alloc] initWithFrame:CGRectMake(30, 0, 30, 30)];
imageWindow.clipsToBounds = YES;
//your image view is the height and width of mainView and x and y is imageWindow - mainView. You can do this manually or put in calculations.
UIImageView *myImage = [[UIImageView alloc] initWithFrame:CGRectMake(imageWindow.frame.origin.x - mainView.frame.origin.x, imageWindow.frame.origin.y - mainView.frame.origin.y, mainView.frame.size.width, mainView.frame.size.height)];
myImage.image = [UIImage imageNamed:#"1024x1024.png"];
[imageWindow addSubview:myImage];
[mainView addSubview:imageWindow];
[self.view addSubview:mainView];
Looking over my code, I don't think mainView is necessary and you could add imageWindow to self.view directly.

Draw Line using CGContext

I want to draw line in table view cell so that I can place textfield & switch in single cell. I increased the height of cell. How can I draw line in cell?
I have subclass of UIView which contains following code
//Get the CGContext from this view
CGContextRef context = UIGraphicsGetCurrentContext();
//Set the stroke (pen) color
CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);
//Set the width of the pen mark
CGContextSetLineWidth(context, 1.0);
// Draw a line
//Start at this point
CGContextMoveToPoint(context, 10.0, 30.0);
//Give instructions to the CGContext
//(move "pen" around the screen)
CGContextAddLineToPoint(context, 310.0, 30.0);
//Draw it
CGContextStrokePath(context);
Then I have a tableViewController with grouped table style. In cellForRowAtIndexPath I have following code
//code to add textfield
DrawLineView *drawLine = [[DrawLineView alloc]init];
[cell addSubview:drawLine];
//code add switch
But it is not drawing any line. I can't use 2 different cells. I have to Please help me. This is my first to deal with graphics i iphone. Thanks
If all you want to do is draw a line, it would be a lot better to use a CAShapeLayer, pass it a path with a line, and then attach that as a sublayer of the cells content view. The table should perform better than using a view with a custom drawRect.
Example of drawing a line via CALayer and a path:
// You'll also need the QuartzCore framework added to the project
#import <QuartzCore/QuartzCore.h>
CAShapeLayer *lineShape = nil;
CGMutablePathRef linePath = nil;
linePath = CGPathCreateMutable();
lineShape = [CAShapeLayer layer];
lineShape.lineWidth = 4.0f;
lineShape.lineCap = kCALineCapRound;;
lineShape.strokeColor = [[UIColor blackColor] CGColor];
int x = 0; int y = 0;
int toX = 30; int toY = 40;
CGPathMoveToPoint(linePath, NULL, x, y);
CGPathAddLineToPoint(linePath, NULL, toX, toY);
lineShape.path = linePath;
CGPathRelease(linePath);
[self.layer addSublayer:lineShape];
Two things...
First, you usually don't draw into the cell itself.
You normally draw into the content view. Sometimes it makes sense draw into the cell's backgroundView or selectedBackgroundView.
[cell.contentView addSubview:drawLine];
Second, the default cell text labels cell.textLabel and cell.detailTextLabel have non-transparent background. Try setting their background colors to [UIColor clearColor].
Edit: one more thing: you need to set a proper frame for your drawLine
DrawLineView *drawLine = [[DrawLineView alloc]initWithFrame:cell.contentView.bounds];
I think a very simplified way of drawing a line is to create a UIView and fill it with desired color, then choose its width accordingly, and setup height to be 1 pixel like so:
var lineView : UIView = {
let view = UIView()
view.backgroundColor = UIColor.blackColor()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
self.view.addSubview(lineView)
self.view.addConstraints(NSLayoutConstraint.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[view]|", options: NSLayoutFormatOptions(), metrics: nil, views: ["view": lineView])))
self.view.addConstraints(NSLayoutConstraint.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-50-[view(1)]", options: NSLayoutFormatOptions(), metrics: nil, views: ["view": lineView])))

UIImage in a circle

Can somebody help me here?. New as iPhone Developer. I am trying to display a .png picture in a circle instead of a rectangle which is the standard for iPhone
Well, all png files are 'rectangles' but if you want to have the apperence of a circle or other non rectangle object on the screen you can do so by using transparacy. To make sure the transparent pixels in the image are also transparent on the iPhone, you can set the background color of the UIImageView to clear. This can be done in Interface Builder by dragging the opacity slider in the background color picker all the way down,
or in code as follows:
UIImage *image = [UIImage imageNamed:#"yourRoundImage.png"];
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
imageView.backgroundColor = [UIColor clearColor];
[self.view addSubview: imageView];
If you simply want to add rounder corners, to make a circle, you can also use the cornerRadius Property like this if you have added the QuartzCore framework to your project:
#import <QuartzCore/QuartzCore.h>
UIImage *image = [UIImage imageNamed:#"yourRoundImage.png"];
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
imageView.layer.cornerRadius = image.size.width / 2;
imageView.layer.masksToBounds = YES;
[self.view addSubview: imageView];
try this code
yourImageView.layer.cornerRadius = yourImageView.frame.size.height /2;
yourImageView.layer.masksToBounds = YES;
yourImageView.layer.borderWidth = 0;
this show image like ios 7 circle image thanks
My contribution with a swift extension used to set an UIImageView as circle
extension UIImageView{
func asCircle(){
self.layer.cornerRadius = self.frame.width / 2;
self.layer.masksToBounds = true
}
}
Just call MyImageView.asCircle()
Use a UIImageView and set the cornerRadius to be half height and width. view.layer.cornerRadius = cornerRadius;
UIImage rounded corners
Try this to get rounded corners of the image View and also to colour the corners:
self.imgView.layer.cornerRadius =self.imgView.frame.size.height/2;
self.imgView.layer.masksToBounds = YES;
self.imgView.layer.borderColor = [UIColor colorWithRed:148/255. green:79/255. blue:216/255. alpha:1.0].CGColor;
self.imgView.layer.borderWidth=2;
Condition*: The height and the width of the imageView must be same to get rounded corners.
Changing the cornerRadius of the image view works well if you have only a couple of images in your view. However if the image view is in a tableview performance will be affected.
Some of the other options:
Make the image assets circle on the server or manually if they are bundled into the app, with transparent parts for the outer region of the circle.
If the background of the image view doesn't change, create an overlay image that has the inner circle part transparent, and the rest to be the same as the background. Also set the backgroundColor of the image view to clearColor.
When receiving the images, edit them in code to be a circle, in a background thread.
Swift 4: This should display your .png in a circle.
Drag (ctrl + click) an IBOutlet of an image toward your code.
cornerRadius
The radius to use when drawing rounded corners for the layer’s background. Animatable. https://developer.apple.com/documentation/quartzcore/calayer/1410818-cornerradius
clipsToBounds property
A Boolean value that determines whether subviews are confined to the bounds of the view. https://developer.apple.com/documentation/uikit/uiview/1622415-clipstobounds
2.Inside viewDidLoad(), Use the instance property layer.cornerRadius and clipsToBounds.
profileImage.layer.cornerRadius = 50
profileImage.clipsToBounds = true
I'll add a slightly more universal extension to UIImageView that will work with non-square images.
To be noted that it will work slower than the cornerRadius method.
extension UIImageView {
#IBInspectable public var asEllipse:Bool {
get {
if let mask = self.layer.mask {
return mask.name == kMaskLayerName
}
return false;
}
set {
if (newValue) {
let ellipseMask = CAShapeLayer()
ellipseMask.name = kMaskLayerName
ellipseMask.path = CGPathCreateWithEllipseInRect(self.bounds, nil)
ellipseMask.strokeColor = UIColor.clearColor().CGColor
ellipseMask.fillColor = UIColor.whiteColor().CGColor
self.layer.mask = ellipseMask
} else if self.asEllipse {
self.layer.mask = nil
}
}
}
}
private let kMaskLayerName="EllipseMaskLayer"
On Objective-C it looks like:
UIImage* pIconImage = [UIImage imageNamed:#"ImageName"];
UIImageView* pIconView = [[UIImageView alloc] initWithImage:pIconImage];
[pIconView.layer setCornerRadius:pIconImage.size.width / 2];
[pIconView.layer setMasksToBounds:YES];

Drawing a transparent circle on top of a UIImage - iPhone SDK

I am having a lot of trouble trying to find out how to draw a transparent circle on top of a UIImage within my UIImageView. Google-ing gives me clues, but I still can't find a working example.
Are there any examples that anyone knows of that demonstrate this?
Easiest way is simply to create a semi-transparent square UIView, then set the cornerRadius of its layer to be half of its width/height. Something like:
UIView *squareView = [[UIView alloc] initWithFrame:CGRectMake(0,0,100,100)];
squareView.alpha = 0.5;
squareView.layer.cornerRadius = 50;
...
[squareView release];
This has got to be the simplest solution:
CGFloat r = 150;
UILabel *lbl = [[UILabel alloc] initWithFrame:CGRectMake(0,0,1.5*r,1.5*r)];
lbl.text = #"●";
lbl.transform = CGAffineTransformMakeTranslation(0.0f, -r/6);
lbl.textAlignment = UITextAlignmentCenter;
lbl.backgroundColor = [UIColor clearColor];
lbl.textColor = [UIColor redColor];
lbl.font = [UIFont systemFontOfSize:2*r];
lbl.alpha = 0.5;
lbl.center = self.view.center;
[self.view addSubview:lbl];
One way would be to add a CAShapeLayer with a circular path, either directly to the layer of the UIImageView or as the layer of a new UIView that is added to the UIImageView.
If you actually want to modify the image, then create a mutable copy of it by drawing it into a CGBitmapContext then creating a new image from the modified bitmap.
CGPathRef circlePath = CGPathCreateMutable();
CGPathAddEllipseInRect( circlePath , NULL , CGRectMake( 0,0,20,20 ) );
CAShapeLayer *circle = [[CAShapeLayer alloc] init];
circle.path = circlePath;
circle.opacity = 0.5;
[myImageView.layer addSublayer:circle];
CGPathRelease( circlePath );
[circle release];
You can implement a custom sub-class of UIView that draws your image and then the circle in the drawRect method:
#interface CircleImageView : UIView {
UIImage * m_image;
CGRect m_viewRect;
// anything else you need in this view?
}
Implementation of drawRect:
- (void)drawRect:(CGRect)rect {
// first draw the image
[m_image drawInRect:m_viewRect blendMode:kCGBlendModeNormal alpha:1.0];
// then use quartz to draw the circle
CGContextRef context = UIGraphicsGetCurrentContext ()
// stroke and fill black with a 0.5 alpha
CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 0.5);
CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 0.5);
// now draw the circle
CGContextFillEllipseInRect (context, m_viewRect);
}
You will need to set up the m_viewRect and m_image member functions on init.