I am creating one custom button class inherit from the UIControl.
I am creating Button with Kite Shape as shown in image using Bizer Path.
Code
.h
import
#interface CustomButton : UIControl
-(instancetype)initWithFrame:(CGRect)frame;
#end
.m
#import "CustomButton.h"
#implementation CustomButton
-(instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if(self)
{
UIBezierPath *path = [UIBezierPath new];
// [path moveToPoint:(CGPoint){0, 0}];
[path moveToPoint:(CGPoint){100,50}];
[path addLineToPoint:(CGPoint){100, 100}];
[path addLineToPoint:(CGPoint){150, 100}];
[path addLineToPoint:(CGPoint){200, 0}];
[path addLineToPoint:(CGPoint){100, 50}];
// Create a CAShapeLayer with this triangular path
// Same size as the original imageView
CAShapeLayer *mask = [CAShapeLayer new];
mask.frame = self.bounds;
mask.path = path.CGPath;
// Mask the imageView's layer with this shape
self.layer.mask = mask;
}
return self;
}
#end
VC .m
CustomButton *button = [[CustomButton alloc]initWithFrame:CGRectMake(20, 20, 200, 200)];
button.backgroundColor = [UIColor redColor];
[button addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside] ;
[self.view addSubview:button];
}
- (void)buttonPressed:(id)sender
{
NSLog(#"pressing");
}
Image
My Question Is,
When I clicked outside the button(Red Portion) It gives me a click event.
I do not want to do this.
Please help me,How can i solve it?
Thank You
I am updating my answer for UIBUtton
CustomButton.h
#import <UIKit/UIKit.h>
#interface CustomButton : UIControl
-(instancetype)initWithFrame:(CGRect)frame;
#end
CustomButton.m
#import "CustomButton.h"
#implementation CustomButton
-(instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if(self)
{
UIBezierPath *path = [UIBezierPath new];
[path moveToPoint:(CGPoint){100,50}];
[path addLineToPoint:(CGPoint){100, 100}];
[path addLineToPoint:(CGPoint){150, 100}];
[path addLineToPoint:(CGPoint){200, 0}];
[path addLineToPoint:(CGPoint){100, 50}];
CAShapeLayer *mask = [CAShapeLayer new];
mask.frame = self.bounds;
mask.path = path.CGPath;
// Mask the imageView's layer with this shape
self.layer.mask = mask;
}
return self;
}
In your controller viewDidLoad
CustomButton *buttonCustom = [[CustomButton alloc] initWithFrame:CGRectMake(20, 20, 200, 200)];
[buttonCustom setBackgroundColor:[UIColor redColor]];
[buttonCustom addTarget:self action:#selector(buttonCustom:forEvent:) forControlEvents:UIControlEventTouchUpInside];
[buttonCustom setTag:1000];
[self.view addSubview:buttonCustom];
Add these methods in your Controller
-(void)buttonCustom:(UIButton *)sender forEvent:(UIEvent*)event{
UITouch *touch = [[event touchesForView:sender] anyObject];
CGPoint location = [touch locationInView:self.view];
UIColor *color = [self colorOfPoint:location];
if([color isEqual:[UIColor redColor]]){
NSLog(#"red ");
}else{
NSLog(#"White Color");
}
}
- (UIColor *) colorOfPoint:(CGPoint)point
{
unsigned char pixel[4] = {0};
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(pixel, 1, 1, 8, 4, colorSpace, kCGBitmapAlphaInfoMask & kCGImageAlphaPremultipliedLast);
CGContextTranslateCTM(context, -point.x, -point.y);
[self.view.layer renderInContext:context];
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
UIColor *color = [UIColor colorWithRed:pixel[0]/255.0 green:pixel[1]/255.0 blue:pixel[2]/255.0 alpha:pixel[3]/255.0];
return color;
}
If you have multiple UIButton then use the tag property to distinguish your button.
Related
This code creating only topLeft border, but i want topRight also. How?
UIBezierPath *maskPath;
maskPath = [UIBezierPath bezierPathWithRoundedRect:self.colorSliderBackgroundView.bounds
byRoundingCorners:(UIRectCornerTopLeft|UIRectCornerTopRight)
cornerRadii:CGSizeMake(10.0,10.0)];
CAShapeLayer *borderLayer = [[CAShapeLayer alloc] init];
borderLayer.frame = self.colorSliderBackgroundView.bounds;
borderLayer.path = maskPath.CGPath;
borderLayer.lineWidth = 1.5f;
borderLayer.strokeColor = [UIColor colorWithRed:243.0/255.0 green:243.0/255.0 blue:243.0/255.0 alpha:1.0].CGColor;
borderLayer.fillColor = [UIColor clearColor].CGColor;
[self.colorSliderBackgroundView.layer addSublayer:borderLayer];
Based on your code, it looks like you want an outlined rectangle with the top-left and top-right corners rounded, as a sublayer of another view...
Create a new view class, and set it as the custom class of your colorSliderBackgroundView.
TopCornersRoundedView.h
//
// TopCornersRoundedView.h
//
// Created by Don Mag on 10/30/19.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
IB_DESIGNABLE
#interface TopCornersRoundedView : UIView
#end
NS_ASSUME_NONNULL_END
TopCornersRoundedView.m
//
// TopCornersRoundedView.m
// ObjCXIBTest
//
// Created by Don Mag on 10/30/19.
// Copyright © 2019 Don Mag. All rights reserved.
//
#import "TopCornersRoundedView.h"
#interface TopCornersRoundedView ()
#property (strong, nonatomic) CAShapeLayer *borderLayer;
#end
#implementation TopCornersRoundedView
- (instancetype)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
if (self) {
[self commonInit];
}
return self;
}
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self commonInit];
}
return self;
}
- (void)prepareForInterfaceBuilder {
[super prepareForInterfaceBuilder];
[self commonInit];
}
- (void) commonInit {
// instantiate the shape layer
_borderLayer = [CAShapeLayer new];
// set line width, stroke and fill colors
_borderLayer.lineWidth = 1.5f;
_borderLayer.strokeColor = [UIColor colorWithRed:243.0/255.0 green:243.0/255.0 blue:243.0/255.0 alpha:1.0].CGColor;
_borderLayer.fillColor = [UIColor clearColor].CGColor;
// add the shape layer as a sublayer of self
[self.layer addSublayer:_borderLayer];
}
- (void)layoutSubviews {
[super layoutSubviews];
// create a bezier path with top left and right corners rounded
// doing this in layoutSubviews will keep the frame size correct when
// the view changes size
UIBezierPath *maskPath;
maskPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds
byRoundingCorners:(UIRectCornerTopLeft|UIRectCornerTopRight)
cornerRadii:CGSizeMake(10.0,10.0)];
_borderLayer.frame = self.bounds;
_borderLayer.path = maskPath.CGPath;
}
#end
By designating this class as IB_DESIGNABLE you will even see the result at design-time:
All you need todo is this:
UIView *view = [[UIView alloc] initWithFrame:frame];
CALayer *layer = [CALayer layer];
UIBezierPath *shadowPath = [UIBezierPath bezierPathWithRoundedRect:frame byRoundingCorners:(UIRectCornerTopLeft|UIRectCornerTopRight)
cornerRadii:CGSizeMake(3.0, 3.0)];
layer.shadowPath = shadowPath.CGPath;
view.layer.mask = layer;
Or you can check this link for further detail
how to set cornerRadius for only bottom-left,bottom-right and top-left corner textview?
I have made sample demo for creating random path using UIBezier object.
I know I asked same type of question which was already asked, But I was not able to solve so.
Code
#implementation RandomShape
#synthesize randomPath,size,color;
- (void)drawRect:(CGRect)rect {
self.size = 1.0;
[self.color setStroke];
[self.randomPath stroke];
}
-(id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if(self)
{
self.randomPath = [UIBezierPath bezierPath];
[self.randomPath stroke];
}
return self;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
[self.randomPath moveToPoint:[touch locationInView:self]];
[self.randomPath setLineWidth:size];
[self setNeedsDisplay];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *mytouch=[touches anyObject];
[self.randomPath addLineToPoint:[mytouch locationInView:self]];
[self setNeedsDisplay];
}
-(void)clearRandomShape
{
self.randomPath = nil; //Set current path nil
self.randomPath = [UIBezierPath bezierPath]; //Create new path
[self.randomPath setLineWidth:2.0];
[self setNeedsDisplay];
}
1) I have select the colour from the picker view.
Now My problem is,
-->When I select colour from the picker it change all previous line colour as it is.
(It displays last colour which I choose in all random path.)
--->My requirement is I wand different different colour's random Path.
Please help Me I am confuse.
Thank you.
Write this code wherever you want to create path..
//path 1
UIBezierPath *linePath = [[UIBezierPath alloc] init];
[linePath moveToPoint:CGPointMake(100, 100)];
[linePath addLineToPoint:CGPointMake(275, 100)];
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.strokeColor = [UIColor redColor].CGColor;
shapeLayer.fillColor = [UIColor clearColor].CGColor;
shapeLayer.lineWidth = 2;
shapeLayer.lineJoin = kCALineJoinRound;
shapeLayer.lineCap = kCALineCapRound;
shapeLayer.path = linePath.CGPath;
[self.view.layer addSublayer:shapeLayer];
//Path 2
UIBezierPath *verticalLinePath = [[UIBezierPath alloc] init];
[verticalLinePath moveToPoint:CGPointMake(100, 200)];
[verticalLinePath addLineToPoint:CGPointMake(275, 200)];
CAShapeLayer *horizontalLayer = [CAShapeLayer layer];
horizontalLayer.strokeColor = [UIColor greenColor].CGColor;
horizontalLayer.fillColor = [UIColor clearColor].CGColor;
horizontalLayer.lineWidth = 2;
horizontalLayer.lineJoin = kCALineJoinRound;
horizontalLayer.lineCap = kCALineCapRound;
horizontalLayer.path = verticalLinePath.CGPath;
[self.view.layer addSublayer:horizontalLayer];
//Path
UIBezierPath *path3 = [[UIBezierPath alloc] init];
[path3 moveToPoint:CGPointMake(100, 300)];
[path3 addLineToPoint:CGPointMake(275, 300)];
CAShapeLayer *horizontalLayer3 = [CAShapeLayer layer];
horizontalLayer3.strokeColor = [UIColor blueColor].CGColor;
horizontalLayer3.fillColor = [UIColor cyanColor].CGColor;
horizontalLayer3.lineWidth = 2;
horizontalLayer3.lineJoin = kCALineJoinRound;
horizontalLayer3.lineCap = kCALineCapRound;
horizontalLayer3.path = path3.CGPath;
[self.view.layer addSublayer:horizontalLayer3];
Output of this code is ->
I am drawing a line in a UIView using drawRect & BezierPath. I also have a segmented controller with contentview1 and contentview2. I want the line to be displayed in content view1 but not contentview2. The code for my line is in a uiview file while the segmented control is in a uiviewcontroller. How can I successfully hide the line between the 2 content views.
InformationView.m (UIView)
- (void)drawRect:(CGRect)rect {
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(10.0, 10.0)];
[path addLineToPoint:CGPointMake(100.0, 100.0)];
path.lineWidth = 3;
[[UIColor blueColor] setStroke];
[path stroke];
}
InformationViewController.m (UIViewController)
segmentedControl = [[UISegmentedControl alloc] initWithItems:itemArray];
segmentedControl.frame = CGRectMake(12, 80, 300, 30);
[segmentedControl addTarget:self action:#selector(segmentAction) forControlEvents: UIControlEventValueChanged];
segmentedControl.selectedSegmentIndex = 0;
[self.view addSubview:contentView2];
[self.view addSubview:contentView ];
-(void) segmentAction {
if (segmentedControl.selectedSegmentIndex == 0) {
[contentView setHidden:NO;
[contentView2 setHidden:YES];
}
if (segmentedControl.selectedSegmentIndex == 1) {
[contentView setHidden:YES];
[contentView2 setHidden: NO];
}
I wan't to add the line to contentview so it will be hidden when another view is selected.
Add a property to InformationView
.h
#interface InformationView : UIView
#property (assign, nonatomic ,getter=isLineHidden) BOOL lineHidden;
#end
.m
#implementation InformationView
- (void)drawRect:(CGRect)rect {
if (self.lineHidden == false) {
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(10.0, 10.0)];
[path addLineToPoint:CGPointMake(100.0, 100.0)];
path.lineWidth = 3;
[[UIColor blueColor] setStroke];
[path stroke];
}
}
-(void)setLineHidden:(BOOL)lineHidden{
if (_lineHidden != lineHidden) {
_lineHidden = lineHidden;
[self setNeedsDisplay];
}
}
#end
Then,when you want to hide line
self.yourView.lineHidden = true;
I have a UIView that contains some subviews - drawn using UIBezierPath. Every subview contains a scrollview having image as mask. When I try to render image of whole view (overall), instead of making image from path, it draws image of individual rect of subviews. Let me make it clear by figure:
Original View:
What I am getting after rendering Image:
I don't know what am I missing. Please guide me. Thanks.
Code:
IrregularSquare
#interface IrregularSquare : UIView
{
UIScrollView *imageResizer;
CAShapeLayer *maskLayer;
}
#end
#implementation IrregularSquare
- (id)initWithFrame:(CGRect)frame index:(NSInteger) index
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
self.backgroundColor = [UIColor clearColor];
self.layer.backgroundColor = [UIColor clearColor].CGColor;
}
return self;
}
-(void) drawRect:(CGRect)rect
{
UIBezierPath *aPath = [UIBezierPath bezierPath];
[aPath moveToPoint:CGPointMake(CGRectGetMinX(rect), CGRectGetMinY(rect))];
[aPath addLineToPoint:CGPointMake(CGRectGetMaxX(rect), CGRectGetMinY(rect))];
[aPath addLineToPoint:CGPointMake(CGRectGetMaxX(rect) - 20, CGRectGetMidY(rect) - 10)];
[aPath addLineToPoint:CGPointMake(CGRectGetMaxX(rect) - 5, CGRectGetMaxY(rect) - 10)];
[aPath addLineToPoint:CGPointMake(CGRectGetMidX(rect) + 10, CGRectGetMaxY(rect))];
[aPath addLineToPoint:CGPointMake(CGRectGetMidX(rect) - 20, CGRectGetMaxY(rect) - 20)];
[aPath addLineToPoint:CGPointMake(CGRectGetMinX(rect), CGRectGetMaxY(rect) - 20)];
[aPath closePath];
aPath.lineWidth = 2;
[[UIColor whiteColor] setStroke];
[aPath stroke];
[self initializeImageWithPath]; //this method adds scrollview to main view and assigns an image to scrollview with mask
}
-(void) initializeImageWithPath
{
CGRect aFrame = somevalue;
self.backImage = [[UIImageView alloc] initWithFrame:aFrame];
self.backImage.contentMode = UIViewContentModeScaleAspectFill;
self.backImage.clipsToBounds = YES;
imageResizer = [[UIScrollView alloc] initWithFrame:self.bounds];
imageResizer.showsHorizontalScrollIndicator = imageResizer.showsVerticalScrollIndicator = NO;
imageResizer.scrollEnabled = YES;
imageResizer.backgroundColor = [UIColor clearColor];
imageResizer.zoomScale = 1.0;
imageResizer.delegate = self;
imageResizer.clipsToBounds = YES;
[imageResizer addSubview:self.backImage];
[self addSubview: imageResizer];
maskLayer = [CAShapeLayer layer];
maskLayer.path = [aPath CGPath];
self.layer.mask = maskLayer;
}
IrregularShapesContainer.m
#implementation IrregularShapesContainer
-(void) drawSubviews
{
for(UIView *aView in self.subviews)
[aView removeFromSuperview];
IrregularSquare *sq1 = [[IrregularSquare alloc] initWithFrame:CGRectMake(HORIPADDING, VERTICALPADDING, (self.frame.size.width - (HORIPADDING * 2) - (SPACING * 2)) * .5, (self.frame.size.height - (VERTICALPADDING) - SPACING) * .5) index:1];
[self addSubview:sq1];
[sq1.layer display];
[self randomlyPlaceImage:sq1];
sq1.irrViewDelegate = self;
//many similar instances are added in following code
}
#end
I hope my Question is clear.. Any help is appreciated.
Is there any way we can make only the selected area of a superview transparent? I have a UIView with black (alpha 0.5) background color. I am putting some hollow circles on the UIView and want the underneath UIView to be transparent so that I could see through it. Any idea
- (id)initWithFrame:(CGRect)iFrame andHollowFrames:(NSArray *)iHollowFrames withRadius:(NSNumber *)iRadius {
if ((self = [super initWithFrame:iFrame]) != nil) {
self.hollowFrames = [[NSSet setWithArray:iHollowFrames] allObjects];
self.hollowCircleRadius = iRadius;
[self addShadowView];
}
return self;
}
- (void)addShadowView {
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height) cornerRadius:0];
for (NSValue *point in self.hollowFrames) {
UIBezierPath *circlePath = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(point.CGPointValue.x - self.hollowCircleRadius.floatValue, point.CGPointValue.y - self.hollowCircleRadius.floatValue, 2.0 * self.hollowCircleRadius.floatValue, 2.0 * self.hollowCircleRadius.floatValue) cornerRadius:self.hollowCircleRadius.floatValue];
[path appendPath:circlePath];
}
[path setUsesEvenOddFillRule:YES];
CAShapeLayer *fillLayer = [CAShapeLayer layer];
fillLayer.path = path.CGPath;
fillLayer.fillRule = kCAFillRuleEvenOdd;
fillLayer.fillColor = [UIColor blackColor].CGColor;
fillLayer.opacity = 0.5;
[self.layer addSublayer:fillLayer];
}
Here is a UIView subclass solution. In order for this to work you must leave the superviews backgroundColor property as nil witch is the default value. If this UIView-subclass is in the storyboard then make sure you set the background color to "Clear color" in the attributes inspector.
- (void)drawRect:(CGRect)rect
{
CGContextRef ctx = UIGraphicsGetCurrentContext();
UIColor *blackBackgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.5];
CGContextSetFillColorWithColor(ctx, blackBackgroundColor.CGColor);
CGContextFillRect(ctx, rect);
CGRect transparentPart = CGRectMake(10, 10, 120, 80);
CGContextClearRect(ctx, transparentPart);
}