Set proper gap between text.view frame and button frame - ios

I have a text view and buttons. For some reason i got unexpected result when trying to set proper gap between those 2 elements. I think there could be incorrect calculating of text.view frame. That is how i manage to set text.view frame:
//1 Setting properties for text, starting with dictionary containing font size and family
NSDictionary *stringAttributes = [NSDictionary dictionaryWithObject:[UIFont fontWithName:#"helvetica neue"
size:14]
forKey: NSFontAttributeName];
//Creating frame to hold textView
CGSize maximumLabelSize = CGSizeMake(self.myTextView.frame.size.width, FLT_MAX);
CGSize textViewSize = [self.descriptionStringShort boundingRectWithSize:maximumLabelSize
options:NSStringDrawingTruncatesLastVisibleLine|NSStringDrawingUsesLineFragmentOrigin
attributes:stringAttributes context:nil].size;
//Setting frame
CGRect frame = self.myTextView.frame;
frame.size.height = textViewSize.height;
NSLog(#"%f height", frame.size.height);
self.myTextView.frame = frame;
After that, when tried to set button frames it always show different gap between those to elements (my "rough" solutions is to check height of text.view and set "minimum" and "maximum" y depend on it, but it won't work in a real world app). For example, button frame may be draw on textView.frame or much below it. There is how i set map frame:
CGRect mapButtonFrame = self.mapButton.frame;
mapButtonFrame.origin.x = 30;
if (frame.size.height < 50){
mapButtonFrame.origin.y = (200+frame.size.height + 150);
} else if (frame.size.height >300){
mapButtonFrame.origin.y = (200+frame.size.height +50);
} else {
mapButtonFrame.origin.y = (200+frame.size.height +100);
}
self.mapButton.frame = mapButtonFrame;
Still, that approach is bad, please take a look at screenshots attached:
Here, as you can see, always different gap between 2 elements. How could i make it fixed?
By the way, auto layout is turned off.
Any advice would be appreciated, thanks1

This should work just fine:
[myTextView sizeToFit];//This will change the textView frame according to the text length
CGRect bFrame = self.mapButton.frame;
bFrame.origin.y = myTextView.frame.size.height + 20.0f;// The gap you want between the text and the button
self.mapButton.frame = bFrame;

Related

Incorrect size of a textview frame (self.textview.frame.size.height)

I want to change the height of a textview depending on its content. I created the method to resize its view. The first time I call this view controller it resize properly (height = 253) but not the other times (height = 296).
I tried resizing it from viewDidAppear, viewWillAppear and viewDidLoad. The first time viewDidAppear and viewDidLoad are called. Second and following times all methods (viewDidAppear, viewWillAppear and viewDidLoad) are called. I don't know the reason and I don't know why this weird behavior, any clue?
-(void) setHeight
{
NSLog(#"Set height");
CGRect frame = descriptionTextView.frame;
frame.size.height = descriptionTextView.contentSize.height;
descriptionTextView.frame = frame;
NSLog(#"height: %f", descriptionTextView.frame.size.height);
if([[UIScreen mainScreen] bounds].size.height == 568) //iPhone 4inch
{
totalHeight = 380+frame.size.height;
[self.mainScrollView setContentSize:CGSizeMake(320,totalHeight)];
}
else{
totalHeight = 250+frame.size.height;
[self.mainScrollView setContentSize:CGSizeMake(320,totalHeight)];
}
}
I use autolayout in my project but not for this view since I dont know how to properly resize a textview inside a scrollview (which also includes 2 more views with labels, images and buttons) based on the textview content with autolayout. Is it better to use autolayout than this function? Perhaps you can help me with the constraints...
You are changing only the scroll size according to your calculation but you are missing to change the size of text view itself. After setting scroll view content size update the size of the text view and all should be fine (contentSize and frame). This may look like:
[descriptionTextView setContentSize:CGSizeMake(CGRectGetWidth(descriptionTextView.frame),totalHeight)];
CGRect frame = descriptionTextView.frame;
frame.size.height = totalHeight;
[descriptionTextView setFrame:frame];
By the way: in the if-statement you can only calculate totalHeight and set it afterwards.
Additionally you do not need this line:
frame.size.height = descriptionTextView.contentSize.height;
Try this:
CGSize constraintSize;
constraintSize.height = MAXFLOAT;
constraintSize.width = yourTextView.frame.size.width;
NSDictionary *attributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
[UIFont fontWithName:#"yourFontName" size:yourFontSize], NSFontAttributeName,
nil];
CGRect frame = [yourTextView.text boundingRectWithSize:constraintSize
options:NSStringDrawingUsesLineFragmentOrigin
attributes:attributesDictionary
context:nil];
// Use this frame for your textview

Calculating proper size of label for given string

I have problem with calculating rect from given string.
Here are my strings:
_name = #"Any veryveryveryvery key here:";
_value = #"Any very very very very long value";
and my layoutSubviews method:
- (void)layoutSubviews {
[super layoutSubviews];
CGRect rect = self.contentView.bounds;
CGFloat verticalMargin = 5.0f;
//calculate rect for given name string:
CGFloat halfScreen = CGRectGetMidX(rect); //160points in portrait
//_nameLabel:
CGRect nameRect =
[_name boundingRectWithSize:CGSizeMake(halfScreen, CGRectGetHeight(rect))
options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading)
attributes:#{NSFontAttributeName: [UIFont fontWithName:kHelveticaFont size:_nameLabel.font.pointSize]}
context:nil];
//name rect = origin=(x=0, y=0) size=(width=147.53174, height=34.5) - WHY width = 147.53174 NOT halfScreen = 160points?
[_nameLabel setFrame:CGRectMake(0.0f,
verticalMargin,
ceilf(CGRectGetWidth(nameRect)),
CGRectGetHeight(rect) - verticalMargin * 2)];
//calculate rect for given value string:
//_valueLabel:
CGFloat maxWidth = CGRectGetWidth(rect) - CGRectGetMaxX(_nameLabel.frame); //172points in portrait
CGRect valueRect =
[_value boundingRectWithSize:CGSizeMake(maxWidth, CGRectGetHeight(rect))
options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading)
attributes:#{NSFontAttributeName: [UIFont fontWithName:kHelveticaFont size: _valueLabel.font.pointSize]}
context:nil];
//valueRect = origin=(x=0, y=0) size=(width=160.03418, height=34.5) - WHY width = 160.03418 NOT maxWidth = 172 points?
[_valueLabel setFrame:CGRectMake(CGRectGetMaxX(_nameLabel.frame),
verticalMargin,
ceilf(CGRectGetWidth(valueRect)),
CGRectGetHeight(rect) - verticalMargin * 2)];
}
And result:
Yellow background is half Width of Screen (160 points). Green background is another 160 points. I want to have _nameLabel with max size equal to half screen width.
Anyone has ANY idea how to calculate it properly? Question are also commented in code. Thank you in advance for help.
NOTE: I'm developing an app only for iOS7.
EDIT:
Note, that if _name will be much shorter, for example "key", i want to have _valueLabel next to _nameLabel like this (and it works as it should):
I solved my problem. Actually I dived deep in apple documentation and the problem was generated by this argument:
NSStringDrawingUsesLineFragmentOrigin // which means: The specified origin is the line fragment origin, not the base line origin
in line:
options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading)
Thats why method:
(CGRect)boundingRectWithSize:options:attributes:context:
gave me wrong rect dimensions. Now everything works as should.
_valueLabel.text = _value;
CGSize fitSize = [_valueLabel sizeThatFits:CGSizeMake(FLT_MAX, 18.0)];
CGRect newFrame = _valueLabel.frame;
newFrame.size.width = if fitSize.width > 160.0 ? 160.0 : fitSize.width
_valueLabel.frame = newFrame;
Obviously your code has a few more calculations to move the second UITextField over but hence use the same fitSize above to calculate the origin of the second UITextField plus your margin. Hope that helps get you your issue solved.

How to create TextView with increasing frame size rather than increasing the scroll size when user types

I need to create two text entry field one beneath the other. When user types in the upper text field, I need to increase the frame size dynamically (scrolling inside the textview is not recommended.) and the lower text entry frame should go downwards. Will this can be possible in ios? Any help will be appreciated.
You can update the frame of your textView via its contentSize like below:
-(void)updateTextViewSize
{
CGRect rect = textView.frame;
rect.size.width = textView.contentSize.width;
rect.size.height = textView.contentSize.height;
textView.frame = rect;
//lowering the textView2 below this textView
//assuming that the lower textview touches the
//bottom of the upper textView.
CGRect rect2 = textViewLower.frame;
rect2.origin.y = textView.frame.origin.y + textView.frame.size.height;
textViewLower.frame = rect2;
//update your scrollView here
//assuming textView and textViewLower are already added to the scrollView
scrollView.contentSize = CGSizeMake(scrollView.contentSize.width, textViewLower.frame.origin.y + textViewLower.frame.size.height);
}
//implement this delegate method as shown below
-(void)textViewDidChange:(UITextView*)textView
{
[self updateTextViewSize];
}
It is easy to do resizing of the UITextView to its correct height according to its content using the UITextView contentSize.
CGRect frame = _textView.frame;
frame.size.height = _textView.contentSize.height;
_textView.frame = frame;

Why can't I change the frame of my UILabel?

I have been trying for two days to modify the frame of a UILabel, which
is ridiculous... The UILabel is an IBOutlet, but that is not the reason
why it's not working: I tried to create a UILabel programatically and
it still didn't work. Here is how I do it:
self.descriptionLabel.text = description;
self.descriptionLabel.lineBreakMode = NSLineBreakByWordWrapping;
CGSize textSize = [self.descriptionLabel.text sizeWithFont:[UIFont systemFontOfSize:12.0]
constrainedToSize:CGSizeMake(self.descriptionLabel.frame.size.width, FLT_MAX)
lineBreakMode:self.descriptionLabel.lineBreakMode];
CGFloat frameHeight = textSize.height;
CGRect frame = self.descriptionLabel.frame;
frame.size.height = frameHeight;
self.descriptionLabel.frame = frame;
CGRect bounds = self.descriptionLabel.frame;
bounds.origin.x = self.descriptionLabel.frame.origin.x + 10.0;
bounds.size.width = self.descriptionLabel.frame.size.width - 20.0;
self.descriptionLabel.bounds = bounds;
self.descriptionLabel.numberOfLines = 0;
I already asked on IRC and they told me that there is no reason why the
frame would not be changed...
I also tried to create a frame with CGRectMake and give it arbitrary
value but that didn't do the trick either..
Does anyone know what might be the problem please?
Edit 1: I logged the frame before and after, and I got odd results:
Before: 0.000000 0.000000 0.000000 0.000000
After: 0.000000 0.000000 0.000000 33525.000000
The height after I set the frame is the only value that makes sense (I have a lot of text in the label on purpose).
Edit 2: I changed the code as follows, the log says that the frame
changed but on the simulator it didn't change; I proved it by adding red
borders to the layer of the UILabel.
self.descriptionLabel.text = description;
self.descriptionLabel.lineBreakMode = NSLineBreakByWordWrapping;
CGSize textSize = [self.descriptionLabel.text sizeWithFont:[UIFont systemFontOfSize:12.0]
constrainedToSize:CGSizeMake(self.view.frame.size.width, FLT_MAX)
lineBreakMode:self.descriptionLabel.lineBreakMode];
CGFloat frameHeight = textSize.height;
CGRect frame = CGRectMake(0.0, 300.0, self.view.frame.size.width, frameHeight);
self.descriptionLabel.frame = frame;
DDLogInfo(#"After: %f %f %f %f", self.descriptionLabel.frame.origin.x, self.descriptionLabel.frame.origin.y, self.descriptionLabel.frame.size.width, self.descriptionLabel.frame.size.height);
// After: 0.000000 300.000000 320.000000 585.000000
self.descriptionLabel.numberOfLines = 0;
self.descriptionLabel.layer.borderColor = [UIColor redColor].CGColor;
self.descriptionLabel.layer.borderWidth = 2;
If you're using auto layout, you shouldn't be doing any setting of frames -- either turn off auto layout, or use constraints to change the size of your label. The easiest way to do this is to give your label a height constraint (and width too, if you want a constant width) in IB, and make an IBOutlet to it. Then, in code, change the constant value of that constraint based on the value you get from sizeWithFont:constrainedToSize:lineBreakMode:.
Your label has a zero frame to begin with, so, when you do this:
CGSize textSize = [self.descriptionLabel.text sizeWithFont:[UIFont systemFontOfSize:12.0]
constrainedToSize:CGSizeMake(self.descriptionLabel.frame.size.width, FLT_MAX)
lineBreakMode:self.descriptionLabel.lineBreakMode];
You're asking the sizeWithFont method to do something effectively impossible - tell you the height that is required when no width is allowed. The response it provides (33525.000000) is probably the height if one character is allowed on each line or something like that.
So, either set the width of the label before you start, or provide the allowed width to the sizeWithFont method and then set the label size using the response (not just the height).
Also, consider what you're trying to do by changing the bounds. Comment that code out till you get the frame right at least, then you can add it back in and check it actually does what you want.

IOS: I cannot show my label multiline

I have a problem with UILabel. I want to show the comments multiline. But they are single line. This is my code:
CGRect currentFrame = comment.frame;
CGSize max = CGSizeMake(comment.frame.size.width,20000.0f);
CGSize expected = [comment.text sizeWithFont:[UIFont systemFontOfSize:10.0] constrainedToSize:max lineBreakMode:UILineBreakModeWordWrap];
currentFrame.size.height = expected.height;
comment.frame = currentFrame;
comment.numberOfLines = 0;
[comment sizeToFit];
But the result is not good. Where am I wrong?
Your code is okay, but you should add this line in your code to get multi line
comment.lineBreakMode = UILineBreakModeWordWrap;
I think you should increase the number of lines like
comment.numberOfLines = 2 /* or more */
So when the text size increase the width of label it will be multy line but keep in mind about font size and lable size ration

Resources