center custom title in UINavigationBar? - iphone

I have a custom UINavigationBar title and a custom back button.
My problem is that the title is not centered on the iPhone.
It is as if my back button is pushing the title over to the right. Any Idea how I can center it?
int height = self.navigationController.navigationBar.frame.size.height;
int width = self.navigationController.navigationBar.frame.size.width;
UILabel *navLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, width + 300, 20)];
navLabel.backgroundColor = [UIColor whiteColor];
navLabel.textColor = [UIColor redColor];
navLabel.font = [UIFont fontWithName:#"Helvetica" size:30];
navLabel.textAlignment = UITextAlignmentCenter;
self.navigationItem.titleView = navLabel;
[navLabel release];
((UILabel *)self.navigationItem.titleView).text = self.title;
Thanks!
edit I removed superfluous code and added this picture:
Notice how the title is pushed over to accomodate the button....

iOS is doing this because the frame you initialize is alway 300+width pixels. It is trying to center the full frame, the frame is larger than the space it wants to fit it in (because of the button) and therefore your label gets pushed to the right.
What you need to do is give the Frame of the navLabel the minimum size it needs.
So if your text is only 100px wide, but the frame is 400px, then iOS is trying to center the 400px inside the Navigation header, and doesn't have enough space. When you set the size to the actual 100px that is needed, iOS will center your header correctly, because there is plenty of space to center 100px.
The code snippet below should help you to detect the minimum size your frame needs, depending on the font and the text you try to put in.
Make sure the frame of the label is as small as possible, but does not exceed the max width.
(the width of the navigation bar).
UIFont* titleFont = [UIFont fontWithName:#"Helvetica" size:30];
CGSize requestedTitleSize = [titleText sizeWithAttributes:#{NSFontAttributeName: titleFont}];
CGFloat titleWidth = MIN(maxTitleWidth, requestedTitleSize.width);
UILabel *navLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, titleWidth, 20)];
navLabel.backgroundColor = [UIColor whiteColor];
navLabel.textColor = [UIColor redColor];
navLabel.font = [UIFont fontWithName:#"Helvetica" size:30];
navLabel.textAlignment = NSTextAlignmentCenter;
navLabel.text = titleText;
self.navigationItem.titleView = navLabel;
Swift 5.0
let titleFont = UIFont.systemFont(ofSize: 17.0)
let title = "My Title"
let titleSize = title.size(withAttributes: [.font: titleFont])
let frame = CGRect(x: 0, y: 0, width: titleSize.width, height: 20.0)
let titleLabel = UILabel(frame: frame)
titleLabel.font = titleFont
titleLabel.textColor = .red
titleLabel.textAlignment = .center
titleLabel.text = title
navigationItem.titleView = titleLabel

I had the same problem before. I had a UINavigationbar with right- and left-button.
I want to center an image on the UINavigationbar. So I had to put the image into an UIView with width 0.
The image self get a x-value which is half of own width.
UINavigationItem *item = navigationController.topViewController.navigationItem;
UIView *backView =[[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, 30)];
[img_logo setFrame:CGRectMake(-45, 5, 90, 20)];
[backView addSubview:img_logo];
item.titleView = backView;

Nice answer! However sizeWithFont is now deprecated. You would want to do something like this now.
NSDictionary *textTitleOptions = [NSDictionary dictionaryWithObjectsAndKeys: [UIFont fontWithName:#"Helvetica" size:30], NSFontAttributeName, nil];
CGSize requestedTitleSize = [[NSString stringWithFormat:#"Your String"] sizeWithAttributes:textTitleOptions];
CGFloat titleWidth = MIN(self.view.frame.size.width, requestedTitleSize.width);
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, titleWidth, 44)];

I used autolayout constraints to solve this issue:
Add UILabel into a UIView.
Set constraints of centerX for the UILabel:
self.titleLabelCenterXConstraint = [NSLayoutConstraint constraintWithItem:self.titleLabel attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterX multiplier:1.0f constant:0.0f];
In the UIView layoutSubViews to adjust the centerX offset value:
- (void)layoutSubviews
{
[super layoutSubviews];
CGFloat screenCenter = CGRectGetMidX([UIScreen mainScreen].bounds);
CGFloat diffCenter = screenCenter - CGRectGetMidX(self.frame);
self.titleLabelCenterXConstraint.constant = diffCenter;
}
set UIView to navigationItem titleView

Swift 2.3:
let tlabel = UILabel(frame: CGRectMake(0, 0, 200, 40))
tlabel.text = self.title
tlabel.textColor = UIColor.whiteColor()
tlabel.font = UIFont.boldSystemFontOfSize(17) //UIFont(name: "Helvetica", size: 17.0)
tlabel.backgroundColor = UIColor.clearColor()
tlabel.adjustsFontSizeToFitWidth = true
tlabel.textAlignment = .Center
self.navigationItem.titleView = tlabel

Swift 3 for #BHuelse's answer:
let image = UIImage(named: "logo")
let logoView = UIView.init(frame: CGRect(x: 0, y: 0, width: 0, height: 30))
let imageView = UIImageView(frame: CGRect(x: -45, y: 5, width: 90, height: 20))
imageView.image = image
imageView.contentMode = .scaleAspectFit
logoView.addSubview(imageView)
self.navigationItem.titleView = logoView

The title is not centered in the navbar itself. It is centered between the left buttons and the right buttons of the navbar. This means that if you have a big button on the left, the title will be shifted to the right.
You can change the center by adding a centered constraint to your title and then modifying it so it's really the center of the navbar :
// Position the title in the middle of the navbar and not in the middle of buttons
fileprivate func centerTitle () {
if let navigation = self.navigationController {
let titleMiddle = navigation.navigationBar.convert(titleViewLabel.frame, from: titleViewLabel.superview).midX
let diff = navigation.navigationBar.center.x - titleMiddle
constraintTitleViewCentered.constant += diff
}
}

Related

How to add space at start of UITextField

I am creating an app that contain multiple UITextField. In the textField i have sated border type to none and background image. It display fine, But now my text is started from the lest border which does not look good, like this
How can i add space at the start of the textfield?
Try this
UILabel * leftView = [[UILabel alloc] initWithFrame:CGRectMake(10,0,7,26)];
leftView.backgroundColor = [UIColor clearColor];
textField.leftView = leftView;
textField.leftViewMode = UITextFieldViewModeAlways;
textField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
Here's #Kalpesh's answer in Swift 3.x:
let leftView = UILabel(frame: CGRectMake(10, 0.0, 7, 26))
leftView.backgroundColor = .clearColor()
customField.leftView = leftView
customField.leftViewMode = .Always
customField.contentVerticalAlignment = .Center
Swift 4.x
let leftView = UILabel(frame: CGRect(x: 10, y: 0, width: 7, height: 26))
leftView.backgroundColor =.clear
customField.leftView = leftView
customField.leftViewMode = .always
customField.contentVerticalAlignment = .center
You should subclass UITextField and override drawText function.
check this for help
OR
You can do following:
UIView *paddingView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 15, height_of_textfiled)];
textField.leftView = paddingView;
textField.leftViewMode = UITextFieldViewModeAlways;
Objective c
For padding only placeholder this code will work
usernameTF.attributedPlaceholder = [[NSAttributedString alloc] initWithString:#" Your text"];
For padding both placeholder and text of the UITextField this below code will work
usernameTF.layer.sublayerTransform = CATransform3DMakeTranslation(40, 0, 30);
Swift 3.0
For padding only placeholder this code will work
yourTextField.attributedPlaceholder = NSAttributedString(string: " YourText")
For padding both placeholder and text of the UITextField this below code will work
usernameTF.layer.sublayerTransform = CATransform3DMakeTranslation(40, 0, 30)
You can subclass UITextField and override textRectForBounds and editingRectForBounds.
For example,
- (CGRect)textRectForBounds:(CGRect)bounds {
return CGRectMake(bounds.origin.x + 10, bounds.origin.y + 5, bounds.size.width - 20, bounds.size.height - 10);
}
- (CGRect)editingRectForBounds:(CGRect)bounds {
return CGRectMake(bounds.origin.x + 10, bounds.origin.y + 5, bounds.size.width - 20, bounds.size.height - 10);
}
Swift 4
yourTextField.layer.sublayerTransform = CATransform3DMakeTranslation(10, 0, 10)
You can put the textfield background image in an image view,above the imageview put your textfield a space left.
-(void)textField:(UITextField *) textField didBeginEditing {
if ([textField.text isEqualToString:#""] || textField.text == NULL) {
textField.text = #" ";
}
}

Controlling size / position of UINavigationItem titleView

In my app, I have some custom titles (with lettering that isn't a font) stored in pngs that I want to put as the title of my navigation. I want the lettering in the titles all to be the same size for each different view controller, so in illustrator I've worked on making it all the same size and width (affording blank space to account for shorter strings). I do the following:
UIImageView *titleImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"SelectAnAlbumTitleLettering"]];
titleImageView.contentMode = UIViewContentModeCenter;
self.navigationItem.titleView = titleImageView;
[titleImageView release];
And it seems the image is arbitrarily resized and positioned based on the elements included on each navigationBar (i.e. back button, right button etc.).
I'm wondering, how can I gain control of titleView so I can make it implement the size and position that I want and so it isn't arbitrarily resized / repositioned.
Instead of using your image view as the title view, create another view that contains the image view. Set that view as the title view of the navigation item; now you’re free to adjust the image view’s frame within the title view.
You can control size and position of UINavigationbar titleview. Don't set imageview as titleview directly. Instead create a custom UIView and then set its frame as per your requirement and add your titleImageView as its subview.
UIView *backView =[[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 40)];// Here you can set View width and height as per your requirement for displaying titleImageView position in navigationbar
[backView setBackgroundColor:[UIColor greenColor]];
UIImageView *titleImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"SelectAnAlbumTitleLettering"]];
titleImageView.frame = CGRectMake(45, 5,titleImageView.frame.size.width , titleImageView.frame.size.height); // Here I am passing origin as (45,5) but can pass them as your requirement.
[backView addSubview:titleImageView];
//titleImageView.contentMode = UIViewContentModeCenter;
self.navigationItem.titleView = backView;
Hope it helps you.
In Swift, you can do it like this:
var titleView = UIView(frame: CGRectMake(0, 0, 100, 40))
var titleImageView = UIImageView(image: UIImage(named: "cocolife"))
titleImageView.frame = CGRectMake(0, 0, titleView.frame.width, titleView.frame.height)
titleView.addSubview(titleImageView)
navigationItem.titleView = titleView
Updated Swift4 code:
var titleView = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 40))
var titleImageView = UIImageView(image: UIImage(named: "headerlogo"))
titleImageView.frame = CGRect(x: 0, y: 0, width: titleView.frame.width, height: titleView.frame.height)
titleView.addSubview(titleImageView)
navigationItem.titleView = titleView
Update swift 5
var titleView = UIView()
navigationItem.titleView?.translatesAutoresizingMaskIntoConstraints = false
navigationItem.titleView = titleView

Sizing UITextView to its content isn't working

Here's the code for a UITextView that I want to size to the height of its content.
If I write the textView.frame height explicitly like:
textView.frame = CGRectMake(100, 12, 320, 458);
the textView sizes to it's content as expected.
If, however, I write it like the following. It doesn't even display although the NSLog statement says that there's a value to textView.contentSize.height
UITextView *textView = [[UITextView alloc] init];
textView.layer.borderWidth = 5.0f;
textView.layer.borderColor = [[UIColor redColor] CGColor];
textView.text = [item objectForKey:#"description"];
textView.frame = CGRectMake(100, 12, 320, textView.contentSize.height);
NSLog(#"%f textviewcontnet size", textView.contentSize.height);
textView.editable = NO;
[self.view addSubview:textView];
When I log the output of:
NSLog(#"%f textviewcontent size", textView.contentSize.height);
I get "458.000000 textviewcontent size"
thanks for any help
I'd suggest trying:
UITextView *textView = [[UITextView alloc] init];
textView.layer.borderWidth = 5.0f;
textView.layer.borderColor = [[UIColor redColor] CGColor];
textView.text = [item objectForKey:#"description"];
textView.frame = CGRectMake(100, 12, 320, 458);
textView.editable = NO;
[self.view addSubview:textView];
textView.frame = CGRectMake(100, 12, 320, textView.contentSize.height);
I've heard that textView.contentSize.height doesn't work until it's been added to a view (though that's not my experience). More importantly, I don't know how it would interpret textView.contentSize.height if it doesn't yet know what the width of the control is. So go ahead, set the initial frame, do addSubview and then readjust the size based upon textView.contentSize.height.
Quickly copied out of one of my projects:
AppDelegate *appDelegate;
CGSize textSize1, textSize2;
appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
textSize1 = [self.subjectLabel.text sizeWithFont:[appDelegate fontNormal] constrainedToSize:CGSizeMake(300.0f, 10000.0f) lineBreakMode:NSLineBreakByWordWrapping];
self.subjectLabel.frame = CGRectMake(10, 5, 300, textSize1.height);
textSize2 = [self.descriptionLabel.text sizeWithFont:[appDelegate fontNormal] constrainedToSize:CGSizeMake(300.0f, 10000.0f) lineBreakMode:NSLineBreakByWordWrapping];
self.descriptionLabel.frame = CGRectMake(10, 5 + textSize1.height + 5, 300, textSize2.height);
[appDelegate fontNormal] just returns a UIFont object, the one that I am using for all "normal" text items. Don't worry about that too much. But it is important that you use the same font that is used for the text view too.
My example is a bit easier because it is a UILable. That works with a text view too but you will have to consider the insects. Easy solution, just substract some "fuzzy offset" from the width compared to the frame width of your text view.

Adding a label to a scroll view

I am trying to add a label to a scroll view, then set the contentSize of the scrollview to match the desired size of the label. The problem is I seem to have to make the contentSize bigger than the size of the label:
theScrollview = [[UIScrollView alloc] initWithFrame:CGRectMake(0,0,320,480)];
bodyLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 320.0, 50.0)];
bodyLabel.textColor = [UIColor whiteColor];
bodyLabel.backgroundColor = [UIColor clearColor];
bodyLabel.textAlignment = UITextAlignmentLeft;
bodyLabel.text = event.description; <- basically some long ass text here
bodyLabel.font=[UIFont systemFontOfSize:16.0];
bodyLabel.numberOfLines = 0;
bodyLabel.lineBreakMode = UILineBreakModeWordWrap;
here I think Im getting the necessary label size to contain the text
CGSize size = [event.description sizeWithFont:bodyLabel.font constrainedToSize:CGSizeMake(bodyLabel.frame.size.width, 9500) lineBreakMode:bodyLabel.lineBreakMode];
frame = bodyLabel.frame; // to get the width
frame.size.height = size.height;
bodyLabel.frame = frame;
here I set the contentSize to the label's Size, but it isn't big enough, I need to
set it to bodyLabel.frame.size.height + 80 for it to be covered in the scrolling.
theScrollview.contentSize = CGSizeMake(bodyLabel.frame.size.width, bodyLabel.frame.size.height);
[theScrollview addSubview:bodyLabel];
Thanks for any thoughts in advance!
[theScrollview addSubView: bodyLabel];

How to increase the UITextView height and X axis value in iPhone?

Am working in an iPhone app using UITextView. I am trying to increase the height of UITextView based on it's content length. It is working fine. But, when the height of uitextview increase the UITextView should change the height in up side not increase height in down.
This is the code am trying in my project,
baseView = [[UIView alloc] initWithFrame:CGRectMake(0, 50, 320, 50)];
baseView.backgroundColor = [UIColor lightGrayColor];
[self.view addSubview:baseView];
TextView = [[UITextView alloc] initWithFrame:CGRectMake(20, 10, 280, 40)];
TextView.backgroundColor = [UIColor whiteColor];
TextView.layer.borderWidth = 2;
TextView.delegate = self;
TextView.font = [UIFont fontWithName:#"Helvetica" size:16];
[baseView addSubview: TextView];
-(void)textViewDidChange:(UITextView *)textView
{
CGRect frame = messageTextView.frame;
frame.size.height = messageTextView.contentSize.height;
TextView.frame = CGRectMake(20, 10, 280, frame.size.height);
baseView.frame = CGRectMake(0, 50, 320, frame.size.height+20);
}
When the UITextView height is changing the effect textview height will be increase on top side. Can anyone please help me on this? Thanks in advance.
In the method you change the frames, also edit the frame.origin.y value of the textView
-(void)textViewDidChange:(UITextView *)textView
{
CGRect frame = messageTextView.frame;
frame.size.height = messageTextView.contentSize.height;
TextView.frame = CGRectMake(20, 0, 280, frame.size.height); //previous y was 10
baseView.frame = CGRectMake(0, 50, 320, frame.size.height+20);
}
Nonetheless, I believe you are aware that you have only 10 pixels for the textView to go up, as you are adding it to a BaseView view.