I'm trying to make custom badge. For that I make subclass of UIButton and remake - (void)drawRect:(CGRect)rect like this:
- (void)drawRect:(CGRect)rect
{
self.titleLabel.font = [UIFont systemFontOfSize:12];
[self setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
self.userInteractionEnabled = NO;
self.layer.borderWidth = 1.5f;
self.layer.cornerRadius = rect.size.width / 2;
self.layer.shouldRasterize = YES;
self.layer.rasterizationScale = [[UIScreen mainScreen] scale];
self.layer.backgroundColor = [UIColor grayColor].CGColor;
self.layer.borderColor = [UIColor grayColor].CGColor;
}
And everything is good except alignment. It is a little upper than it should be. Looks like this:
What to do?
#property(nonatomic) NSTextAlignment textAlignment;
// default is NSTextAlignmentLeft
It's an attribute of UILabel.
Here is badge I need: https://github.com/jessesquires/JSCustomBadge . Works perfect!
Related
Here is my code to add a shadow on my uibutton which is created using a .XIB file
UIBezierPath *shadowPathEndbtn = [UIBezierPath bezierPathWithRect:CGRectMake(0, self->_navigationView.frame.size.height - 70,[UIScreen mainScreen].bounds.size.width , 2)];
self->_EndButton.layer.masksToBounds = NO;
self->_EndButton.layer.shadowColor = [UIColor blackColor].CGColor;
self->_EndButton.layer.shadowOffset = CGSizeMake(0.0f, 5.0f);
self->_EndButton.layer.shadowOpacity = 0.7f;
self->_EndButton.layer.shouldRasterize = YES;
self->_EndButton.layer.shadowPath = shadowPathForEndbtn.CGPath;
I am able to set the shadow using this code but this code makes my button text look blury. I am unable to figure out the exact reason behind this. Any help is Appreciated!
self->_EndButton.layer.masksToBounds = false
self->_EndButton.layer.shadowColor = [UIColor blackColor].CGColor
self->_EndButton.layer.contentsScale = [[UIScreen mainScreen]scale];
self->_EndButton.layer.shadowOpacity = 0.7f;
self->_EndButton.layer.shadowRadius = 10.0;
self->_EndButton.layer.shadowOffset = CGSizeMake(0,0)
This will give shadow and also the test is not blurry
Set button background color
self.EndButton.BackgroundColor=[UIColor WhiteColor];
I subclassed UIButton and did some customized drawing in drawRect method such as drawing NSAttributedString and UIImage.
However, after I did this, the customized UIButton doesn't gray out when enabled is set to NO. I think my customized drawing happens on top of its state. How do I deal with this?
Sharing my drawing code here:
- (void)drawRect:(CGRect)rect
{
// Drawing code
if (self.faceUp) {
[self drawCardText:self.card.contents inRect:self.bounds];
} else {
[self drawCardImage:[UIImage imageNamed:CardBackImageName] inRect:self.bounds];
}
}
- (void)drawCardText:(NSString *)text inRect:(CGRect)rect
{
// set background color to white so text can be shown
[[UIColor whiteColor] setFill];
[[UIBezierPath bezierPathWithRect:rect] fill];
UIFont *preferedFont = [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
UIFont *actualFont = [UIFont fontWithName:preferedFont.fontName
size:hypotf(rect.size.width, rect.size.height) / 6.0];
NSDictionary *attributes = #{NSFontAttributeName: actualFont};
NSAttributedString *attributedText = [[NSAttributedString alloc] initWithString:text attributes:attributes];
[self setAttributedTitle:attributedText forState:UIControlStateNormal];
}
- (void)drawCardImage:(UIImage *)image inRect:(CGRect)rect
{
UIGraphicsBeginImageContextWithOptions(rect.size, NO, 1.0f);
[image drawInRect:rect];
UIImage *actualImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[[UIColor colorWithPatternImage:actualImage] setFill];
[[UIBezierPath bezierPathWithRect:rect] fill];
}
You might have to add an overlay view with grey color and some alpha yourself. Remove the overlay when button is enabled again.
You can add this method to CustomButton class.
-(void)setEnabled:(BOOL)enabled{
//disableLayer.hidden = !enabled;
if (enabled) {
//self.enabled = YES;
self.alpha = 1.0;
}else{
//self.enabled = NO;
self.alpha = 0.7;
}
[super setEnabled:enabled];
}
For enable or disable call-
[customButtob setEnabled:buttonStatus];
If you want to change color, add a background layer, and toggle its hidden property in setEnabled method.
disableLayer = [CALayer layer];
disableLayer.backgroundColor = [UIColor colorWithRed:20/255.0f green:20/255.0f blue:20/255.0f alpha:1.0f].CGColor;
disableLayer.frame = self.layer.bounds;
disableLayer.hidden = YES;
[self.layer insertSublayer:disableLayer below:otherLayer];
I think you share some more details of your implementation. Moreover I am sure you have called
Super methods in the customized methods at first call.
You have to override the setEnabled: method of your CustomButton
-(void)setEnabled:(BOOL)enabled
{
if (!enabled) {
[self setAlpha:0.2f];
}
}
OR
If you have to change the color of UIButton in its disabled state. Yo can change drawRect: method as
Make a assign property of BOOL type variable (say isEnabled)
-(void)drawRect:(CGRect)rect
{
[[UIColor redColor] setFill];
UIRectFill(rect);
if (!self.isEnabled) {
[[UIColor blackColor] setFill];
UIRectFill(rect);
}
}
-(void)setEnabled:(BOOL)enabled
{
self.isEnabled = enabled;
[self setNeedsDisplay];
}
You can use
btn.userInteractionEnabled = NO;
Or you can use
btn.enabled = NO;
Hope this helps... :)
Edit:
I think you can use this
[btn setTitleColor:[UIColor grayColor] forState:UIControlStateDisabled];
Add this:
-(void)setEnabled:(BOOL)enabled{
if (!enabled) {
self.alpha = 0.3;
}else{
self.alpha = 1.0;
}
[super setEnabled:enabled];
}
add a method which can help u for enable and disable of your button just add this method in custom button class
//in customButton.h file
#import <UIKit/UIKit.h>
#interface CustomButton : UIButton
#property (nonatomic,assign) BOOL faceUp;//your property
- (void)makeButtonDisable:(BOOL)disable;//method to handle disable and enable
#end
//in customButton.m file
#import "CustomButton.h"
#implementation CustomButton
{
CALayer *grayLayer;//layer to handle disable and enable
}
#synthesize faceUp;
// in initilization method
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if(self)
{
grayLayer = [CALayer layer];
grayLayer.frame = frame;
[self.layer addSublayer:grayLayer]; //add the grayLayer during initialisation
}
return self;
}
//your code that put above
- (void)drawRect:(CGRect)rect
{
// Drawing code
if (self.faceUp) {
[self drawCardText:self.card.contents inRect:self.bounds];
} else {
[self drawCardImage:[UIImage imageNamed:CardBackImageName] inRect:self.bounds];
}
}
- (void)drawCardText:(NSString *)text inRect:(CGRect)rect
{
// set background color to white so text can be shown
[[UIColor whiteColor] setFill];
[[UIBezierPath bezierPathWithRect:rect] fill];
UIFont *preferedFont = [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
UIFont *actualFont = [UIFont fontWithName:preferedFont.fontName
size:hypotf(rect.size.width, rect.size.height) / 6.0];
NSDictionary *attributes = #{NSFontAttributeName: actualFont};
NSAttributedString *attributedText = [[NSAttributedString alloc] initWithString:text attributes:attributes];
[self setAttributedTitle:attributedText forState:UIControlStateNormal];
}
- (void)drawCardImage:(UIImage *)image inRect:(CGRect)rect
{
UIGraphicsBeginImageContextWithOptions(rect.size, NO, 1.0f);
[image drawInRect:rect];
UIImage *actualImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[[UIColor colorWithPatternImage:actualImage] setFill];
[[UIBezierPath bezierPathWithRect:rect] fill];
}
//add this method
- (void)makeButtonDisable:(BOOL)disable
{
if(disable)
{
grayLayer.backgroundColor = [UIColor colorWithRed:201.0f/255.0f green:201.0f/255.0f blue:201.0f/255.0f alpha:5.0f].CGColor;
self.userInteractionEnabled = NO;
grayLayer.opacity = 0.5f;
self.alpha = 0.5f;
}
else
{
grayLayer.backgroundColor = [UIColor clearColor].CGColor;
self.userInteractionEnabled = YES;
grayLayer.opacity = 0.0f;
self.alpha = 1.0f;
}
}
in the controller where u are using this button
//some where in the controller u want to disable the button just do like this
//to disable
[button makeButtonDisable:YES]; //button is an instance of customCell
//to enable
[button makeButtonDisable:NO]; //button is an instance of customCell
I am trying to set the frame size of an UIImageView inside a subclass of UICollectionCell but it does not work. I use storyboard.
In the code, everything works but the last line regarding the imageView.
If i put the code in drawRect it works ok.
- (id)initWithCoder:(NSCoder *)decoder {
if ((self = [super initWithCoder:decoder]))
{
self.backgroundColor = [UIColor colorWithWhite:0.85f alpha:1.0f];
self.layer.borderColor = [UIColor lightGrayColor].CGColor;
self.layer.borderWidth = 1.0f;
self.layer.cornerRadius = 8.0f;
self.layer.masksToBounds = NO;
self.layer.shadowColor = [UIColor blackColor].CGColor;
self.layer.shadowRadius = 3.0f;
self.layer.shadowOffset = CGSizeMake(0.0f, 2.0f);
self.layer.shadowOpacity = 0.5f;
self.imageView.frame = CGRectMake(10, 10, 50, 50);
}
That is because your imageView (I believe it's and IBOutlet) is not yet initialized, it's still nil. Be aware that some of you variables/properties are being initialized inside init's method. Set you breakpoint and you will see. Try set the imageView values somewhere else such as drawRect (as you suggest) or awakeFromNib.
Is the image view being moved later by a different object? Try moving that code into layoutSubviews
Add this method:
- (void) layoutSubviews
{
[super layoutSubviews];
self.imageView.frame = CGRectMake(10, 10, 50, 50);
}
I am trying to draw a simple line connecting two points. I think i got the right code for that in my drawLine method. No lines appear at all and I am pretty sure it has to do with the View I am calling with and the one I want to draw on. The following code is where I build my next View in code (data coming from a web service). The View gets created just fine and all buttons and objects appear.
I am trying to add lines to the View I'm creating (Next) dynamically and not sure how to get that done. From the Errors I get (invalid context 0x0) it seems I am doing something out of order. Trying to display on a view that is not there. how than can I get this done? Any advice would be appreciated.
I realize that passing on the View might not be the right answer. I am in the midst of trial and error here.
To clarify: I am calling drawLine here:
[nextView.view addSubview:next];
Thanks,
Shai
-(void) drawView
{
CGRect rec;
CGFloat width = [UIScreen mainScreen].bounds.size.width;
CGFloat height = [UIScreen mainScreen].bounds.size.height;
UIView *next = [[UIView alloc]initWithFrame:CGRectMake(0, 0, height, width)];
next.backgroundColor = [UIColor whiteColor];
next.userInteractionEnabled = YES;
next.multipleTouchEnabled = YES;
nextView = [UIViewController alloc];
[nextView setTitle: as_objectDesc];
for (object in viewObjects)
{ // ratio based on Ipad 2 screen size conversion from the Datawindow size - alter to support other device
CGFloat objWidth = object.Width/3.83;
CGFloat objHeight = object.Height/2.78;
CGFloat objXPoint = object.positionX/3.83;
CGFloat objYPoint = object.positionY/2.78;
if ([object.Shape isEqualToString:#"text"])
{
rec = CGRectMake(objXPoint, objYPoint, objWidth, objHeight);
UILabel *myLabel = [[UILabel alloc] initWithFrame:rec];
myLabel.backgroundColor = [UIColor clearColor];
myLabel.text = object.objectTag;
myLabel.lineBreakMode = NSLineBreakByWordWrapping;
if ([object.description isEqualToString:#"Header"])
{
myLabel.font = [UIFont systemFontOfSize:20];
}
else
{
myLabel.font = [UIFont systemFontOfSize:10];
}
[next addSubview:myLabel];
}
else if ([object.Shape isEqualToString:#"line"])
{
**[self drawLine:nextView.view];**
}
else
{
UIButton *myButton = [UIButton buttonWithType:UIButtonTypeCustom];
if ([object.Shape isEqualToString:#"ellipse"])
{
UIImage * buttonImage;
if ([object.Color isEqualToString:#"255"])
{
buttonImage = [UIImage imageNamed:#"redBackground.png"];
}
else if ([object.Color isEqualToString:#"65535"])
{
buttonImage = [UIImage imageNamed:#"yellowBackground.png"];
}
else if ([object.Color isEqualToString:#"GRAY"])
{
buttonImage = [UIImage imageNamed:#"graybground.PNG"];
}
else if ([object.Color isEqualToString:#"BLACK"])
{
buttonImage = [UIImage imageNamed:#"BlackBackground.png"];
}
[myButton setBackgroundImage:buttonImage forState: UIControlStateNormal];
objWidth = objHeight;
rec = CGRectMake(objXPoint, objYPoint, objWidth, objHeight);
myButton.frame = rec;
myButton.clipsToBounds = YES;
myButton.layer.cornerRadius = objWidth/2;
}
else
{
rec = CGRectMake(objXPoint, objYPoint, objWidth, objHeight);
if ([object.Color isEqualToString:#"255"])
myButton.backgroundColor = [UIColor redColor];
else if ([object.Color isEqualToString:#"65535"])
myButton.backgroundColor = [UIColor yellowColor];
else if ([object.Color isEqualToString:#"GRAY"])
myButton.backgroundColor = [UIColor grayColor];
else if ([object.Color isEqualToString:#"BLACK"])
myButton.backgroundColor = [UIColor blackColor];
}
[[myButton layer] setBorderWidth:1.0f];
[[myButton layer] setBorderColor:[UIColor blackColor].CGColor];
myButton.enabled = YES;
myButton.accessibilityHint = object.objectTag;
myButton.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
myButton.titleLabel.textAlignment = NSTextAlignmentCenter;
myButton.titleLabel.font = [UIFont systemFontOfSize:13];
[myButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[myButton addTarget:self action:#selector(btnClick:) forControlEvents:UIControlEventTouchUpInside];
myButton.frame = rec;
[myButton setTitle:object.description forState:UIControlStateNormal];
// Check if an Empty Rectangle
NSRange test =[myButton.accessibilityHint rangeOfString:#"r_"];
if (test.location == 0)
{
[next sendSubviewToBack:myButton];
[myButton setEnabled:NO];
}
[next addSubview:myButton];
}
UIPinchGestureRecognizer *twoFingerPinch = [[UIPinchGestureRecognizer alloc]
initWithTarget:self
action:#selector(twoFingerPinch:)]
;
[[nextView view] addGestureRecognizer:twoFingerPinch];
[next addSubview:activityIndicator];
[next bringSubviewToFront:activityIndicator];
}
[nextView.view addSubview:next];
[self dismissViewControllerAnimated:NO completion:nil];
[self.navigationController pushViewController:nextView animated:NO];
}
- (void)drawLine:(UIView *) view
{
CGFloat x1 = object.positionX;
CGFloat y1 = object.positionY;
CGFloat x2 = object.positionX2;
CGFloat y2 = object.positionY2;
CGContextRef context = UIGraphicsGetCurrentContext();
if ([object.Color isEqualToString:#"255"])
CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);
else if ([object.Color isEqualToString:#"65535"])
CGContextSetStrokeColorWithColor(context, [UIColor yellowColor].CGColor);
else if ([object.Color isEqualToString:#"GRAY"])
CGContextSetStrokeColorWithColor(context, [UIColor grayColor].CGColor);
else if ([object.Color isEqualToString:#"BLACK"])
CGContextSetStrokeColorWithColor(context, [UIColor blackColor].CGColor);
CGContextSetLineWidth(context, 3.0);
CGContextBeginPath(context);
CGContextMoveToPoint(context, x1, y1);
CGContextAddLineToPoint(context, x2, y2);
CGContextStrokePath(context);
}
I end up figuring this up days a go and thought I would share here. I might have added to much code in my question which did not help to simplify it to others (no comments).
What this came down to is when trying to Draw a line you need to override the DrawRect Method of the UIView subclass and not the UIViewController as I did. There is no Error thrown if you call DrawRect from your UIViewController but it doesn't do anything. I missed that small detail.
What added to the complexity of finding this out ans solving this was that I was creating all of it Programmatically and initially didn't subclass UIView at all. I ended up adding all the Points in an NSMutablearray and redrawing the lines in the following class after the newly View got created:
#import "draw.h"
#implementation draw
#synthesize lines;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
// Initialization code
}
return self;
}
-(void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
for (line *myLine in lines)
{
if ([myLine.color isEqualToString:#"255"])
CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);
else if ([myLine.color isEqualToString:#"65535"])
CGContextSetStrokeColorWithColor(context, [UIColor yellowColor].CGColor);
else if ([myLine.color isEqualToString:#"GRAY"])
CGContextSetStrokeColorWithColor(context, [UIColor grayColor].CGColor);
else if ([myLine.color isEqualToString:#"BLACK"])
CGContextSetStrokeColorWithColor(context, [UIColor blackColor].CGColor);
int setNew = myLine.Width/4;
CGContextSetLineWidth(context, (CGFloat)setNew);
CGContextBeginPath(context);
CGContextMoveToPoint(context, myLine.x1, myLine.y1);
CGContextAddLineToPoint(context, myLine.x2, myLine.y2);
CGContextStrokePath(context);
}
}
#end
I have a UITextView where I add some drop shadow to the frame, but when I write, the text got also the same shadow. How to avoid this problem?
My code :
commentary = [[UITextView alloc]initWithFrame:CGRectMake(10, 435, 230, 120)];
commentary.font = STANDARDFONT;
commentary.backgroundColor = BACKGROUND;
commentary.layer.shadowColor = [UIColor blackColor].CGColor;
commentary.layer.shadowOffset = CGSizeMake(2, 2);
commentary.layer.shadowOpacity = 0.8;
commentary.layer.shadowRadius = 2.0;
commentary.layer.borderColor = [UIColor grayColor].CGColor;
commentary.layer.borderWidth = 1.5;
commentary.layer.cornerRadius = 5;
commentary.layer.masksToBounds = NO;
commentary.clipsToBounds = NO;
[self addSubview:commentary];
BACKGROUND and STANDARDFONT is [UICOLOR clearColor].CGColorand [UIFont fontWithName:#"TimesNewRomanPSMT" size:16];
Try setting the layer background color also: commentary.layer.backgroundColor = BACKGROUND.CGColor