I'm using a UILabel for the titleView of a navigation bar (I'm making simple in-app web browser). It works fine, except that when I present a modal view controller, the titleView shifts from the center of the navbar to the far left (underneath the back button). I've tested in 3.0 and up. Here is relevant code:
- (void)viewDidLoad {
[super viewDidLoad];
// Title view label
CGRect labelFrame = CGRectMake(0.0, 0.0, 120.0, 36.0);
UILabel *label = [[[UILabel alloc] initWithFrame:labelFrame] autorelease];
label.font = [UIFont boldSystemFontOfSize:14];
label.numberOfLines = 2;
label.backgroundColor = [UIColor clearColor];
label.textAlignment = UITextAlignmentCenter;
label.textColor = [UIColor whiteColor];
label.shadowColor = [UIColor blackColor];
label.shadowOffset = CGSizeMake(0.0, -1.0);
label.lineBreakMode = UILineBreakModeMiddleTruncation;
self.navigationItem.titleView = label;
}
-(void)displayComposerSheet:(NSString*)mailto
{
MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
picker.mailComposeDelegate = self;
[self presentModalViewController:picker animated:YES];
[picker release];
}
Screenshots:
Any idea why this is happening? Thanks.
I looked into the problem with some hit and try and found the following facts:
If the UINavigationBar doesn't have the rightBarButtonItem, the titleView shifts towards the right by ~30pts.
It could be reproduced for leftBarButtonItem. But I haven't tried.
In a scenario where the a default UINavigationBar's (with no changes to rightBarButtonItem defaults) titleView is set. And then a new UIView is pushed to the navigation stack which HAS a rightBarButtonItem. Now, if this view is popped [with back button], the navigation bar will remove the rightBarButtonItem. And this will account for the weird offset that shifts the titleView towards a side.
How I fixed the problem was like this:
self.navigationItem.titleView = myCustomTitleView;
// Fake right button to align titleView properly.
UIBarButtonItem *rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:[[UIView alloc] initWithFrame:CGRectMake(0, 0, 50, 1)]];
// Width equivalent to system default Done button's (which appears on pushed view in my case).
rightBarButtonItem.enabled = NO;
self.navigationItem.rightBarButtonItem = rightBarButtonItem;
Everything is sweet now. yummmm.
Thanks to DougW for pointing me in right direction. Here's the best hack I found. Basically I retain the UILabel as a class property. Before presenting modal view I unset the titleView, and then reset it immediately after. When the modal view is dismissed I unset then reset the titleView. To the user none of this is visibly notable.
-(void)displayComposerSheet:(NSString*)mailto
{
self.navigationItem.titleView = nil;
MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
picker.mailComposeDelegate = self;
picker.navigationBar.tintColor = [APPDELEGATE getNavTintColor];
[picker setToRecipients:[NSArray arrayWithObject:mailto]];
[self presentModalViewController:picker animated:YES];
[picker release];
self.navigationItem.titleView = titlelabel;
}
- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error
{
self.navigationItem.titleView = nil;
self.navigationItem.titleView = titlelabel;
[self dismissModalViewControllerAnimated:YES];
}
Does it animate? It may be animating the title view as though it's transitioning to a new view. I don't see anything wrong with your code as written.
I would suggest in your displayComposerSheet, you just unset the titleView, or animate the alpha of the titleView to 0.0. Then, animate it back to 1.0 when you dismiss the modal view controller. Not ideal, but it may look better that way.
Frankly, the whole UINavigation system is crap. We went ahead and re-wrote it ground up because of bizarre issues like these.
The only problem is your frame size. so u have to change it.
Try this one.
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 36.0)];
label.font = [UIFont boldSystemFontOfSize:14];
label.numberOfLines = 2;
label.backgroundColor = [UIColor clearColor];
label.textAlignment = UITextAlignmentCenter;
label.textColor = [UIColor whiteColor];
label.shadowColor = [UIColor blackColor];
label.shadowOffset = CGSizeMake(0.0, -1.0);
label.lineBreakMode = UILineBreakModeMiddleTruncation;
label.text=#"Stack Overflow";
self.navigationItem.titleView = label;
You can try move the code in viewDidAppear:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
// You code to customize title view
self.navigationItem.titleView = logoImage;
}
It works for me.
If you change the width size to be small like 100 points or smaller instead of 120 you set, this problem may go away. Setting width of the label smaller worked for me.
UIView *view= [[UIView alloc] initWithFrame:CGRectMake(0, 0, 40, 40)];
[view setUserInteractionEnabled:NO];
view.backgroundColor=[UIColor colorWithPatternImage:[UIImage imageNamed:#"logo_small.png"]];
UIBarButtonItem *barButton=[[UIBarButtonItem alloc]initWithCustomView:view ];
self.navigationItem.leftBarButtonItem = barButton;
Related
I would like to show a small icon next to the title in my UINavigationController.
Through the magic of Photoshop, like this:
I know I need to create a new view and build the image and title into it. Here is what I am doing:
In viewDidLoad in the UINavigationController view controller, I call the method
[self setTitleBar];
Which calls this method:
- (void) setTitleBar {
CGRect navBarFrame = self.navigationController.navigationBar.frame;
//UIView *titleView = [[UIView alloc] initWithFrame:CGRectMake(navBarFrame.origin.x, navBarFrame.origin.y, (leftButtonFrame.origin.x + leftButtonFrame.size.width) - rightButtonFrame.origin.x, navBarFrame.size.height)];
UIView *titleView = [[UIView alloc] initWithFrame:CGRectMake(navBarFrame.origin.x, navBarFrame.origin.y,self.view.frame.size.width,navBarFrame.size.height)];
titleView.backgroundColor = [UIColor clearColor];
CGPoint tvCenter = CGPointMake(titleView.frame.size.width/2, titleView.frame.size.height/2);
UIImage * icon = [UIImage imageNamed:#"star"];
UIImageView *iconView = [[UIImageView alloc] initWithImage:icon];
iconView.frame = CGRectMake(0, 0, icon.size.width, icon.size.height);
UILabel *title = [[UILabel alloc] init];
title.backgroundColor = [UIColor clearColor];
title.textColor = [UIColor whiteColor];
title.textAlignment = NSTextAlignmentCenter;
title.text = #"SOME TITLE";
title.frame = CGRectMake(0, 0, 100, titleView.frame.size.height);
[title sizeToFit];
iconView.center = CGPointMake(tvCenter.x - (icon.size.width/2), tvCenter.y);
[titleView addSubview:iconView];
[titleView addSubview:title];
self.navigationItem.titleView = titleView;
}
My logic in the titleView is: Get the left most button's frame and get the right most buttons frame. THEN do some math to figure out how big the view can be. That should be the titleView's frame size.
However, I can't seem to get it to work. If I plug in a frame size of 0,0,100,40; then it shows the frame but everything is squished together. But you see it. I know that 100 should be dynamic to ensure that the title is shown.
But I can't seem to figure it out.
Any help?
You can place objects on the Navigation Controller View, as subviews.
- (void) setTitleBar {
//Let's say your icon size is 20
int starSize = 20;
//Now you'll have to calculate where to place the ImageView respect the TextSize (for this you'll need to know the text and font of your UINavigationItem title)
CGSize textSize = [#"SOME TITLE" sizeWithAttributes:#{NSFontAttributeName:[UIFont fontWithName:#"navfontname" size:15]}];
UIImageView *startImageView = [[UIImageView alloc] initWithFrame:CGRectMake(self.navigationController.view.frame.size.width/2 - textSize.width/2, self.navigationController.view.frame.size.height/2 - starSize/2, starSize,starSize)];
startImageView.image = [UIImage imageNamed:#"star"];
[self.navigationController.view addSubview:startImageView];
}
- (void)setRightNavigationBarViewForUser {
UIBarButtonItem *spacer = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace
target:nil action:nil];
spacer.width = 760;
NSString *title = [VimondStore sessionManager].userName;
UIView *tempView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 144, 44)];
tempView.backgroundColor = [UIColor clearColor];
UIImageView *tempImageView = [[UIImageView alloc] initWithFrame:CGRectMake(4, 0, 44, 44)];
tempImageView.image = [UIImage imageNamed:#"user.png"];
UILabel *tempLabel = [[UILabel alloc] initWithFrame:CGRectMake(44, 0, 80, 44)];
tempLabel.backgroundColor = [UIColor clearColor];
tempLabel.text = title;
tempLabel.font = [UIFont boldSystemFontOfSize:14.0];
tempLabel.textColor = [UIColor whiteColor];
tempLabel.textAlignment = NSTextAlignmentLeft;
tempLabel.adjustsFontSizeToFitWidth = YES;
tempLabel.minimumScaleFactor = 0.8;
[tempView addSubview:tempImageView];
[tempView addSubview:tempLabel];
UIBarButtonItem *userView = [[UIBarButtonItem alloc]initWithCustomView:tempView];
NSArray *items = #[spacer ,userView];
self.navigationTableViewController.navigationItem.rightBarButtonItems = items;
}
- (void)navigateToHome {
[self setRightNavigationBarViewForUser];
self.loginViewController = nil;
[self showCenterPanelAnimated:YES];
[self setLeftBarButtonForDrawerTitle];
NSAssert([self.centreViewController isKindOfClass:[GGBaseViewController class]], #"Must be of GGBaseViewController class");
[GenreNavigator navigateToRoot:(GGBaseViewController*)self.centreViewController completionHandler:nil];
}
My code is given above: The problem, I am facing is that navigation right bar button items are not visible first time when I navigate to home. When I navigate to some other page and comes back then its visible. The first method is used to create right navigation bar button items.
From Apple doc on rightBarButtonItems, you can see that most likely your custom view is too wide and your button is not showing because it does not fit. Test making it narrower and see if it appears?
Discussion
This array can contain 0 or more bar button items to display on the right side of the navigation bar. Items are displayed right-to-left in the same order as they appear in the array. Thus, the first item in the array is the rightmost item and other items are added to the left of the previous item.
If there is not enough room to display all of the items in the array, those that would overlap the title view (if present) or the buttons on the left side of the bar are not displayed.
On iOS7.0.3 - 7.0.6, my searchBar colour is Gold/yellow colour like this:
But on iOS 7.1, colour becomes like this:
I set
searchBar.tintColor = [UIColor clearColor];
searchBar.backgroundColor = goldColor;
searchBar.tintColor = [UIColor blackColor];
I've tried so many ways and all are failed. Can anyone figure out what changes in iOS 7.1?
============== My fix ===============
I fix this problem by covering a view on searchBar and add the search text filed as subview on this new view.
I need point out that the gold status bar is a subView of searchBar, and it's frame is CGRectMake(0, -20, 320, 20) and it's background colour is gold.
At first, I set this:
_searchBar.translucent = YES;
_searchBar.scopeBarBackgroundImage = [self imageWithColor:UWGold];
and looks like this:
Then, I expand the view cover the status bar, I changed the view's frame.size.height + searchBar's height, then use this line:
UITextField *textSearchField = [_searchBar valueForKey:#"_searchField"];
to get the textSearchField, then add this textSearchField to the cover view.
At last, the searchBar is exactly like when on iOS 7.0
Not a good way, I need figure out what changes on iOS 7.1 and use a right way to implement this.
Try this:
if(IOS_7)
{
self.searchBar.searchBarStyle = UISearchBarStyleMinimal;
self.searchBar.backgroundImage = [UIImage imageWithColor:[UIColor redColor] cornerRadius:5.0f];
}
Hopefully this will help you.
None of the above answers worked for me on iOS 7/8. Here's some setup code that did the trick:
searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.view.frame), 44)];
searchBar.scopeButtonTitles = #[#"Scope1", #"Scope2"];
searchBar.selectedScopeButtonIndex = 0;
searchBar.backgroundColor = [UIColor clearColor];
searchBar.barTintColor = [UIColor clearColor];
searchBar.translucent = YES; // SUPER IMPORTANT, REMOVING THIS MESSED UP THE SCOPE BAR
// ONLY USE IMAGES, NOT BACKGROUND COLORS
UIImage *searchBarBackgroundImage = [[UIImage imageNamed:#"SearchBarBackgroundImage"];
UIImage *scopeBarBackgroundImage = [[UIImage imageNamed:#"ScopeBarBackgroundImage"];
[searchBar setBackgroundImage:searchBarBackgroundImage
forBarPosition:UIBarPositionAny
barMetrics:UIBarMetricsDefault];
searchBar.scopeBarBackgroundImage = scopeBarBackgroundImage;
searchBar.tintColor = [UIColor whiteColor];
I used next approach for changing backgroundColor of searchBar
1.As suggested by #Ben Jackson - set BackgroundImage
[self.searchBar setBackgroundImage:[self imageWithColor:[UIColor blueColor]] forBarPosition:UIBarPositionAny
barMetrics:UIBarMetricsDefault];
2.Change textField to what u need according to design
NSArray *searchBarSubViews = [[self.searchBar.subviews objectAtIndex:0] subviews];
for( int i = 0; i < searchBarSubViews.count; i++) {
if([[searchBarSubViews objectAtIndex:i] isKindOfClass:[UITextField class]]) {
UITextField *searchTextField = (UITextField *)[searchBarSubViews objectAtIndex:i];
[searchTextField setTintColor:[UIColor blueColor]];
searchTextField.placeholder = #"Search";
searchTextField.backgroundColor = [UIColor whiteColor];
searchTextField.layer.borderColor = [UIColor blueColor].CGColor;
searchTextField.layer.borderWidth = 1.0f;
searchTextField.layer.cornerRadius = 8.0f;
searchTextField.leftViewMode = UITextFieldViewModeNever;
}
}
Also method for image from color - here
Result:
I've embedded my first view into a NavigationController and then i set the segue as push.
I want to change in each view the title of the Navigation bar to display something and update it through my code.
i tried to call the navigation controller like this:
self.navigationController.navigationBar.topItem.title = #"YourTitle";
but this wont work, how can I do it?
Navigation controller gets the title from the viewcontroller so
this will do the job
- (void)viewDidLoad {
[super viewDidLoad];
self.title = #"Some Title";
}
This works for me:
self.navigationItem.title = #"YourTitle";
Hope it helps.
self.title = #"My Title"
This will change the navigation bars title as well as the title elements that refer to this view controller (eg. tab bar etc.)
self.navigationItem.title = #"My Title";
This will change only the title for the navigation bar for current view controller.
You can replace title view too:
UIView* titleView = [[UIView alloc] init];
[self.navigationItem setTitleView: titleView];
if u only change the navigation bar title then try this
on initwithnibname method
self.title=#"your title";
but you want to give a color or font size of title then u want to take a UIlable on it
UILabel *label = [[UILabel alloc] initWithFrame:CGRectZero];
label.backgroundColor = [UIColor clearColor];
label.font = [UIFont boldSystemFontOfSize:20.0];
label.shadowColor = [UIColor colorWithWhite:0.0 alpha:0.5];
label.textAlignment = UITextAlignmentCenter;
label.textColor = [UIColor blackColor];
self.navigationItem.titleView = label;
label.text =#"your title";
[label sizeToFit];
I have a bit of code that allows me to customize the Navigation Bar title of a view to allow for shrinking / truncating of long titles. The code works fine almost everywhere, however when it's used in a UITableViewController, the title never appears.
The code in question is:
- (void)viewDidLoad
{
[super viewDidLoad];
//Nav bar title for truncating longer titles
CGRect frame = CGRectMake(0, 0, 400, 44);
UILabel *label = [[UILabel alloc] initWithFrame:frame];
label.backgroundColor = [UIColor clearColor];
label.font = [UIFont boldSystemFontOfSize:20.0];
label.textAlignment = UITextAlignmentCenter;
label.textColor = [UIColor whiteColor];
label.adjustsFontSizeToFitWidth = YES;
label.minimumFontSize = 10.0f;
label.lineBreakMode = UILineBreakModeTailTruncation;
label.text = #"This is a really long title. It will shrink and eventually get truncated correctly.";
self.navigationItem.titleView = label;
}
I've put together a small demo project that illustrates the problem.
https://sites.google.com/site/coffeestainit/files/NavTitleError.zip
I just went through your project. The problem is that in your storyboard, you have not connected your tableViewController to the FirstViewController. So the viewDidLoad of the
FirstViewController is never called.
When I set the custom class of your TableViewController to FirstViewController in the storyboard, it set the label as title, as expected