Modal View Controllers - UIBarButtonItems Do Not Persist - ios

I present modal view controllers, packaged in a UINavigationController.
When they first appear, the bar button items are alright.
However, if I click a button and a new view controller is pushed to the UINavigationController, and then I use the back button of that view controller, and it gets popped back to the original modal view controller, the buttons do not show up, (but they work when I click them -> just can't see them)
I can't seem to figure out why this occurs.
Here's some code.
Oh, and by the way, I customize the navigation controller's navigation bar's background. I have a feeling this may be causing this visual interference, but I don't know what to change to get it right.
In GGMainViewController:
GGSelectTeamsViewController *chooseTeam = [[GIFSelectTeamsViewController alloc] init];
UINavigationController* navigationController = [[UINavigationController alloc] initWithRootViewController:chooseTeam];
[self setupModalNavigationBar:navigationController];
[self presentViewController:navigationController animated:YES completion:nil];
- (void)setupModalNavigationBar:(UINavigationController *)nav {
// unnecessary code removed for a quicker read
// basically navigation bar has a background gradient as well as a bottom border
[nav.navigationBar.layer addSublayer:bottomBorder];
[nav.navigationBar.layer addSublayer:gradient];
}
In GGSelectTeamsViewController
- (void)viewDidLoad
{
[super viewDidLoad];
title = [[UILabel alloc] init];
title.text = someText;
title.backgroundColor = [UIColor clearColor];
title.textColor = [UIColor whiteColor];
self.navigationItem.titleView = title;
[title sizeToFit];
UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom];
[backButton setTitle:#"Back" forState:UIControlStateNormal];
[backButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
backButton.frame = someFrame;
[backButton addTarget:self action:#selector(goBack) forControlEvents:UIControlEventTouchUpInside];
[self.navigationItem setLeftBarButtonItem:[[UIBarButtonItem alloc] initWithCustomView:backButton] animated:NO];
UIButton *selectButton = [UIButton buttonWithType:UIButtonTypeCustom];
[selectButton setTitle:#"Select" forState:UIControlStateNormal];
[selectButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
selectButton.frame = someFrame;
[selectButton addTarget:self action:#selector(sendContent) forControlEvents:UIControlEventTouchUpInside];
[self.navigationItem setRightBarButtonItem:[[UIBarButtonItem alloc] initWithCustomView:selectButton] animated:NO];
}
Since the navigation items are set in the viewDidLoad method, why can't I see them (but they are still functional) when I return to it from another view controller?

That seems like an over-complicated way of doing this.
Why don't you create your own button and then use the setRightBarButtonItems:items: method from the UINavigationBar to set the buttons you want?
I'm guessing they disappear because you're adding them to the layer of the UINavigationBar.
Still, if you want to keep this method with the layers, you may want to add them in the viewWillAppear method, but you may need call the removeFromSuperlayer to make sure you don't add stuff more than once.
Hope this helps.

The problem was:
the gradients for the navigation bar (done by code)
The solution was:
use Sketch to create an image of the gradients and use the appearance proxy to set the image as a background image
[[UINavigationBar appearance] setBackgroundImage:[UIImage imageNamed:#"NavigationBarBackground"] forBarMetrics:UIBarMetricsDefault];

Related

iOS Button action doesn't work

I have a strange issue with iOS UIButton.
I have a UIViewController class:
#interface CustomViewController : UIViewController
Inside of this class I have a label called customLabel. In this label I have a button subview:
UIButton *addButton = [[UIButton alloc] init];
[customButton setImage:[UIImage imageNamed:#"image"] forState:UIControlStateNormal];
[customButton addTarget:self action:#selector(customButtonClicked) forControlEvents:UIControlEventTouchUpInside];
[customLabel insertSubview:customButton atIndex:1];
And of course, action method:
- (void)customButtonClicked
{
NSLog(#"- (void)customButtonClicked");
}
I also have a subclass for this view controller:
#interface MyNewCustomViewController : CustomViewController
This view controller is loaded inside UIWindow:
[self.navigationController pushViewController: myNewCustomViewController animated:YES];
Everything seems to be fine, label with button are at the correct positions, except the fact, that button click doesn't call action method...
Maybe you know, where the problem could be?
As long as you don't have another view over top of your current button and user interaction is enabled on the view. This should work.
// First make sure userInteractionEnabled is enabled for your custom label which will contain your button as a subview
customLabel.userInteractionEnabled = YES;
// Then create and add your button as a subview
UIButton *addButton = [[UIButton alloc] init];
[customButton setImage:[UIImage imageNamed:#"image"] forState:UIControlStateNormal];
[customButton addTarget:self action:#selector(customButtonClicked) forControlEvents:UIControlEventTouchUpInside];
[customLabel addSubview:addButton]; // Places view on top index

Transition to UINavigationBar with transparent background image results in black flickering

I want to navigate from a white UINavigatinonBarto a transparent UINavigationBar.
In my root view controller, this is the setup:
self.navigationController.navigationBar.hidden = NO;
[self.navigationController.navigationBar setBarTintColor:[UIColor whiteColor]];
[self.navigationController.navigationBar setTranslucent:NO];
It's important that it stays non translucent.
This is the setup in the second view controller:
// set title of navbar
self.title = [self.data objectForKey:#"title"];
[self.navigationController.navigationBar setTitleTextAttributes:#{NSForegroundColorAttributeName : [UIColor whiteColor]}];
//
// IMPORTANT PART: make the nav bar transaparent - no prerequisites.
self.navigationController.navigationBar.barStyle = UIBarStyleDefault;
[self.navigationController.navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
self.navigationController.navigationBar.shadowImage = [UIImage new];
self.navigationController.navigationBar.translucent = YES;
// set custom back button
UIButton *backButton = [[UIButton alloc] initWithFrame: CGRectMake(16, 31, 22, 20)];
UIImage *backImage = [UIImage imageNamed:#"backButtonDetail"];
[backButton setBackgroundImage:backImage forState:UIControlStateNormal];
[backButton setTitle:#"" forState:UIControlStateNormal];
[backButton addTarget:self action:#selector(popBack) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *backButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
self.navigationItem.leftBarButtonItem = backButtonItem;
This goes almost well, except for the animation:
As you can see, the background becomes black when I animate it. I want to fade the white into the destination color. It now animates from the black background.
I tried settings a custom UIView underneath the nav bar, but that didn't work.
I'm quite lost about how to about this now and any help would be highly appreciated.
I recently ran into this same problem and was able to get around it by just setting the window's background color in the appDelegate's didFinishLaunchingWithOptions
window.backgroundColor = UIColor.whiteColor()
and if you don't already have a reference to window then
UIApplication.sharedApplication().delegate?.window.backgroundColor = ...
I found this to be the cleanest solution. Hope it helps, albeit a bit late.

Reloading navigation bar

How can I reload/reassign navigation bar items? I use some libraries that change navigation bar and sometimes I have a bag in which all navigation items disappear. I have reassigned right items in viewWillAppear like:
UIButton *actionButton = [UIButton buttonWithType:UIButtonTypeCustom];
actionButton.frame = CGRectMake(270, 0, 50, 50);
actionButton.adjustsImageWhenHighlighted = YES;
[actionButton setImage:[UIImage imageNamed:#"share.png"] forState:UIControlStateNormal];
[actionButton setImage:[UIImage imageNamed:#"share-active.png"] forState:UIControlStateHighlighted];
[actionButton addTarget:self action:#selector(presentActivity) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *actionBarButton = [[UIBarButtonItem alloc]initWithCustomView:actionButton];
actionBarButton.tintColor = [UIColor whiteColor];
self.navigationItem.rightBarButtonItem = actionBarButton;
But it does not work and sometimes I do not have any navigation items.
UIBarButtonItem
is not child of UIButton.
here is not known methods like setImage:forState: etc.
create and custon an UITabBarButton like this
UIBarButtonItem *newBackButton = [[UIBarButtonItem alloc] initWithTitle:#"" style:UIBarButtonItemStyleBordered target:self action:#selector(goBack)];
newBackButton.image = [UIImage imageNamed:#"back"];
self.navigationItem.leftBarButtonItem=newBackButton;
also verify if method with this code will be called when viewDidLoad
Check out this like https://developer.apple.com/library/ios/documentation/uikit/reference/uinavigationbar_class/Reference/UINavigationBar.html the apple dev is awesome.
This is another good link
AppCoda has a lot of great tutorials this one has everything you need to know about Nav Bars
http://www.appcoda.com/customize-navigation-status-bar-ios-7/
and you could also use perform segue with identifier method and to send a string or something to a new view controller and then when you see that string is equal to what you want use an if statement in your viewWillAppear method.

how to show back button on navigation bar?

I was practicing an application with navigation bar. I used UIBarButton to go to the next screen from the main screen.
UIButton *moveLeft = [UIButton buttonWithType:UIButtonTypeCustom];
[moveLeft setTitle:#"Next Screen" forState:UIControlStateNormal];
moveLeft.titleLabel.font = [UIFont fontWithName:#"Helvetica-Bold" size:12.0f];
[moveLeft.layer setCornerRadius:4.0f];
[moveLeft.layer setBorderWidth:1.0f];
[moveLeft.layer setBorderColor: [[UIColor redColor] CGColor]];
moveLeft.frame=CGRectMake(200, 100.0, 90.0, 30.0);
[moveLeft setTitleColor:[UIColor greenColor] forState:UIControlStateNormal];
[moveLeft addTarget:self action:#selector(moveToNext) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem* barbutton= [[UIBarButtonItem alloc] initWithCustomView:moveLeft];
self.navigationItem.rightBarButtonItem = barbutton;
But now when the second screen appears there is no navigation bar.
Here are the screen shots of the app
i tried UIBarButton for back also but still navigation bar is not coming on the second screen.
UIBarButtonItem *back = [[UIBarButtonItem alloc] initWithTitle:#"Back"
style:UIBarButtonItemStylePlain
target:nil
action:nil];
[[self navigationItem] setBackBarButtonItem:back];
My question how do i show the back button the second screen?? i am not making any custom button but the default is also not coming automatically.
Please guide me.
From your comments, you are presenting the next view controller, instead of this
[self presentViewController:secondScreen animated:YES completion:nil];
Do like this
[self.navigationController pushViewController:secondScreen animated:YES]
Suggestion
Instead of adding subView to the window, you should set the rootViewController of the window which is the recommended way. So change
[self.window addSubview:[navControll view]];
To
self.window.rootViewController = navControll;
No one answered the question correctly, I met the same question, and I have solve it by myself. My solution is delete the navigation controller before the child view controller , than control drag between the tableview controller to the child view controller, select the "show"
You have to use UINavigationController. It will be root view controller for your app. Put mainVC into it and then just pushViewController second vc.
You can access navigation controller via navigationController method of any vc(mainVC in your case).
Simply u can add custom back button to navigationBar
UIButton *backButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, button_width, button_height)];
[backButton setImage:[UIImage imageNamed:#"back.png"] forState:UIControlStateNormal];
[backButton addTarget:self action:#selector(backAction) forControlEvents:UIControlEventTouchUpInside];
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];

How to Custom UINavigationController?

I have design goal like picture in this:
The problem is, UIButton valign cannot in center position, UIButton always relative to UINavigationController like this:
How to make UIButton valign in center of background image height not UINavigationController height?
self.btnBack = [UIButton buttonWithType:UIButtonTypeCustom];
[self.btnBack setImage:[UIImage imageNamed:#"back_active.png"] forState:UIControlStateNormal];
[self.btnBack addTarget:self action:#selector(back) forControlEvents:UIControlEventTouchUpInside];
self.btnBack.frame = CGRectMake(5, 9, 50, 30);
[self.navigationController.navigationBar addSubview:self.btnBack];
check this link also.
Update:for back button
-(void)back
{
[self.btnBack removeFromSuperview];
[self.navigationController popViewControllerAnimated animated:NO];
}
First create custom button and then add subview in navigation controller :-
UIButton * headerButton = [UIButton buttonWithType:UIButtonTypeCustom];
[headerButton addTarget:self action:#selector(headerButton1Action:) forControlEvents:UIControlEventTouchUpInside];
headerButton.frame = CGRectMake(95, 1, 30,38 );
[headerButton setImage:[UIImage imageNamed:#"header-icon"] forState:UIControlStateNormal];
[headerButton setImage:[UIImage imageNamed:#"header-icon-pressed"] forState:UIControlStateSelected];
[self.navigationController.navigationBar addSubview:headerButton];
I hope this will help you.
Happy coding...
This is a good quick solution
myButton.titleLabel.font = [UIFont fontWithName:#"FontName" size:20.0];
myButton.contentEdgeInsets = UIEdgeInsetsMake(3.0, 0.0, 0.0, 0.0);
and hide your navigation bar by
[self.navigationController setNavigationBarHidden:YES];
then show your custom view
There is trick,
You can Hide navigationController using [self.navigationController setNavigationBarHidden:YES];
and display custom view in top as you want.
the prob you are facing because of the navigation bar height. Now there are two approaches. Either you can create a category for navigation bar and override the -(CGRect)sizethatFits method like given below:
- (CGSize)sizeThatFits:(CGSize)size {
CGSize newSize = CGSizeMake(320,100);
return newSize;
}
Or you can hide the navigation bar like :
[self.navigationController setNavigationBarHidden:YES];
and put a header view and handle that.
Do what you would prefer to do..

Resources