Strange offset on right bar button item - ios

I encountered a strange problem on the rightBarButtonItem of UINavigationController. The margin of the button disappears on iOS7, so it looks like this:
At first, I thought it was some mistakes in my UINavigationController related categories, but I removed all my customisation code and all the header files of categories, and simply use a UINavigationController and an empty view controller.
In - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
VCTestViewController *vc = [[[VCTestViewController alloc]init]autorelease];
UINavigationController *nc = [[[UINavigationController alloc]initWithRootViewController:vc]autorelease];
self.window.rootViewController = nc;
[self.window makeKeyAndVisible];
In VCTestViewController.m -> viewDidLoad
self.view.backgroundColor = [UIColor whiteColor];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc]initWithTitle:#"hello" style:UIBarButtonItemStyleBordered target:nil action:nil];
The problem still exists(as shown above). I can't figure out what is wrong. Do you have any idea about this problem?

you can share your line of code if it's not working:
- (UIBarButtonItem *)rightNavBarButton
{
UIButton *filterBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[filterBtn setTitle:#"hello" forState:UIControlStateNormal];
filterBtn.frame = CGRectMake(0, 0,40,27);
[filterBtn addTarget:self action:#selector(getFriendsList) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *filterNavBarItem = [[UIBarButtonItem alloc] initWithCustomView:filterBtn];
return filterNavBarItem;
}

I finally figure out what happened.
The link given by βhargavḯ is not the solution of my problem, but it's the cause of my problem. One of my colleagues wrote a category of UINavigationItem to narrow the empty space in iOS7. He then used method swizzling to exchanged the system method setRightBarButtonItem: with his own method. I didn't realise this.
So I think method swizzling would be extremely dangerous if you exchange the system methods with your own methods.

Related

How to create a UINavigationBar programmatically

I've recently started learning Obj-C and according to my friend (who is experienced with Obj-C), it's better if I learnt how to create a view programmatically and not rely on StoryBoards.
So... I've been trying to create a NavigationBar with a left button on it. But, when I run it, I get the actual NavigationBar, but not the button. Here's my code:
The AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc]
initWithFrame:[[UIScreen mainScreen] bounds]];
firstController = [[MainViewController alloc] init];
navController = [[UINavigationController alloc] initWithRootViewController:firstController];
self.window.rootViewController = navController;
[self.window makeKeyAndVisible];
return YES;
}
and here's the MainViewController.m:
- (void)viewDidLoad
{
[super viewDidLoad];
UIColor *navbarColor = [UIColor whiteColor];
self.view.backgroundColor = [UIColor whiteColor];
self.navigationController.navigationBar.barTintColor = navbarColor;
UIBarButtonItem *button = [[UIBarButtonItem alloc]initWithTitle:#"Settings" style:UIBarButtonItemStylePlain target:self action:NULL];
self.navigationController.navigationItem.leftBarButtonItem = button;
}
Any help would be appreciated. I'm fairly new to Objective-C but I understand the code concept, so you don't need to "baby" talk it when explaining ^.^
add this line before [self.window makeKeyAndVisible];
[self.window addSubview:navController.view];

UITabBar appearance setSelectionIndicatorImage does not work on first launch iOS7

I have a customised UITabBar and use the following code in the AppDelegate:
- (void)tabBarController:(MainUITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
[self customizeTabBar];
}
- (void)customizeTabBar {
NSLog(#"*******customizeTabBar*******");
UIImage *tabBackground = [[UIImage imageNamed:#"unselectedtab"]
resizableImageWithCapInsets:UIEdgeInsetsMake(0, 0, 0, 0)];
// Set background for all UITabBars
[[UITabBar appearance] setBackgroundImage:tabBackground];
// Set tint color for the images for all tabbars
[[UITabBar appearance] setSelectedImageTintColor:[UIColor whiteColor]];
// Set selectionIndicatorImage for all tabbars
[[UITabBar appearance] setSelectionIndicatorImage:[UIImage imageNamed:#"selectedtab"]];
}
- (void)tabBarController:(MainUITabBarController *)tabBarController didEndCustomizingViewControllers:(NSArray *)viewControllers changed:(BOOL)changed
{
NSLog(#"*******didEndCustomizingViewControllers*******");
}
This is all fine in iOS5+ but in 7 on first load the first TabBarItem the item indicator is white and the button seems to have been selected but the "selectedTab" image is not loaded.
When I press another tab the new tab is red and appears correctly - as does the first or any tab bar item selected after this - it only doesn't work on first launch.
customizeTabBar get called but the selected image does not appear on first launch.
didEndCustomizingViewControllers does not seem to get called at all.
This doesn't work in emulator or device on iOS7 - but does on iOS5, 6.
Any ideas?
Thanks in advance.
Setting the selection indicator image for the tab bar directly once again, apart from doing it via appearance, worked for me!
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
....
UITabBarController *tabBarContr = (UITabBarController *)self.window.rootViewController;
...
[[UITabBar appearance] setSelectionIndicatorImage:[UIImage imageNamed:#"tab_bar_selection_indicator.png"]];
// iOS7 hack: to make selectionIndicatorImage appear on the selected tab on the first app run
[[tabBarContr tabBar] setSelectionIndicatorImage:[UIImage imageNamed:#"tab_bar_selection_indicator.png"]];
return YES;
}
I am seeing this exact same issue. Here is my didFinishLaunching
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[self applyStyleSheet];
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
self.window.backgroundColor = [UIColor redColor];
self.window.tintColor = [UIColor whiteColor];
UITabBarController *tabBarController = [self setupTabBarController];
self.window.rootViewController = tabBarController;
[self.window makeKeyAndVisible];
return YES;
}
Here is how I setup the tab bar:
- (UITabBarController *)setupTabBarController
{
UITabBarController *tabBarController = [[UITabBarController alloc] init];
UINavigationController *nav1 = [[UINavigationController alloc] initWithRootViewController:[[FirstViewController alloc] init]];
UINavigationController *nav2 = [[UINavigationController alloc] initWithRootViewController:[[SecondViewController alloc] init]];
UINavigationController *nav3 = [[UINavigationController alloc] initWithRootViewController:[[ThirdViewController alloc] init]];
UINavigationController *nav4 = [[UINavigationController alloc] initWithRootViewController:[[FourthViewController alloc] init]];
UINavigationController *nav5 = [[UINavigationController alloc] initWithRootViewController:[[FifthViewController alloc] init]];
[tabBarController setViewControllers:#[nav1, nav2, nav3, nav4, nav5]];
return tabBarController;
}
And finally, this is the tab bar customization block:
- (void)applyStyleSheet
{
UITabBar *tabBar = [UITabBar appearance];
[tabBar setBackgroundImage:[UIImage imageWithColor:[UIColor redColor]]];
[tabBar setTintColor:[UIColor whiteColor]];
[tabBar setSelectionIndicatorImage:[UIImage imageNamed:#"tab-selected"]];
[tabBar setSelectedImageTintColor:[UIColor whiteColor]];
}
As stated, the "tab-selected" image is not loaded on the first tab. However, I added the following line after [self.window makeKeyAndVisible] so that my tab starts up with a different tab opened, and the "tab-selected" image does show up on this tab:
[tabBarController setSelectedIndex:1];
So here's my finalized didFinishLaunching with the subtle hack that makes it work :)
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[self applyStyleSheet];
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
self.window.backgroundColor = [UIColor redColor];
self.window.tintColor = [UIColor whiteColor];
UITabBarController *tabBarController = [self setupTabBarController];
self.window.rootViewController = tabBarController;
[self.window makeKeyAndVisible];
[tabBarController setSelectedIndex:1];
[tabBarController setSelectedIndex:0];
return YES;
}
ok.
not the best of fixes but hey have to submit.
Remove the customisation code in the appdelegate and in the projects xib file (is an old project) on the TabBars attributes inspector (using xcode 5) - add the tab bars background and selection images.
This works for ios7 without the need for any of the customisation code in the appdelegate.
For pre iOS5 + 6 (this app only supports 5+) however we still need the code so I added a simple check for version and kept the code as is:
#define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
if(SYSTEM_VERSION_LESS_THAN(#"7.0"))
{
UIImage *tabBackground = [[UIImage imageNamed:#"unselectedtab"]
resizableImageWithCapInsets:UIEdgeInsetsMake(0, 0, 0, 0)];
// Set background for all UITabBars
[[UITabBar appearance] setBackgroundImage:tabBackground];
[[UINavigationBar appearance] setTintColor:[UIColor blackColor]];
// Set tint colour for the images for all tabbars
[[UITabBar appearance] setSelectedImageTintColor:[UIColor whiteColor]];
// Set selectionIndicatorImage for all tabbars
[[UITabBar appearance] setSelectionIndicatorImage:nil];
[[UITabBar appearance] setSelectionIndicatorImage:[UIImage imageNamed:#"selectedtab.png"]];
}
I think I also have had the same problem when doing my design for the new App in iOS 7!!
iOS 7 has been built more of the stuff different as we all were used to things different.
Here as I have understood we all were using StoryBoards, and were unable to integrate that Segues in our Code! :)
So I choose not to mess with the code, after I tried most of all the StackOverFlow Answers regarding this! :) Because, why you wanna do so, when you have given a Goody Good Interface Builder (IB) and Story Boarding Tool?
Question:
When we have set our Selected Tab Image, background image specially for the tab bar, it doesn't shows which tab is selected with the image we have set in our code...???
Solution
Following are the screenshots of my StoryBoard Settings I did to solve this problem!
Select your TabBarController from your via document outline panel:
Set your settings for the Tab Bar from the Utilities Panel:
Then your Program is set up to run! It now knows that first tab is selected when the App first shows the First Tab View and also which image should be shown for all the Tab Bar indicators when each of them are selected! :)
hope you all got a clue!!!
If I helped you I'm Happy!!!
But if I have wasted your Time I'm So Sorry!!! :(
But trust me, This worked me like a charm!!!
- (void)customizeTabBar {
UIImageView *customizeTabBar = [[UIImageView alloc]initWithFrame:CGRectMake(0,0,320.0,50)];
customizeTabBar.image=[UIImage imageNamed:#"Tab_bar.png"];
firstTab = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"tab1.png"] highlightedImage:[UIImage imageNamed:#"tab11.png"]];
[firstTab setFrame:CGRectMake(8.0,01.0,90.0,49.0)];
[customizeTabBar addSubview: firstTab];
secondTab = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"tab2"] highlightedImage:[UIImage imageNamed:#"tab22"]];
[secondTab setFrame:CGRectMake(115.0,01.0,90.0,49.0)];
[customizeTabBar addSubview: secondTab];
thirdTab = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"tab3"] highlightedImage:[UIImage imageNamed:#"tab33"]];
[thirdTab setFrame:CGRectMake(223.0,01.0,90.0,49.0)];
[customizeTabBar addSubview: thirdTab];
self.tabBar.tag=10;
[self.tabBar addSubview:customizeTabBar];
}

Issue with adding buttons to UINavigationController

So this is how I make the navbar:
- (void)viewDidLoad
{
[super viewDidLoad];
UINavigationController *navBar = [[UINavigationController alloc] init];
[navBar willMoveToParentViewController:self];
navBar.view.frame = CGRectMake(0, 0, 320, 44);
[self.view addSubview:navBar.view];
[self addChildViewController:navBar];
[navBar didMoveToParentViewController:self];
...
And everywhere I have read says that this is how you add buttons:
UIBarButtonItem *button = [[UIBarButtonItem alloc]initWithTitle:#"test" style:UIBarButtonItemStyleBordered target:self action:#selector(print_message:)];
self.navigationItem.rightBarButtonItem = button;
[button release];
But the button does not show on the navbar. What is wrong with this code?
Unless you're building a custom container view controller (which is a relatively rare thing to do), you should not be building a UINavigationController inside your content controller's -viewDidLoad. While it will provide you a navigation bar, your view controller parent-child relationship will be backwards: your content controller will contain the navigation controller, rather than the other way around.
Instead, you need to create the navigation controller earlier in your app's startup process - maybe in your application delegate, or in your main storyboard if you're using one. Make sure that the new navigation controller has your content controller as its root controller (usually by way of -initWithRootViewController:). Then your self.navigationItem configuration will work properly.
You should create your navigationbar probably differently:
In your xxxAppDelegate.m edit this method:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
//This is the ViewController of the view you want to be the root
xxxViewController *tvc = [[xxxViewController alloc]init];
//Now you have to initialize a UINavigationController and set its RootViewController
UINavigationController *nvc = [[UINavigationController alloc]initWithRootViewController:tvc];
//Now set the RootViewController to the NavigationViewController
[[self window]setRootViewController:nvc];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
So now you have a proper NavigationController. If you do this in the viewDidLoad method, the NavigationController will be made each time you reload your view.
Now in your xxxViewController.m edit your init method:
- (id)init
{
...
if (self) {
//Create a UINavigationItem
UINavigationItem *n = [self navigationItem];
//Create a new bar button item
UIBarButtonItem *button = [[UIBarButtonItem alloc]initWithTitle:#"test" style:UIBarButtonItemStyleBordered target:self action:#selector(print_message:)];
[[self navigationItem]setRightBarButtonItem:button];
}
return self;
}
This should now display a proper NavigationBar with a UIBarButtonItem.

How do i make the more button go always to more view?

I'm developing an app for ios with a Tab Bar. I have more than 5 buttons on the bar, so on the iphone i have the button more.
Now, suppose i have this buttons: Button1 Button2 Button3 Button4 More (and inside More) Button5 Button6.
If i click More and then Button5 i go in the view relative to Button5. Then i click Button2 (that is not in the More) and i go in the view relative to Button2.
So far so good.
Now if i click More i go not to More Tab but back to the view relative to Button5.
How do i make the more button go always to the more view?
You don't need to add more button. Just set the view controllers to the UITabBarController
- (void)setViewControllers:(NSArray *)viewControllers animated:(BOOL)animated
and it will automatically create a more button if you have more than 5 view controllers! i.e. the count of NSArray is greater than 5.
Another way you could do is, whenever the user presses more, the first button gets removed and other buttons gets added.
Basically you can create an array and keep all the buttons inside it. And then based on the button pressed you can navigate to that particular view.
For Ex:
Initially you have: Button1 Button2 Button3 Button4 Next
After Clicking Next: Prev Button3 Button4 Button5 Button6
I used this code in my app delegate.m to solve the problem
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
UITabBarController* tabBarController2 = (UITabBarController*)self.window.rootViewController;
if (tabBarController2.selectedIndex < 4) {
[tabBarController2.moreNavigationController popViewControllerAnimated:NO];
}
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
UIViewController *viewController1 = [[UIViewController alloc] init];
UIViewController *viewController2 = [[UIViewController alloc] init];
UIViewController *viewController3 = [[UIViewController alloc] init];
UIViewController *viewController4 = [[UIViewController alloc] init];
UIViewController *viewController5 = [[UIViewController alloc] init];
UIViewController *viewController6 = [[UIViewController alloc] init];
UIViewController *viewController7 = [[UIViewController alloc] init];
UIViewController *viewController8 = [[UIViewController alloc] init];
UIViewController *viewController9 = [[UIViewController alloc] init];
[viewController1.view setBackgroundColor:[UIColor whiteColor]];
[viewController2.view setBackgroundColor:[UIColor redColor]];
[viewController3.view setBackgroundColor:[UIColor greenColor]];
[viewController4.view setBackgroundColor:[UIColor grayColor]];
[viewController5.view setBackgroundColor:[UIColor blueColor]];
[viewController6.view setBackgroundColor:[UIColor yellowColor]];
[viewController7.view setBackgroundColor:[UIColor brownColor]];
[viewController8.view setBackgroundColor:[UIColor magentaColor]];
[viewController9.view setBackgroundColor:[UIColor purpleColor]];
[viewController1 setTitle:#"one"];
[viewController2 setTitle:#"two"];
[viewController3 setTitle:#"three"];
[viewController4 setTitle:#"four"];
[viewController5 setTitle:#"five"];
[viewController6 setTitle:#"six"];
[viewController7 setTitle:#"seven"];
[viewController8 setTitle:#"eight"];
[viewController9 setTitle:#"nine"];
self.tabBarController = [[UITabBarController alloc] init];
self.tabBarController.viewControllers = #[viewController1, viewController2, viewController3, viewController4, viewController5, viewController6, viewController7, viewController8, viewController9];
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
return YES;
}
I have added a sample AppDelegate code which I tried and its working absolutely fine for me. Let me know what problem your having in this.

Adding UINavigationController with back button [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I'm having trouble figuring out how to add a navigationcontroller to my iOS app. I need all of the views except the "home" screen to have a back button but I'm not sure how to add it.
Here is a link to my project:
https://www.dropbox.com/s/sv0y3oh1aftxl95/KFBNewsroom%204.zip
Remove the navigation bars from all of your NIBs and use a navigation controller (such as in the app delegate like NeverBe outlined), and then transition to the child controllers via a pushViewController rather than presentViewController as you're currently doing, and you should get your "back" button automatically. You'll also want to remove any references to dismissViewControllerAnimated, if you have any, as your back button will now do popViewControllerAnimated for you. If you need to programmatically pop anywhere, though, you can just used popViewControllerAnimated.
In your NIBs, you might also want to tweak the simulated metrics so you can design your NIBs with the navigation bar graphically represented, e.g.:
See the navigation controller section of the View Controller Catalog and refer to the UINavigationController Class Reference.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:[[KFBViewController alloc] initWithNibName:#"KFBViewController" bundle:nil]];
self.window.rootViewController = nav;
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
Call new view controller
KFBYouTubeView *youtubeView = [[KFBYouTubeView alloc] initWithNibName:#"KFBYouTubeView" bundle:nil];
[self.navigationController pushViewController:youtubeView animated:YES];
Update:
Method for add custom nav bar buttons
- (void)customizeNavigationButtonWithType:(NavigationBarButtonType)type
normalImageName:(NSString *)normalImageName
selectedImageName:(NSString *)selectedImageName
selector:(SEL)selector {
UIImage *img = [UIImage imageNamed:normalImageName];
UIImage *imgPressed = [UIImage imageNamed:selectedImageName];
UIButton *customButton = [UIButton buttonWithType:UIButtonTypeCustom];
[customButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[customButton setImage:img forState:UIControlStateNormal];
[customButton setImage:imgPressed forState:UIControlStateHighlighted];
customButton.frame = CGRectMake(0, 0, img.size.width, img.size.height);
[customButton addTarget:self action:selector forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *btn = [[UIBarButtonItem alloc] initWithCustomView:customButton];
switch (type) {
case NavigationBarButtonTypeLeft:
[self.navigationItem setLeftBarButtonItem:btn animated:YES];
break;
case NavigationBarButtonTypeRight:
[self.navigationItem setRightBarButtonItem:btn animated:YES];
break;
}
}
Usage:
[self customizeNavigationButtonWithType:NavigationBarButtonTypeRight
normalImageName:#"create.png"
selectedImageName:#"create_highlight.png"
selector:#selector(pressButton:)];

Resources