I've created a really simple custom flat button:
#implementation HAFlatButton
+ (id)buttonWithColor:(UIColor *)aColor
{
id button = [super buttonWithType:UIButtonTypeCustom];
[button setFlatColor:aColor];
CGRect frame = [button frame];
frame.size.height = 200;
[button setFrame:frame];
return button;
}
+ (id)defaultButton
{
return [HAFlatButton buttonWithColor:[HAColors buttonColor]];
}
- (void)setFlatColor:(UIColor *)flatColor
{
_flatColor = flatColor;
[self setNeedsDisplay];
}
- (void)drawRect:(CGRect)rect {
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = UIGraphicsGetCurrentContext();
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:4.0];
CGContextSaveGState(context);
[path addClip];
[_flatColor setFill];
CGContextFillRect(context, rect);
CGColorSpaceRelease(colorSpace);
}
#end
When I add a button to my auto layout using [HAFlatButton defaultButton], it's just barely taller than the button text, but when I add a [UIButton buttonWithType:UIButtonTypeRoundedRect] to my layout, it has the proper insets around the label.
What am I doing wrong?
You need to do one or more of the following:
Add a height constraint.
Override the intrinsicSize return value.
Adjust the vertical content hugging priority.
Related
Hi i want to create a quarter transparent hole at right bottom on overlay UIView.
i am able to solve it using below code. But it does not look right as i am creating a rectangle outside the bond of view.
What i have tried:
#implementation PartialTransparentView
- (id)initWithBottomRightCornerRadiusForView:(UIView *)view withRadius:(CGFloat)radius
{
[self commonInitWithRect:CGRectMake(view.frame.size.width - radius, view.frame.size.height - radius, radius*2, radius*2)];
self = [super initWithFrame:CGRectMake(0, 0, 5000, 5000)];//**it does not look right to me**
if (self) {
// Initialization code
self.opaque = NO;
}
return self;
}
-(void)commonInitWithRect:(CGRect)rect{
backgroundColor = [UIColor colorWithWhite:1 alpha:0.75];
rectToBeSurrounded = rect;
}
- (void)drawRect:(CGRect)rect {
[backgroundColor setFill];
UIRectFill(rect);
CGFloat x = rectToBeSurrounded.origin.x;
CGFloat y = rectToBeSurrounded.origin.y;
CGFloat width = rectToBeSurrounded.size.width;
CGFloat height = rectToBeSurrounded.size.height;
//create outer square
CGFloat outerX = (x - width/2);
CGFloat outerY = y - height/2;
CGFloat outerWidth = 2*width;
CGFloat outerHeight = outerWidth;
//create outer square
CGRect outerRect = CGRectMake(outerX, outerY, outerWidth, outerHeight);
CGRect holeRectIntersection = CGRectIntersection( outerRect, rect );
CGContextRef context = UIGraphicsGetCurrentContext();
if( CGRectIntersectsRect( holeRectIntersection, rect ) )
{
CGContextAddEllipseInRect(context, holeRectIntersection);
CGContextClip(context);
CGContextClearRect(context, holeRectIntersection);
CGContextSetFillColorWithColor( context, [UIColor clearColor].CGColor );
CGContextFillRect( context, holeRectIntersection);
}
}
Now i am using above code as :
PartialTransparentView *transparentView = [[PartialTransparentView alloc] initWithBottomRightCornerRadiusForView:self.view withRadius:50];
[self.view addSubview:transparentView];
Result as expected:
i know my solution will break if i have to acheive same thing but on top left of view.
what i am looking for just provide center (x, y) and radius for circle and get desired results.
Thanks
Basd on Mr.T
UIView *transparentView = [[UIView alloc] initWithFrame:self.view.frame];
[transparentView setBackgroundColor:[UIColor colorWithWhite:1 alpha:0.75]];
[self.view addSubview:transparentView];
circleView *acircleView = [[circleView alloc] initWithFrame:CGRectMake(50, 50, 60, 60)];
[acircleView setBackgroundColor:[UIColor grayColor]];
[transparentView addSubview:acircleView];
and circleView.m
- (void)drawRect:(CGRect)rect {
// Drawing code
//// Oval Drawing
UIBezierPath* ovalPath = [UIBezierPath bezierPathWithOvalInRect: CGRectMake(50, 50, 60, 60)];
[UIColor.grayColor setFill];
[ovalPath fill];
}
output:
My suggestions is to add the transparent view as a separate view on your view controller. This can be either done on storyboard,so that you can set the background color and the alpha value to give the transparent effect!!!
Now create another view to make the circle and add it to transparent view, , and move this view on the transparent view according to your need!!!
Create the circle using bezier path:
circleView.m
- (void)drawRect:(CGRect)frame {
//// Oval Drawing
UIBezierPath* ovalPath = [UIBezierPath bezierPathWithOvalInRect: CGRectMake(CGRectGetMinX(frame), CGRectGetMinY(frame), 60, 60)];
[UIColor.grayColor setFill];
[ovalPath fill];
}
For testing purpose, I have created a circle view on my IB and created an outlet property in my view controller.
HEre is the screenshot.
Now to move the circle, I can simply change the frame of the circle view, wherever I need.
For example, If I want to move it to top left, I simply do:
-(void)moveCircleViewwithX:(float) x withY:(float) y{
_cView.frame=CGRectMake(x, y, _cView.frame.size.width, _cView.frame.size.height);
}
The result will be:
Update
Put the following the drawRect method of transparentView:
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGRect transparentPart = self.seeRect; //this is the rect of the circle view
CGContextAddEllipseInRect(ctx,transparentPart); //make the circle shape
CGContextClip(ctx);
CGContextClearRect(ctx, transparentPart);
and in your view controller:
when you want to apply the mask i.e the transparent for both circle and for the transparent layer:
-(void)applyMask{
[_cView setCircleColor:[UIColor clearColor]]; //circle view bezier path color
[_cView setNeedsDisplay];
[_tView setSeeRect:_cView.frame]; //set the transparency cut on transparency view
[_tView setNeedsDisplay];
}
Once you do this, you will get the transparency view!!!
You can move the circle by simply calling
[self moveCircleViewwithX:-30 withY:10]; //top left corner
and you can apply the transparency mask by simply calling:
[self applyMask];
So, the final result after you call the applyMask method will be:
i have a UIButton that when I tap it, goes down giving effect of a click/tap.
My problem is that I have to add a black border around UIButton, but adding this keeps border static and it doesn't move down with the UIButton, the code that let me have click effect on UIButton is this:
- (void)drawRect:(CGRect)rect
{
[super drawRect:rect];
CGSize size = self.bounds.size;
CGContextRef context = UIGraphicsGetCurrentContext();
CGRect faceRect = CGRectMake(0, 0, size.width, size.height);
UIGraphicsBeginImageContextWithOptions(faceRect.size, NO, 0.0);
[[self faceColorForState:self.state] set];
[self drawRoundedRect:faceRect radius:self.radius context:UIGraphicsGetCurrentContext()];
UIImage *faceImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[[self sideColorForState:self.state] set];
CGRect sideRect = CGRectMake(0, size.height * 1.0 / 4.0, size.width, size.height * 3.0 / 4.0);
[self drawRoundedRect:sideRect radius:self.radius context:context];
CGRect faceShrinkedRect;
if(self.state == UIControlStateSelected || self.state == UIControlStateHighlighted) {
faceShrinkedRect = CGRectMake(0, self.depth, size.width, size.height - self.margin);
} else {
faceShrinkedRect = CGRectMake(0, 0, size.width, size.height - self.margin);
}
[faceImage drawInRect:faceShrinkedRect];
}
You're overcomplicating things using drawRect:. The easiest way to do this is to create 2 images for the background of your button, one with a black border. Then use:
[myButton setBackgroundImage:[UIImage imageNamed:<up-image>] forState:UIControlStateNormal];
[myButton setBackgroundImage:[UIImage imageNamed:<down-image>] forState:UIControlStateHighlighted];
You could re-use your code to create the images in code if necessary.
Maybe a category method on UIImage say:
+(UIImage *)buttonBackgroundImageWithColor:(UIColor *) color highlighted: (BOOL) highlighted
I'm having trouble drawing in the drawRect method of my custom UITableViewCell. Here is the code I am using
- (void)drawRect:(CGRect)rect
{
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGPoint origin = _faceView.frame.origin;
CGFloat width = _faceView.frame.size.width;
CGFloat height = _faceView.frame.size.height;
CGFloat border = 2.0f;
CGPoint startPt = CGPointMake(origin.x + width/2, self.frame.size.height);
CGContextBeginPath(ctx);
CGContextMoveToPoint(ctx, startPt.x, startPt.y);
CGPoint basePt = CGPointMake(startPt.x, origin.y - height - border);
CGContextAddLineToPoint(ctx, basePt.x, basePt.y);
CGRect circleRect = CGRectMake(origin.x - border, origin.y - border, width + 2 * border, height + 2 * border);
CGContextAddEllipseInRect(ctx, circleRect);
UIColor *color = [UIColor redColor];
CGContextSetFillColorWithColor(ctx, color.CGColor);
CGContextSetStrokeColorWithColor(ctx, color.CGColor);
CGContextSetLineWidth(ctx, 1.0f);
CGContextDrawPath(ctx, kCGPathFillStroke);
}
I've debugged to make sure that all of the numeric values make sense and it appears that they do. Can't really find out why nothing is being drawn on screen.
For what its worth, this is a cell defined in a nib as well. And i'm building with the iOS 7 sdk.
Any ideas?
tahnks
Try set backgroungcolor property to transparent color
self.backgroundColor = [UIColor clearColor]
You probably shouldn't do this in UITableViewCell's own drawRect. Instead, create a custom UIView and add it as a subview.
See also this answer.
You have to set
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
.....
[cell setNeedsDisplay];
return cell;
}
Try set backgroundColor of contentView property to clear color
self.contentView = [UIColor clearColor];
I have placed a view on a viewController and I want to draw a rectangle in this view, but with a custom height. I determine the height based on a parameter in my viewController.
So for example. If my parameter is 50, I want the rectangle to have the height of 50% of the UIView.
2 questions:
how can I pass the height to the custom drawRect?
how do I make the rectangle be placed on the bottom of the UIView?
I have placed the view using Interface Builder and I have implemented the drawRect in a subclass of UIView and used this as Custom Class for my UIView.
So in the custom class I have:
- (void)drawRect:(CGRect)rect
{
// Drawing code
CGContextRef context = UIGraphicsGetCurrentContext();
UIColor * lightGrayColor = [UIColor colorWithRed:230.0/255.0 green:230.0/255.0 blue:230.0/255.0 alpha:1.0];
CGRect paperRect = self.bounds;
drawLinearGradient(context, paperRect, lightGrayColor.CGColor, [UIColor clearColor].CGColor);
}
void drawLinearGradient(CGContextRef context, CGRect rect, CGColorRef startColor, CGColorRef endColor)
{
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGFloat locations[] = { 0.0, 1.0 };
NSArray *colors = #[(__bridge id) startColor, (__bridge id) endColor];
CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef) colors, locations);
CGPoint startPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMinY(rect));
CGPoint endPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMaxY(rect));
CGContextSaveGState(context);
CGContextAddRect(context, rect);
CGContextClip(context);
CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, 0);
CGContextRestoreGState(context);
CGGradientRelease(gradient);
CGColorSpaceRelease(colorSpace);
}
This draws a nice gradient rectangle in my view but it fills the complete UIView.
This is because of the self.bounds.
I have added a property *height to my custom class, but I don't know how to fill this from my viewController. So I want it to start at the bottom off the UIView, and make it as high as I have determined (a % of the real height).
Anybody knows how I can achieve this?
have you set your custom view class in identity inspector in interface builder?
you can set the height property from your viewController:
((MyViewClass *) self.myView).height = myCalculatedValue;
then implement drawRect:
- (void)drawRect:(CGRect)rect
{
// Drawing code
CGContextRef context = UIGraphicsGetCurrentContext();
UIColor * lightGrayColor = [UIColor colorWithRed:230.0/255.0 green:230.0/255.0 blue:230.0/255.0 alpha:1.0];
CGRect paperRect = self.bounds;
paperRect.origin.y = paperRect.size.height - self.height;
paperRect.size.height = self.height;
//assuming your height property is of CGFloat type
drawLinearGradient(context, paperRect, lightGrayColor.CGColor, [UIColor clearColor].CGColor);
}
this will draw your gradient from (height) points above the bottom to the bottom
I think you can get calculate 50% of screen height and then substract new view height from the full screen Height
youParameter = 50; // Lets assume this is your parametere
int heightOfView = ([UIScreen mainScreen].bounds.size.height * yourParameter) / 100;
// For placing the view to the bottom;
CGRect newFrame;
frame.origin.y = [UIScreen mainScreen].bounds.size.height - heightOfView;
frame.origin.x = 0;
frame.size.width = [UIScreen mainScreen].bounds.size.width; // assuming it will take full width
frame.size.height = heightOfView;
youViewToChange.frame = newFrame; // normally do this or
To pass the value to drawRect you can do:
[self drawRect:newFrame];
In my UITableViewController's cells, I want to display a circle with a number in it. I am using UIBezierPath's bezierPathWithOvalInRect: to draw the circle.
Unfortunately, while I can set the fill color to be clearColor, the unused portion of the CGRect passed to bezierPathWithOvalInRect: is black.
How do I get rid of the black area created?
Partial screenshot for reference:
(I eventually hope to get that number inside the circle)
Code:
LTTTableViewCell:
- (void)awakeFromNib {
[super awakeFromNib];
// Create a square view using the height of the cell
CGRect positionFrame = CGRectMake(0, 0, self.bounds.size.height, self.bounds.size.height);
LTTDrawBallView *drawBallView = [[LTTDrawBallView alloc] initWithFrame:positionFrame];
[self.contentView addSubview:drawBallView];
}
LTTDrawBallView:
- (void)drawRect:(CGRect)rect
{
// Create a new rect with some padding
// + create a circle from this new rect:
CGRect box = CGRectInset(self.bounds, self.bounds.size.width * 0.1f, self.bounds.size.height * 0.1f);
UIBezierPath *ballBezierPath = [UIBezierPath bezierPathWithOvalInRect:box];
[[UIColor whiteColor] setStroke];
[[UIColor greenColor] setFill]; // Green here to show the black area
[ballBezierPath stroke];
[ballBezierPath fill];
[self setBackgroundColor:[UIColor clearColor]]; // Happens with and without this line
}
In the init method of your LTTDrawBallView, include the code:
self.opaque = NO;
self.backgroundColor = [UIColor clearColor];