Automatically Grow a View's Height Based on It's Content - ios

Situation
I have a (vertical) UIStackView containing both a plain UIView of height 50 (named sliderView) and a UILabel of height 36 defined in my storyboard. The label's alpha property is initially set to 0.0 to make it invisible.
In the controller's viewDidLoad I use UIViewController Containment to add another view controller's view to as a subview of sliderView. This new subview does not necessarily match sliderViews height. It might actually a fair bit taller.
At first, this setup looks fine. Once I make the label visible, I see that it still starts at a y-position of 50. So, the sliderView did not automatically stretch to use it's new child's height. Makes sense.
Question
I thought that I could easily just call sizeToFit on sliderView to make those two heights fit. Unfortunately, this does not seem to work. Am I misunderstanding something here? Thanks!

Use following method to get the CGSize required for NSString text.
- (CGSize)getHeightForText:(NSString *)text havingWidth:(CGFloat)widthValue andFont:(UIFont *)font {
CGSize size = CGSizeZero;
if (text) {
CGRect frame = [text boundingRectWithSize:CGSizeMake(widthValue, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin attributes:#{ NSFontAttributeName:font } context:nil];
size = CGSizeMake(frame.size.width, frame.size.height+20.0f);
}
return size;
}
Here width parameter is the width of your label and font is the font specified for your label. Call CGSize.height to get the height.

Related

how make the UIView height equal to its subview's additional height, so that it can easily scroll till the end

I have a situation where i have following view layout.
-UIViewcontroller
-SCrollView
-UIView(outer)
-buttons
-labels
-UIView(inner)
-labels
-buttons
-buttons
the inner UIView height can be any longer as content inside is dynamically added.
So the main issue is i can not scroll till the end of the content, instead i can only scroll till the height of inner UIView.
NOTE - I am using auto layout
Any help is much appreciated.
Thanks
You should change the frame of your inner view dynamically based on the content you are adding. According to your inner view hierarchy, you have label and button. You might be setting some dynamic text on label and also doing some manipulation with button . Use the following method to get the height of the text ,
- (CGSize)getHeightForText:(NSString *)text havingWidth:(CGFloat)widthValue andFont:(UIFont *)font {
CGSize size = CGSizeZero;
if (text) {
CGRect frame = [text boundingRectWithSize:CGSizeMake(widthValue, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin attributes:#{ NSFontAttributeName:font } context:nil];
size = CGSizeMake(frame.size.width, frame.size.height);
}
return size;
}
Here font is the font you set to button and label. Call this method by passing the text added on label and button. CGSize has a height property , add height value of label and button. Now set this sum height to innerView by calling innerView.frame.size.height = <height>. This increase the height of your innerView based on content inside that.
Put all your buttons in the bottom inside a container view and add the following constraints to the outerView (assuming that the new container you've added is called "buttonContainer"):
A vertical spacing constraint between the bottom of innerView and the top of the buttonContainer.
A vertical spacing constraint between the bottom of the buttonContainer and the bottom of the outerView.
Horizontal spacing constraints between between the buttonContainer and outerView to force it to full width.
When using AutoLayout, you have to have enough constraints to properly define the contentSize of the scrollView.
For more information about using AutoLayout with UIScrollView, check out the following links by Apple:
Working with Scroll Views
UIScrollView and Autolayout

Make UILabel height zero if label empty/storyboard

I have a lot of labels stacked up for a contact info screen. If any of the labels are empty, I would love to zero out their height and have them occupy no space to avoid empty space on the screen. However, I have created the screen in storyboard and the labels have been assigned heights and y values.
Here is code I've been trying to use to alter label height but cannot get it to work. Perhaps it is designed to work only for labels created programmatically and the storyboard settings override what I am doing here.
NSString *string = #"some text";
CGSize maximumLabelSize = CGSizeMake(280,1000);
 
// use font information from the UILabel to calculate the size
CGSize expectedLabelSize = [string sizeWithFont:myLabel.font constrainedToSize:maximumLabelSize lineBreakMode:NSLineBreakByWordWrapping];
 
// create a frame that is filled with the UILabel frame data
CGRect newFrame = myLabel.frame;
// resizing the frame to calculated size
newFrame.size.height = expectedLabelSize.height;
// put calculated frame into UILabel frame
myLabel.frame = newFrame;
Is there a way to get the height of labels created in storyboard to zero out if they are empty?
you can override the following method of the view containing your label and do something like that:
-(void) layoutSubviews {
myLabel.frame = CGRectZero;
}
This method is in order to allow to layout the subviews or you view. Now I don't know If you have used contraints to define the height of your label. If so you should change in the same way the height of your label. Note the in the above example I used CGRectZero.

Change ScrollView height based on content of the View

I parse some Json Data and I show it using various UITextView, for now I used a ScrollView created via Storyboard that has a height of 1000px but sometimes I can't show the whole data since it's too long to fit the ScrollView, how can I update it programmatically in order to have a height based on the content the view has to show?
You may calculate the height of text:
CGRect textRect = [#"your text" boundingRectWithSize:CGSizeMake(yourScrollView.width, CGFLOAT_MAX)
options:(NSStringDrawingUsesLineFragmentOrigin)
attributes:#{NSFontAttributeName:[UIFont fontWithName:#"HelveticaNeue" size:18]}
context:nil];
And then update scrollView contentSize
[yourScrollView setContentSize:CGSizeMake(yourScrollView.frame.size.width,textRect.size.height)];
Go to your storyboard and remove all height constraint of your UITextViews. In order to avoid warnings in the storyboard, select Intrinsic Size -> Place Holder for each UITextView in your ScrollView. The option is located in the Size Inspector (right pane). This will tell XCode know that you don't want to specify a height, you rather want them to be based on its intrinsicContentSize.
Finally, create a new class 'FitContentTextView' that inherits from UITextView. In the storyboard make all your UITextView's that you want to have enough size to fit content of type FitContentTextView
- (void)setText:(NSString *)text {
[self setScrollEnabled:YES];
[super setText:text];
[self invalidateIntrinsicContentSize];
}
- (CGSize)intrinsicContentSize {
CGSize size = [self contentSize];
return size;
}
The setScrollEnabled thing in setText is important. The method contentSize only returns enough size to fit all text if srolling is enabled. Otherwise, will return the the TextView's bounds.
Also, calling invalidateIntrinsicContentSize every time we set the text makes sure autolayout will call the method intrinsicContentSize before drawing the TextView, and add this methods to it.
Lastly, remember to pin all ScrollView's subviews vertically to its superview from top to bottom. This is the only way AutoLayout can update the contentSize of the SrollView to fit all subviews.

UITableViewCell get subview height with auto-layout

I have a UITableViewCell subclass on which I'm using auto-layout, and I want to get the height of a UILabel subview once the auto-layout process has been completed.
I tried layoutSubviews and getting the frame property of my UILabel, but this seemed to be the old height of the label before it was recycled.
I then tried to override layoutIfNeeded but I found it was never called.
How can I get the frames of my UITableViewCell subviews once auto-layout is completed and the constraints have been applied? Surely this should be really simple!
Assuming that the label is an immediate subview of the table cell's content view, then my quess is that you could access the final, on-screen value of the label's bounds in the layoutSubviews method for the content view of the table cell (rather than the layoutSubviews method of the table cell itself).
However, if your label is not multi-lined, then simply grab the label's height from its attributedText property at anytime as follows:
NSAttributedString *attrString = label.attributedText;
CGFloat labelHeight = ceilf(attrString.size.height);
Alternatively, you could use the label's font property to determine the label's height (again, only if the label is not multi-lined):
UIFont *font = label.font;
CGFloat labelHeight = ceilf(font.lineHeight);
If your label is multi-lined, then the best choice for calculating the line height is as follows:
// but you have to know the label's width
CGFloat labelWidth = …
NSAttributedString *attrString = label.attributedText;
CGRect rect = [attrString boundingRectWithSize:CGSizeMake(labelWidth, FLT_MAX) options:NSStringDrawingUsesLineFragmentOrigin context:nil];
CGFloat labelHeight = ceilf(rect.size.height);
You would calculate the label's width manually. Often it's the main view's bounds width minus some fixed amount for horizontal spacing margins.

Change label height in tableview in iOS 7

I have a label in custom cell in table view.
I want to change cell height and also label height(at first I am showing only 2 line, I want to show more text) after user taped a cell,
I am able to change cell height based on cell content, but unfortunately I cannot change label height, :((
I've read tons of stackoverflow answers, but still nothing.
it is believed that this would work:
CGSize labelSize = [#"Hello World!" sizeWithFont:[UIFont systemFontOfSize:17] constrainedToSize:CGSizeMake(label.frame.size.width,MAXFLOAT) lineBreakMode:NSLineBreakByWordWrapping];
but this is deprecated in iOS 7; can any one please help me in resizing my label in cell?
If you want the height of your label relative to the height of your cell and you use Storyboard, you should determine the size of your label with constraints in relation to the ContentView of the cell. Just set the top and bottom distance from your label to the ContentView and no additional height for the label.
If you dont know how to set Storyboard and constraints, this might help: https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/AutolayoutPG/AutoLayoutbyExample/AutoLayoutbyExample.html
UITableViewCell lays out it's content in -layoutSubviews. Therefore, if you want to simply have a custom layout logic, you need to subclass UITableViewCell and override the -layoutSubviews method. It's a good idea to call super anyway before applying your logic, though.
You may use something like this to get UIlabel size
-(CGFloat)getLabelSize:(UILabel *)label fontSize:(NSInteger)fontSize
{
NSDictionary *attributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
[UIFont systemFontOfSize:fontSize], NSFontAttributeName,
nil];
CGRect frame = [label.text boundingRectWithSize:CGSizeMake(270, 2000.0)
options:NSStringDrawingUsesLineFragmentOrigin
attributes:attributesDictionary
context:nil];
CGSize size = frame.size;
return size.height;
}

Resources