Unable to make UILabel text glow - ios

I'm running the following code in viewDidLoad, it is applying the glow outside the label not on the text. Please advise.
lbl_score.font = myfont;
lbl_score.alpha = 1.0;
lbl_score.textColor = UIColor.greenColor;
lbl_score.layer.shadowColor = [[UIColor blueColor] CGColor];
lbl_score.layer.shadowOffset = CGSizeMake(0.0, 0.0);
lbl_score.layer.shadowRadius = 30.0f;
lbl_score.layer.shadowOpacity = 0.9;
lbl_score.layer.masksToBounds = NO;
I've imported QuartzCore/QuartzCore.h". I would like to apply the glow only on the label text.
Thanks

To apply a glow to the actual text in a label, you have to override drawTextInRect on the label itself. You're setting a shadow on the label's layer, which is a rectangle.
The override is quite simple. You just adjust the graphics context, call super, then restore the graphics context:
-(void)drawTextInRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
CGContextSetShadowWithColor(context, CGSizeZero, 30.0, [UIColor blueColor].CGColor);
[super drawTextInRect:rect];
CGContextRestoreGState(context);
}

You are putting a shadow on the layer, which is rectangular. UILabel has shadowColor and shadowOffset properties which you should use instead. You can’t set a separate opacity for the shadow this way, but you can bake it into the UIColor that you pass for the shadow color.
lbl_score.font = myfont;
lbl_score.alpha = 1.0;
lbl_score.textColor = UIColor.greenColor;
lbl_score.shadowColor = [[UIColor blueColor] colorWithAlphaComponent:0.9];
lbl_score.shadowOffset = CGSizeMake(0.0, 0.0);
Unfortunately, you can’t set a shadow radius in this way. If you need to change the radius, look at doing your own custom drawing in -drawRect: instead.

I found code similar to jrturton ,but with more customisation.
This is working for me.
DTGlowingLabel.h
#interface DTGlowingLabel : UILabel {
}
#end
DTGlowingLabel.m
#import "DTGlowingLabel.h"
#implementation DTGlowingLabel
- (void) drawRect:(CGRect)rect
{
CGContextRef ctx = UIGraphicsGetCurrentContext();
UIColor *insideColor = [UIColor colorWithRed:69.0/255.0 green:254.0/255.0 blue:0 alpha:1];
UIColor *outlineColor = [UIColor colorWithRed:22.0/255.0 green:145.0/255.0 blue:0 alpha:0.8];
UIColor *blurColor = [UIColor colorWithRed:104.0/255.0 green: 248.0/255.0 blue:0 alpha:0.7];
CGContextSetStrokeColorWithColor(ctx, outlineColor.CGColor);
CGContextSetFillColorWithColor(ctx, insideColor.CGColor);
CGContextSetLineWidth(ctx, self.font.pointSize/60.0);
CGContextSetShadowWithColor(ctx, CGSizeMake(0, 0), self.font.pointSize / 10.0, blurColor.CGColor);
CGContextSetTextDrawingMode(ctx, kCGTextFillStroke);
[self.text drawInRect:self.bounds withFont:self.font lineBreakMode:self.lineBreakMode alignment:self.textAlignment];
}
#end
Source : http://www.cocoanetics.com/2010/01/uilabels-with-neon-effect/

Related

Place text on top of other CALayer in drawRect

I am trying to show text above CALayer but somehow I am not able to achieve it. I have used following code:
- (void)drawRect:(CGRect)rect
{
self.layer.sublayers = nil;
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSaveGState(ctx);
// Code to show grid lines clipped
CGRect overallRectForBarItem = CGRectMake(20, 20, 176, 35);
CAShapeLayer *barItemShape = [CAShapeLayer layer];
barItemShape.frame = overallRectForBarItem;
barItemShape.path = [UIBezierPath bezierPathWithRect:overallRectForBarItem].CGPath;
barItemShape.strokeColor = [UIColor lightGrayColor].CGColor;
barItemShape.fillColor = [UIColor lightGrayColor].CGColor;
[self.layer addSublayer:barItemShape];
[self drawTextForBarItem:#"TESTING" inRect:CGRectMake(100, 40, 35, 0)];
// Other code clipped
CGContextRestoreGState(ctx);
}
-(void) drawTextForBarItem:(NSString*)barItemTitle inRect:(CGRect)rect
{
float actualFontSize = 14.0;
UIFont *font = [ISUtility getSystemFont:actualFontSize];
CGSize size = [barItemTitle sizeWithFont:font];
NSMutableParagraphStyle *paragraphStyle = [[[NSParagraphStyle defaultParagraphStyle] mutableCopy] autorelease];
paragraphStyle.lineBreakMode = NSLineBreakByTruncatingTail;
paragraphStyle.alignment = NSTextAlignmentRight;
[barItemTitle drawInRect:CGRectMake(rect.origin.x, rect.origin.y - size.height/2, rect.size.width, size.height) withAttributes:#{NSFontAttributeName:font, NSForegroundColorAttributeName:[UIColor blueColor], NSParagraphStyleAttributeName:paragraphStyle}];
}
Following is the screen shot of simulator.
I have also tried zPosition but no use.
barItemShape.zPosition = -1000;
The most possible cause of you issue is that you creating CGContextRef but adding sublayer when you need to draw lightgray rectangle. I think, that it would be more consistant to draw your rectange with CoreGraphics functions and that draw your text.
To be more detailed, it seems that you drawing text in current layer but adding sublayer that will be above your text.
For instance, you can use this code to give it a try:
UIColor * redColor = [UIColor colorWithRed:1.0 green:0.0 blue:0.0 alpha:1.0];
CGContextSetFillColorWithColor(context, redColor.CGColor);
CGContextFillRect(context, self.bounds);

text with sharp shadow around

I want to achieve the text appearance like in the pictures below:
Now I'm working on shadow around the letters and I can't figure out how to do that.
What I've tried so far:
- The solution with:
label.shadowColor = [UIColor blackColor];
label.shadowOffset = CGSizeMake(1, 2);
gives a nice sharp shadow, but it doesn't fit my needs by two reasons:
It gives a shadow only from one side, set up by shadowOffset, whereas I need a "wrapping" shadow;
This solution doesn't give the soft part of the shadow (gradient) as there is in the pictures;
-The solution with:
label.layer.shadowOffset = CGSizeMake(0, 0);
label.layer.shadowRadius = 5.0;
label.layer.shouldRasterize = YES;
label.layer.shadowOpacity = 1;
label.layer.shadowColor = [UIColor blackColor].CGColor;
label.layer.masksToBounds = NO;
Works great, but it gives too soft shadow even though the shadowOpacity is set to 1 and the shadowColor is set to black:
Obviously it's not enough and I already think about drawing in labels' context. But it is not clear to me how would I achieve the goal even through context drawing.
Any idea would be much appreciated.
Try this
Create a Custom UILabel SubClass and Override the following method
- (void)drawTextInRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
CGContextSetShadow(context, CGSizeMake(0.0, 0.0), 10);
CGContextSetShadowWithColor(context, CGSizeMake(0.0, 0.0), 10, [UIColor blackColor].CGColor);
[super drawTextInRect:rect];
CGContextRestoreGState(context);
}
and this bottomColorLayer to the Label
CALayer *bottomColorLayer = [CALayer layer];
bottomColorLayer.frame = CGRectMake(0, labelRect.size.height/2, labelRect.size.width, labelRect.size.height/2);
bottomColorLayer.backgroundColor = [[UIColor colorWithWhite:0 alpha:.5] CGColor];
[label.layer insertSublayer:bottomColorLayer above:(CALayer *)label.layer];
or If you want Gradient
CAGradientLayer *bottomGradient = [CAGradientLayer layer];
bottomGradient.frame = CGRectMake(0, labelRect.size.height/2, labelRect.size.width, labelRect.size.height/2);
bottomGradient.cornerRadius = 0.0f;
bottomGradient.colors = #[(id)[[UIColor colorWithWhite:1 alpha:.5] CGColor], (id)[[UIColor colorWithWhite:0 alpha:.5] CGColor]];
[label.layer insertSublayer:bottomGradient above:(CALayer *)label.layer];
Use an explicit shadow path that's the shape you want. It sounds like you want a shadow the same shape as your text, but larger, with each shadow-letter centered on its corresponding letter. Once you have that, use the shadow radius to soften the edges of the shadow to whatever degree you want.
The code you have relies on the shadow radius alone to make the shadow larger than the text, which removes your ability to control the softness.
Try with the code below :-
[_testLable setText:#"TION ERRO"];
[_testLable setTextColor:[UIColor whiteColor]];
[_testLable setFont:[UIFont boldSystemFontOfSize:22] ];
_testLable.layer.shadowOffset = CGSizeMake(0, 0);
_testLable.layer.shadowRadius = 10.0;
_testLable.layer.shouldRasterize = YES;
_testLable.layer.shadowOpacity = 1;
_testLable.layer.shadowColor = [UIColor blackColor].CGColor;
_testLable.layer.masksToBounds = NO;
CGPathRef shadowPath = CGPathCreateWithRect(_testLable.bounds, NULL);
_testLable.layer.shadowPath = shadowPath;
CGPathRelease(shadowPath);
Its output is like this:-

add border in CGRect iOS

I want to add a border in a CGRect. Although previous solutions suggest either this:
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetRGBFillColor(context, 1.0, 0.0, 0.0, 1.0);
CGContextSetRGBStrokeColor(context, 1.0, 0.0, 0.0, 1.0);
CGContextFillRect(context, rectangle);
or something like this:
view.layer.borderWidth = 10;
view.layer.borderColor = [UIColor redColor].CGColor;
I cannot apply either of this in my approach.
In my mainView Controller I am having this code:
-(void)actionHint
{
CGRect viewRect = CGRectMake(kScreenWidth/2 -kMenuWidth, kScreenHeight/2-kMenuHeight - 70,kMenuWidth*10, kMenuHeight*4);
HintMenu* hintMenu = [HintMenu viewWithRect:viewRect];
[hintMenu.btnReveal addTarget:self action:#selector(actionReveal) forControlEvents:UIControlEventTouchUpInside];
[hintMenu.btnNewAnag addTarget:self action:#selector(actionNewAnagram) forControlEvents:UIControlEventTouchUpInside];
[self.gameView addSubview:hintMenu];
}
I am creating a game and I want a simple rect with some help actions to come on top of my current view. The code for viewRect is:
+(instancetype)viewWithRect:(CGRect)r
{
HintMenu* hint = [[HintMenu alloc] initWithFrame:r];
hint.userInteractionEnabled = YES;
UIImage* image=[UIImage imageNamed:#"btn"];
... rest of items in the cgrect
return hint;
}
Where should I add the code for adding the borders and what that code should be?
Your HintMenu is a type of view so in its initWithFrame method you can do:
self.layer.borderWidth = 10;
self.layer.borderColor = [UIColor redColor].CGColor;
You can use this code to create a bordered rectangle. All you have to do is import the QuartzCore framework. Feel free to copy+paste this code.
#import <QuartzCore/QuartzCore.h>
-(void)viewDidLoad{
//give it a blue background
self.layer.backgroundColor=[UIColor blueColor].CGColor;
//set the boarder width
self.layer.borderWidth=5;
//set the boarder color
self.layer.borderColor=[UIColor redColor].CGColor;
}

Quartz 2D Drawing Crashing

I don't know why this stopped working, but this chunk of code is crashing my device when I try drawing any part of it. I'm new to core graphics so any pointers or suggestions would be a great help. Thanks!
// Style
CGContextRef context = UIGraphicsGetCurrentContext();
// Colors
CGColorRef fillBox = [UIColor colorWithRed:250.0/255.0 green:250.0/255.0 blue:250.0/255.0 alpha:1.0].CGColor;
CGColorRef fillBoxShadow = [UIColor colorWithRed:77.0/255.0 green:77.0/255.0 blue:77.0/255.0 alpha:1.0].CGColor;
CGRect box = CGRectMake(5, 5, self.frame.size.width - 10, self.frame.size.height - 10);
// Shadow
CGContextSetShadowWithColor(context, CGSizeMake(0, 0), 1.0, fillBoxShadow);
CGContextAddRect(context, box);
CGContextFillPath(context);
// Box
CGContextSetFillColorWithColor(context, fillBox);
CGContextAddRect(context, box);
CGContextFillPath(context);
If your project is using ARC, then these two lines might be part of your problem:
CGColorRef fillBox = [UIColor colorWithRed:250.0/255.0 green:250.0/255.0 blue:250.0/255.0 alpha:1.0].CGColor;
CGColorRef fillBoxShadow = [UIColor colorWithRed:77.0/255.0 green:77.0/255.0 blue:77.0/255.0 alpha:1.0].CGColor;
ARC is releasing the UIColor object and thus the CGColorRef. You need to retain the CGColorRef and then release it when you are done with it.
I would write the code something like this:
UIColor *fillBox = [UIColor colorWithRed:250.0/255.0 green:250.0/255.0 blue:250.0/255.0 alpha:1.0];
UIColor *fillBoxShadow = [UIColor colorWithRed:77.0/255.0 green:77.0/255.0 blue:77.0/255.0 alpha:1.0];
and then use fillBox.CGColor and fillBoxShadow.CGColor later on in the method.
Instead of doing
CGContextAddRect(context, box);
CGContextFillPath(context);
Try using CGContextFillRect.
You can't fill a path you haven't added to the context beforehand.
Note: you could do
CGContextAddPath(context, [UIBezierPath pathWithRect:box].CGPath);
CGContextFillPath(context);
but that's a bit overkill compared to just filling a rect.
(Not sure about the pathWithRect: syntax, but it exists.)

UIColor and Graphics Context

I have a custom UIView which draws a path like so
- (void)drawRect:(CGRect)rect{
[[UIColor blackColor] setStroke];
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSetFillColor(ctx, CGColorGetComponents(self.color));
CGContextFillPath(ctx);
UIBezierPath *thePath = [UIBezierPath bezierPath];
thePath.lineWidth = _lineWidth;
_center = CGPointMake(rect.size.width, rect.size.height);
[thePath moveToPoint:_center];
[thePath addArcWithCenter:_center radius:rect.size.width startAngle:M_PI endAngle:M_PI+degreesToRadians(_angle)clockwise:YES];
[thePath closePath];
[thePath fill];
}
My custom UIView also has a method to change the filling color
- (void) changeColor:(UIColor *) newColor {
self.color = [newColor CGColor];
[self setNeedsDisplay];
}
If I call the changeColor: method with any of the predefined colors such as
[UIColor redColor]
everything works fine. Instead if i try to give it a custom color such as
UIColor* color = [UIColor colorWithRed:1.0f green:0.0f blue:0.0f alpha:1.0f];
the color of my custom UIView flicker between white, red and blue randomly.
Any ideas of why is that?
Thank you in advance!
Try:
CGContextSetFillColorWithColor(ctx, self.color.CGColor);
instead of:
CGContextSetFillColor(ctx, CGColorGetComponents(self.color));
When you are using this method call :
[UIColor redColor];
For optimization purposes, UIColor return an object with only 2 components because he don't need the other one. (This is made possible with the mechanism of Class clustering).
That's maybe why your code show some differences between this two colors.

Resources