UINavigationBar - Autowidth - uinavigationbar

Having a few issues with the auto width of a custom class I'm calling. I have it working for height, however the width continually truncates at 320px wide. I guess I could hard code each value of the screen but that's madness. I'm calling the custom class into the Global Navigation View Controller.
#implementation MyCustomNav
- (CGSize)sizeThatFits:(CGSize)size {
CGSize newSize = CGSizeMake(self.frame.size.width,100);
return newSize;
}
#end
I have also tried;
CGSize newSize = CGSizeMake(self.bounds.size.width,100);
I get the same result with the UINavigatorBar truncating on each end. Below screen shot.
Now I did read somewhere that this is an iOS 8 bug. But I haven't confirm that yet.
Any Ideas?

Okay I got it working. With iOS8 I found that it required a little different formatting but in the end this worked. The key is to set the bounds with the UIScreen mainScreen. Also use bounds it seems to work better.
//Adjust the height of the NavigationBar
- (CGSize)sizeThatFits:(CGSize)size {
CGSize newSize = CGSizeMake(self.frame.size.width,53);
[self setFrame:CGRectMake(0,0,[[UIScreen mainScreen] bounds].size.width,60)];
return newSize;
}
Hope that helps someone.

Related

How can I enforce an UILabel to be wider than it should be, by 5 points?

I have an UILabel, it has background color as green. But It wraps the text very closely. I need the green background to be little wider than the text, approx 5 points. How can I achieve this?
Details
Label is created in storyboard and has horizontal spacing constraints. You can ignore the constraints as I guess, because I have handled it for any width.
Suggested Requirement
I guess I need a method which I can override in my UILabel's subclass, to increase its width by 5 points. Anybody knows which method I shoul override?
You may try to subclassing of UILabel class and overriding below method -
- (void)drawTextInRect:(CGRect)rect {
UIEdgeInsets insets = {0, 5, 0, 5};
[super drawTextInRect:UIEdgeInsetsInsetRect(rect, insets)];
}
Hope this will be help you !
You can achieve it by calling sizeToFit first, it will shrink the frame and fit to text, then you can increase width by 10 pixels and remember to keep it center aligned.
Hope it helps.. Let me know... :)
Finally I solved my problem! It works great like this -
Make a subclass of UILabel and override the intrinsicContentSize and sizeThatFits to achieve what you want.
So, something like:
- (CGSize) intrinsicContentSize
{
return [self addHorizontalPadding:[super intrinsicContentSize]];
}
- (CGSize)sizeThatFits:(CGSize)size
{
return [self addHorizontalPadding:[super intrinsicContentSize]];
}
- (CGSize)addHorizontalPadding:(CGSize)size
{
if (size.width > 0)
return CGSizeMake(size.width + (2*kSomeHorizontalPaddingValue), size.height);
else
return size;
}
Note that this only touches the horizontal padding, but can obviously be modified to add vertical padding as well.
I think below code will be working for you
CGFloat width = [label.text sizeWithFont:[UIFont systemFontOfSize:22 ]].width;
label.frame = CGRectMake(point.x, point.y, width+5,height);

How to set the background image according to screen size?

I want to set an image according to screen size. I've been going through many codes on it but I've not found a working solution yet. I'm using Xcode 5.1.1 and Iphone Retina 4inch. Whenever I add my background image, it becomes huge and goes out of screen size. Kindly help me.
Use the code from Anbu's answer to get the screen height and set the image to aspectFit to avoid it from getting huge and out of bounds:
yourImageview.contentMode = UIViewContentModeScaleAspectFit;
yourImageview.clipsToBounds = YES;
If your view is directly added to a UIViewController you should use the viewWillLayoutSubviews (doc) method to do the resize. Something like this:
- (void)viewWillLayoutSubviews
{
[super viewWillLayoutSubviews];
self.imageView.frame = self.bounds;
}

iOS7 UITextView contentsize.height alternative

I'm porting one of apps from iOS 6.1 to iOS 7. I'm using a layout where there's a UITextView that has a fix width, but it's height is based on its contentsize. For iOS 6.1 checking the contentsize.height and setting it as the textview's frame height was enough, but it doesn't work on iOS 7.
How can I then create a UITextView with a fixed width, but dynamic height based on the text it's showing?
NOTE: I'm creating these views from code, not with Interface Builder.
With this following code, you can change the height of your UITextView depending of a fixed width (it's working on iOS 7 and previous version) :
- (CGFloat)textViewHeightForAttributedText:(NSAttributedString *)text andWidth:(CGFloat)width
{
UITextView *textView = [[UITextView alloc] init];
[textView setAttributedText:text];
CGSize size = [textView sizeThatFits:CGSizeMake(width, FLT_MAX)];
return size.height;
}
With this function, you will take a NSAttributedString and a fixed width to return the height needed.
If you want to calculate the frame from a text with a specific font you, need to use the following code :
- (CGSize)text:(NSString *)text sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size
{
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"7.0"))
{
CGRect frame = [text boundingRectWithSize:size
options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading)
attributes:#{NSFontAttributeName:font}
context:nil];
return frame.size;
}
else
{
return [text sizeWithFont:font constrainedToSize:size];
}
}
You can add that SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO on your prefix.pch file in your project as:
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
You can also replace the previous test SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) by :
if ([text respondsToSelector:#selector(boundingRectWithSize:options:attributes:context:)])‌
This worked for me for iOS6 and 7:
CGSize textViewSize = [self.myTextView sizeThatFits:CGSizeMake(self.myTextView.frame.size.width, FLT_MAX)];
self.myTextView.height = textViewSize.height;
In iOS7, UITextView uses NSLayoutManager to layout text:
// If YES, then the layout manager may perform glyph generation and layout for a given portion of the text, without having glyphs or layout for preceding portions. The default is NO. Turning this setting on will significantly alter which portions of the text will have glyph generation or layout performed when a given generation-causing method is invoked. It also gives significant performance benefits, especially for large documents.
#property(NS_NONATOMIC_IOSONLY) BOOL allowsNonContiguousLayout;
disable allowsNonContiguousLayout to fix contentSize :
textView.layoutManager.allowsNonContiguousLayout = NO;
Use this little function
-(CGSize) getContentSize:(UITextView*) myTextView{
return [myTextView sizeThatFits:CGSizeMake(myTextView.frame.size.width, FLT_MAX)];
}
My final solution is based on HotJard's but includes both top and bottom insets of text container instead of using 2*fabs(textView.contentInset.top) :
- (CGFloat)textViewHeight:(UITextView *)textView
{
return ceilf([textView.layoutManager usedRectForTextContainer:textView.textContainer].size.height +
textView.textContainerInset.top +
textView.textContainerInset.bottom);
}
There are simplier solution, using this method:
+(void)adjustTextViewHeightToContent:(UITextView *)textView;
{
if([[UIDevice currentDevice].systemVersion floatValue] >= 7.0f){
textView.height = [textView.layoutManager usedRectForTextContainer:textView.textContainer].size.height+2*fabs(textView.contentInset.top);
}else{
textView.height = textView.contentSize.height;
}
}
UPD: working just for displaying text (isEditable = NO)
_textView.textContainerInset = UIEdgeInsetsZero;
_textView.textContainer.lineFragmentPadding = 0;
Just don't forget the lineFragmentPadding
simple solution - textView.isScrollEnabled = false
works perfect when inside another scroll view, or tableView cell with UITableViewAutomaticDimension
#Ana's, #Blake Hamilton's solution in swift.
var contentHeight: CGFloat = textView.sizeThatFits(textView.frame.size).height
The good thing for me was that this also returns the correct contentSize, when isScrollEnable is set to false. Setting to false returned the text view's frame size instead of the content size.

ios create 'readmore'. Let superview be dependent of subview

gaaah designing in ios gives me headache!!
So please, help me out and maby explain to me how one should think trying to come up with the solution.
I have:
As you can see the UITextField has its frame being set in storyboard to be smaller than its actual content.
Everything above the prototypecell is within a UIView that is set to be tableHeader programatically.
I want to:
Press the read more btn so that the UITextField get its actual size. No problem, I can do that with getting the contentSize programmatically. It works but it ofc overflows the tableHeader
So I thought, good. Then all I have to do is set the tableHeader to be the size of the 'new' calculated height of UITextField + height of the 2 UIImageViews.
But nope. it only resizes to the existing height set in storyboard insted. In other word, it does one or the other.
And using autolayout it totally breaks but not giving me any errors about constraints.
This seems so easy wich makes me feel so stupid haha
this is what I have i code
- (IBAction)toggleReadMore:(id)sender{
_toggleReadMoreBtn.hidden = YES;
CGRect textFrame = _cityDescription.frame;
_cityDescription.frame = textFrame;
CGRect tableHeaderViewFrame = CGRectMake(0, 0, self.tableView.tableHeaderView.frame.size.width, _cityDescription.contentSize.height + 218.0f ); //textFrame.size.height
self.tableView.tableHeaderView.frame = tableHeaderViewFrame;
textFrame.size.height = _cityDescription.contentSize.height;
[self.tableView setTableHeaderView:self.viewForTableHeader];
please, guide me how to think
- (IBAction)readMoreBtnClicked:(UIButton *)sender
{
NSLog(#"Read more Btn Clicked");
NSString *stringToBeDisplayed = #"Any Text Here";
CGSize textSize=[stringToBeDisplayed sizeWithFont:[UIFont systemFontOfSize:30]
constrainedToSize:CGSizeMake(270, 500)
lineBreakMode:NSLineBreakByWordWrapping];
NSLog(#"textSize = %#",NSStringFromCGSize(textSize));
[self.textView setFrame:CGRectMake(self.textView.frame.origin.x,self.textView.frame.origin.y, textSize.width, textSize.height)];
NSLog(#"self.textView.frame = %#",NSStringFromCGRect(self.textView.frame));
[self.textView setText:stringToBeDisplayed];
[self.headerView setFrame:CGRectMake(self.headerView.frame.origin.x,self.headerView.frame.origin.y, 320, dynamicHeightCalculatedAfterTextSize)];
[self.tableView reloadData];
}

Vertically Align UILabel text with constraints and no wrap (auto layout, single line)

So I have my view setup in IB such that this text label aligns with the top of the thumbnail via constraints.
However as we know, you can't vertically align text in a UILabel. My text updates the font size based on the length of the content. Full size text looks great, while small text is significantly lower on the view.
The existing solution involves either calling sizeToFit or updating the frame of the uilabel to match the height of the text. Unfortunately the latter (albeit ugly) solution doesn't play well with constraints where you aren't supposed to update the frame. The former solution basically doesn't work when you need to have the text autoshrink until it truncates. (So it doesn't work with a restricted number of lines and autoshrink).
Now as to why the intrinsic size (height) of the uilabel doesn't update like the width does when it's set to it's natural size via "Size to fit content" is beyond me. Seems like it definitely should, but it doesn't.
So I'm left looking for alternative solutions. As far as I can see, you might have to set a height constraint on the label, and adjust the height constant after calculating the height of the text. Anyone have a good solution?
This problem is a real PITA to solve. It doesn't help that the API's that work are deprecated in iOS7, or that the iOS7 replacement API's are broken. Blah!
Your solution is nice, however it uses a deprecated API (sizeWithFont:minFontSize:actualFontSize:forWidth:lineBreakMode:), and it's not very well encapsulated - you need to copy this code around to any cells or views where you want this behavior. On the plus side it's fairly efficient! One bug may be that the label hasn't been laid out yet when you do your calculation, but you perform your calculation based on its width.
I propose that you encapsulate this behavior in a UILabel subclass. By placing the sizing calculation in an overridden intrinsicContentSize method the label will auto-size itself. I wrote the following, which incorporates your code that will execute on iOS6, and my version using non-deprecated API's for iOS7 or better:
#implementation TSAutoHeightLabel
- (CGSize) intrinsicContentSize
{
NSAssert( self.baselineAdjustment == UIBaselineAdjustmentAlignCenters, #"Please ensure you are using UIBaselineAdjustmentAlignCenters!" );
NSAssert( self.numberOfLines == 1, #"This is only for single-line labels!" );
CGSize intrinsicContentSize;
if ( [self.text respondsToSelector: #selector( boundingRectWithSize:options:attributes:context: )] )
{
NSStringDrawingContext* context = [NSStringDrawingContext new];
context.minimumScaleFactor = self.minimumScaleFactor;
CGSize inaccurateSize = [self.text boundingRectWithSize: CGSizeMake( self.bounds.size.width, CGFLOAT_MAX )
options: NSStringDrawingUsesLineFragmentOrigin
attributes: #{ NSFontAttributeName : self.font }
context: context].size;
CGSize accurateSize = [self.text sizeWithAttributes: #{ NSFontAttributeName : [UIFont fontWithName: self.font.fontName size: 12.0] } ];
CGFloat accurateHeight = accurateSize.height * inaccurateSize.width / accurateSize.width;
intrinsicContentSize = CGSizeMake( inaccurateSize.width, accurateHeight);
}
else
{
CGFloat actualFontSize;
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
[self.text sizeWithFont: self.font
minFontSize: self.minimumFontSize
actualFontSize: &actualFontSize
forWidth: self.frame.size.width
lineBreakMode: NSLineBreakByTruncatingTail];
#pragma GCC diagnostic pop
CGRect lineBox = CTFontGetBoundingBox((__bridge CTFontRef)([UIFont fontWithName: self.font.fontName size: actualFontSize]));
intrinsicContentSize = lineBox.size;
}
return intrinsicContentSize;
}
#end
This implementation isn't perfect. I had to ensure using baselineAdjustment == UIBaselineAdjustmentAlignCenters, and I'm not 100% certain I understand why. And I'm not happy with the hoops I had to jump through to get an accurate text height. There's also a few pixel difference between what my calculation produces, and yours. Feel free to play with it and adjust as necessary :)
The boundingRectWithSize:options:attributes:context API seems pretty broken to me. While it (mostly!) correctly constrains the text to the input size, it doesn't calculate the correct height! The height it returns is based on the line-height of the supplied font, even if a scaling is in play. My guess is this is why UILabel doesn't have this behavior by default? My workaround is to calculate an unconstrained size where both the height and width are accurate, then use the ratio between the constrained and unconstrained widths to calculate the accurate height for the constrained size. What a PITA. There are lots of complaints in the Apple dev forums and here on SO that point out that this API has a number of issues like this.
So I found a workaround. It's a little dicey, but it works.
So what I did was add a height constraint to my line of text in IB, and grab a reference to that in my view.
Then in layoutSubviews, I update my constraint height based on the size of the font, which I have to calculate:
- (void)layoutSubviews {
if (self.titleLabel.text) {
CGFloat actualFontSize;
CGSize titleSize = [self.titleLabel.text sizeWithFont:self.titleLabel.font minFontSize:9.0 actualFontSize:&actualFontSize forWidth:self.titleLabel.frame.size.width lineBreakMode:NSLineBreakByTruncatingTail];
CGRect lineBox = CTFontGetBoundingBox((__bridge CTFontRef)([UIFont fontWithName:#"ProximaNova-Regular" size:actualFontSize]));
self.titleHeightConstraint.constant = lineBox.size.height;
}
[super layoutSubviews];
}
At first I was just setting it to the actual font size, but even with an adjustment (*1.2) it was still clipping the smaller font sizes. The key was using CTFontGetBoundingBox with the font size determined from my calculation.
This is pretty unfortunate, and I'm hoping there's a better way. Perhaps I should switch to wrapping.
TomSwift thanks for your answer, i really struggled with this issue.
If someone is still getting weird behaviour, i had to change:
intrinsicContentSize = CGSizeMake( inaccurateSize.width, accurateHeight);
to
intrinsicContentSize = CGSizeMake( inaccurateSize.width, accurateHeight * 2);
then it worked like charm.
What you're looking for is these two lines of code.
myLabel.numberOfLines = 0;
myLabel.lineBreakMode = UILineBreakModeWordWrap;
and you will also find this in the Attributes Inspector under "Line Breaks" and "Lines".

Resources