UITextView - addSubview - Autolayout - ios

Problem:
I have created a subclass of UITextView and added a subview v1.
I am using Autolayout, so I tried to add constraints for positioning the subview v1.
Error:
It throws the following error:
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Auto Layout still required after executing -layoutSubviews.
Attempts Made:
I have tried creating the constraints inside layoutSubviews and yet i get the same error
Objective
My main objective is to add a fading effect at the bottom of the text view
Question:
Is there a better way to attain my objective ?
How do I resolve this error ?

Thanks to #mackworth for the suggestion which led to the solution
For completeness I am answering it.
Overview:
There seems to be some trouble adding subview on UITextView and then using Autolayout.
Solution:
So the solution is to create the HazeView as a subview to the parent view of UITextView.
Steps:
Create a UITextView
Create a HazeView (subclass from UIView)
Add both UITextView and HazeView as subview to the same parent view
Position HazeView at the bottom of the UITextView
Ensure that the background colour of HazeView is [UIColor clearColor]
Disable user interaction on HazeView
It is best to create a subclass of UIView and put the UITextView and HazeView inside that so that it can be reusable
Creating HazeView:
self.hazeView.backgroundColor = [UIColor clearColor];
HazeView is a subclass of UIView
- (void)drawRect:(CGRect)rect
{
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = UIGraphicsGetCurrentContext();
UIColor *color1 = [UIColor colorWithRed:1.0 green:1.0
blue:1.0 alpha:0.25];
UIColor *color2 = [UIColor colorWithRed:1.0 green:1.0
blue:1.0 alpha:0.5];
UIColor *color3 = [UIColor colorWithRed:1.0 green:1.0
blue:1.0 alpha:0.75];
NSArray *gradientColors = #[(id) color1.CGColor,
(id) color2.CGColor,
(id) color3.CGColor];
CGFloat gradientLocations[] = {0, 0.50, 1};
CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef) gradientColors, gradientLocations);
CGPoint startPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMinY(rect));
CGPoint endPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMaxY(rect));
CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, 0);
CGGradientRelease(gradient);
}

I suggest you to use the following library for Autolayout:
https://github.com/jrturton/UIView-Autolayout
It is very easy to add constraints with this.
Create the subclass of UITextView and add the constraints in -(void)didMoveToSuperview
as:
-(void)didMoveToSuperview
{
[self.subview pinToSuperviewEdges:JRTViewPinBottomEdge | JRTViewPinLeftEdge | JRTViewPinRightEdge inset:0];
[self.subview constrainToHeight:10];
}

Related

Draw border and keep above all subviews in view

I've been thinking about this one for a while. Basically, the code below draws a border on a UIView, but, if I add another UIView as a subview to that UIView - it'll appear above the border.
Like this:
How do I (as cleanly as possible), keep the border above all subviews?
Like this:
This is what I have so far. But, like stated above, it doesn't keep the border above all its subviews.
CGPathRef CGPathRect = CGPathCreateWithRect(rect, 0);
CGContextRef context = UIGraphicsGetCurrentContext();
CGPathRef border = CGPathCreateCopyByStrokingPath(rect.CGPath, NULL, 5.0f, kCGLineCapButt, kCGLineJoinMiter, 0);
CGContextAddPath(context, border);
CGContextSetFillColorWithColor(context, someCGColor);
CGContextDrawPath(context, kCGPathFill);
CGPathRelease(border);
I could create a separate UIView for the border itself, and just insert subviews below that UIView, but that feels rather hackish. If there's a better way - I'd love to hear about it.
I would say use:
view.clipToBounds = YES;
view.layer.borderColor = [UIColor redColor];
view.layer.borderWidth = 2;
view.layer.cornerRadius = 4;
All subviews are clipped and u can keep ur border :).

Fill UIView background color with percentage changing

I have UIView.
My JSON object every time return percentage count like 45% or 68% etc..
My query is I want to fill background view color programmatically when i receive success json result.
Suppose If i receive 32%. Left to right 35% filling red color remaining 65% white color.
How is possible ?
Can you give me sample code ?
Take a UIView in storyboard and make its subclass as UIProgressView or you can make it with code too.
UIProgressView * progressView = [[UIProgressView alloc]initWithFrame:CGRectMake(0, 0, 100, 100)];
You can then use code
Example for 25% filled red and remaining white
progressView.progress = .25;
progressView.trackTintColor = [UIColor whiteColor];
progressView.progressTintColor = [UIColor redColor];
Output
You can even animate the filling by just changing the progress of progressView in some timer method.
For label just grab a UILabel and add it to the progressView as a subview.
How about using a custom UIView with UIBezierPath like this
#define PERCENTAGE 0.3f
#define PROGRESS_COLOR [UIColor redColor]
#define FILL_COLOR [UIColor whiteColor]
#define LBL_TEXT #"Some text goes here..."
- (void)drawRect:(CGRect)rect {
[super drawRect:rect];
UIBezierPath *fillPath = [UIBezierPath bezierPathWithRect:rect];
[FILL_COLOR setFill];
[fillPath fill];
CGRect progressRect = rect;
progressRect.size.width = progressRect.size.width * PERCENTAGE;
UIBezierPath *percentagePath = [UIBezierPath bezierPathWithRect:progressRect];
[PROGRESS_COLOR setFill];
[percentagePath fill];
[LBL_TEXT drawInRect:rect withAttributes:#{
NSFontAttributeName : [UIFont systemFontOfSize:20],
NSForegroundColorAttributeName : [UIColor blackColor]
}
];
}

Unable to make UILabel text glow

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/

text is disappearing when filling the gradient for uilabel, custom uilabel

My goal is to add gradients for my uilabel by doing the following (CustomLabelBackGround is subclass of UILabel)
#implementation CustomLabelBackGround
- (id)initWithFrame:(CGRect)frame {
if ((self = [super initWithFrame:frame])) {
// Initialization code
}
return self;
}
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGColorRef whiteColor = [UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:1.0].CGColor;
CGColorRef lightGrayColor = [UIColor colorWithRed:230.0/255.0 green:230.0/255.0 blue:230.0/255.0 alpha:1.0].CGColor;
CGColorRef separatorColor = [UIColor colorWithRed:208.0/255.0 green:208.0/255.0 blue:208.0/255.0 alpha:1.0].CGColor;
CGRect paperRect = self.bounds;
// Fill with gradient
drawLinearGradient(context, paperRect, whiteColor, lightGrayColor);
// Add white 1 px stroke
CGRect strokeRect = paperRect;
strokeRect.size.height -= 1;
strokeRect = rectFor1PxStroke(strokeRect);
CGContextSetStrokeColorWithColor(context, whiteColor);
CGContextSetLineWidth(context, 1.0);
CGContextStrokeRect(context, strokeRect);
// Add separator
CGPoint startPoint = CGPointMake(paperRect.origin.x, paperRect.origin.y + paperRect.size.height - 1);
CGPoint endPoint = CGPointMake(paperRect.origin.x + paperRect.size.width - 1, paperRect.origin.y + paperRect.size.height - 1);
draw1PxStroke(context, startPoint, endPoint, separatorColor);
}
However, the text of CustomLabelBackGround is disappearing when I am trying to display onto the screen. please look at the picture below as reference:
What I am missing here. Please help if you have any ideas about this. thanks
You need to call :
[super drawRect:rect];
in order to super draw your text before drawing your anything else. The text with then be drawn normaly
Since you are implementing drawRect for UILabel you are owning that Graphics Context, therefore you are basically "overriding" the text, you can draw that yourself as well, or an easier approach would just be to have a container view with the gradient and a transparent label with the text.
The best approach
Create a custom UIView
make this drawrect implement there
In this UILabel class add that class as background to the label
Otherwise you have to draw the label contents also since you are overriding its drawrect method
Why not just pre-render the gradient in photoshop and then on your label just set:
myLabel.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"myImage"]];
I would:
Create a custom UIView,and use your drawRect code there.
Make sure that the UILabel background is set to [UIColor
clearColor].
Add the Custom UILabel Class as a
subview of the Custom UIView class.
Or just do like Imram said, and create that gradient as an image in Photoshop or some other graphic editor program, and set the label background there. Personally, I think this may be the simplest and most maintainable solution.

How to remove border from some part of UIView?

I am having a UIView which contains other subviews. I am applying border to this UIView and the border is applied to the whole UIView. For that see the first image.
But do not want the border around the title where it says "Leaderboard". How can i remove the border for that portion only. See the below image and in that see that there is no border around the header Leaderboard..
NO,CALayer borders don’t support that behavior.
But you can try an alternate method if you need to implement this,
try adding an n-point-wide opaque subview with your desired border color as its background color, on each side of your main view.
Add this Code:
CGSize mainViewSize = theView.bounds.size;
CGFloat borderWidth = 2;
UIColor *borderColor = [UIColor redColor];
CGFloat heightfromTop = 25;
UIView *leftView = [[UIView alloc] initWithFrame:CGRectMake(0, heightfromTop borderWidth, mainViewSize.height-heightfromTop)];
UIView *rightView = [[UIView alloc] initWithFrame:CGRectMake(mainViewSize.width - borderWidth, heightfromTop, borderWidth, mainViewSize.height-heightfromTop)];
leftView.opaque = YES;
rightView.opaque = YES;
leftView.backgroundColor = borderColor;
rightView.backgroundColor = borderColor;
[mainView addSubview:leftView];
[mainView addSubview:rightView];
This will add borders to both sides only.Repeat the same idea for top and bottom also.
NB : heightfromTop is the height of the top section where you don't want the border view to be present, you can alter it as per your needs
You can subclass the UIView and implement the drawRect like:
- (void)drawRect:(CGRect)rect
{
float borderSize = 3.0f;
//draw the bottom border
CGContextSetFillColorWithColor(context, [UIColor blueColor].CGColor);
CGContextFillRect(context, CGRectMake(0.0f, self.frame.size.height - borderSize, self.frame.size.width, borderSize));
//draw the right border
CGContextSetFillColorWithColor(context, [UIColor blueColor].CGColor);
CGContextFillRect(context, CGRectMake(0.0f,0.0f, borderSize,self.frame.size.height));
//draw the left border
CGContextSetFillColorWithColor(context, [UIColor blueColor].CGColor);
CGContextFillRect(context, CGRectMake(self.frame.size.width - borderSize,0.0f, borderSize,self.frame.size.height));
}
Now, you need to use the subclassed UIView for creating the needed view.

Resources