I'm trying to show a UIPopoverPresentationController which has a UIButton in it's navigation bar. This used to work, but the UIButton is not showing anymore, since iOS 11 (iPad). Interestingly, in my popup, I can also push another UIViewController, and when I come back from it, the UIButton appears.
Here's the code to show the popup:
- (IBAction)buttonPressed:(id)sender {
PopupViewController *popupController = [self.storyboard instantiateViewControllerWithIdentifier:#"PopupController"];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:popupController];
navController.modalPresentationStyle = UIModalPresentationPopover;
[self presentViewController:navController animated:YES completion:nil];
UIPopoverPresentationController *popController = [popupController popoverPresentationController];
CGRect rect = self.button.frame;
CGSize size = CGSizeMake(500, 400);
popController.sourceView = self.view;
popController.sourceRect = rect;
popupController.preferredContentSize = size;
}
and here is the code in the popup, to show the UIButton:
- (void)viewWillAppear:(BOOL)animated
{
UIButton *rightButton = [[UIButton alloc]init];
[rightButton setTitle: #"Press me" forState:UIControlStateNormal];
[rightButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
rightButton.frame = CGRectMake(0, 0, 120, 24);
UIBarButtonItem *rightButtonItem = [[UIBarButtonItem alloc] initWithCustomView:rightButton];
UIBarButtonItem *flexible = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil];
self.navigationItem.rightBarButtonItems = [NSArray arrayWithObjects:flexible, rightButtonItem, nil];
self.navigationController.preferredContentSize = self.preferredContentSize;
}
Does anybody know what's going on? Why is the button now showing right away?
I would move your code out of viewWillAppear and into viewDidLoad. Its being in viewWillAppear is the reason you can see the button when you open another controller and then go back to this one, but you don't really want the button to be recreated every time you go back to this view. I think there's a good chance this will fix the problem of it not showing at first, too.
Related
I am trying to display a custom UIButton as a UINavigationItem's rightBarButtonItem.
I wrote the following code:
UIButton *inviteButton = [UIButton buttonWithType:UIButtonTypeCustom];
[inviteButton setTitle:#"Invite" forState:UIControlStateNormal];
inviteButton.frame = CGRectMake(0, 0, 30, 30);
inviteButton.backgroundColor = [UIColor redColor];
inviteButton.layer.borderColor = [UIColor blueColor].CGColor;
inviteButton.layer.borderWidth = 1.0f;
UIBarButtonItem *inviteButtonContainer = [[UIBarButtonItem alloc] initWithCustomView:inviteButton];
viewController.navigationItem.rightBarButtonItem = inviteButtonContainer;
Nothing shows up in my navigation bar.
However, with the following code, I can see a basic button:
UIBarButtonItem *inviteButton = [[UIBarButtonItem alloc] initWithTitle:#"Invite"
style:UIBarButtonItemStyleDone
target:self
action:nil];
viewController.navigationItem.rightBarButtonItem = inviteButton;
But it's obviously not what I am after, since I am looking to play with the button appearance.
Edit
I was trying to add the same instance of UIBarButtonItem (inviteButtonContainer) to many navigation bars. Doing that, it's visible on the last navigation bar only.
However, if I use the same instance of a simple UIBarButtonItem (without custom view), it's displayed on every navigation bars. Any idea why?
Your code is fine, just change this line:
viewController.navigationItem.rightBarButtonItem = inviteButtonContainer;
to
self.navigationItem.rightBarButtonItem = inviteButtonContainer;
From the Documentation:
The navigation item used to represent the view controller in a
parent's navigation bar.
self itself represents that it belongs to view controller , so there is no need to mention the view controller instance to add the navigation item.
-> To display custom button in a view controller in which custom bar button is crated (i.e. in self) :
- (void)viewDidLoad {
[super viewDidLoad];
UIButton *inviteButton = [UIButton buttonWithType:UIButtonTypeCustom];
[inviteButton setTitle:#"Invite" forState:UIControlStateNormal];
inviteButton.frame = CGRectMake(0, 0, 70, 30);
inviteButton.backgroundColor = [UIColor redColor];
inviteButton.layer.borderColor = [UIColor blueColor].CGColor;
inviteButton.layer.borderWidth = 1.0f;
UIBarButtonItem *inviteButtonContainer = [[UIBarButtonItem alloc] initWithCustomView:inviteButton];
controller.navigationItem.rightBarButtonItem = inviteButtonContainer;
}
-> To display custom bar button in a view controller that is about to present
eg. To display a view controller after a cell is selected in table view
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
DjDetailsViewController *controller = (DjDetailsViewController *)
[self.storyboard instantiateViewControllerWithIdentifier:#"DjDetailsViewController"];
UIButton *inviteButton = [UIButton buttonWithType:UIButtonTypeCustom];
[inviteButton setTitle:#"Invite" forState:UIControlStateNormal];
inviteButton.frame = CGRectMake(0, 0, 70, 30);
inviteButton.backgroundColor = [UIColor redColor];
inviteButton.layer.borderColor = [UIColor blueColor].CGColor;
inviteButton.layer.borderWidth = 1.0f;
UIBarButtonItem *inviteButtonContainer = [[UIBarButtonItem alloc] initWithCustomView:inviteButton];
controller.navigationItem.rightBarButtonItem = inviteButtonContainer;
[self.navigationController pushViewController:controller animated:YES];
}
I didn’t done major. I just used your code and change frame of custom bar button.
I hope this will help you.
You issue is with your invite button initialiser:
UIButton *inviteButton = [UIButton UIButtonTypeCustom];
UIButtonTypeCustom is an enum value not a class method/convenience constructor.
use
UIButton *inviteButton = [UIButton buttonWithType:UIButtonTypeCustom];
Hope this helps
I know viewcontroller's navigation item's backBarButtonItem gets displayed when another view controller is pushed on stack and this is 2nd viewcontroller from top.
I have viewcontroller A which have following in viewDidLoad
{
[super viewDidLoad];
self.navigationController.navigationBarHidden = NO;
[self.navigationItem setBackBarButtonItem:[UIBarButtonItem itemWithImageNamed:#"ic_header_slide" selectedImage:nil target:nil action:nil]];
}
When I push viewcontroller B, this custom back button is not getting displayed, instead I see default back button which iOS creates.
A extends UITableViewController and B extends UIViewController. I am not setting leftBarButtonItem, leftBarButtonItems, rightBarButtonItem, rightBarButtonItems in any of these navigationItem.
EDIT
I have read about setting leftBarButtonItems. setting leftbarbuttonitems on B works. but I think setting backBarButtonItem on A is correct way of doing that. It is also mentioned in documentation but not working in my case. I want to ask whether there is bug in backBarButtonItem or I have some misunderstanding the way it works and I am not doing it correctly.
To hide the default back button of the navigation bar use,
self.navigationItem.hidesBackButton=TRUE;
Also use the following method to add the custom BarButtons,
- (NSArray*)getLeftNavButtons:(NSString*)image andTarget:(id)target andFrame:(CGRect)frame andSpace:(int)fixedSpace
{
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = frame;
button.clipsToBounds = YES;
[button setBackgroundImage:[UIImage imageNamed:image] forState:UIControlStateNormal];
[button addTarget:target action:#selector(leftNavBtnClicked) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *barButton = [[UIBarButtonItem alloc]initWithCustomView:button];
if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"7"))
{
UIBarButtonItem *negativeSpacer = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace
target:nil action:nil];
negativeSpacer.width = fixedSpace;
return #[negativeSpacer,barButton];
}
else{
return #[barButton];
}
return #[barButton];
}
Just override the default
self.navigationItem.hidesBackButton = YES;
UIBarButtonItem *back = [[UIBarButtonItem alloc]init];
back.title = #"Pick Me";
back.image = #"Your image";
[self.navigationItem setLeftBarButtonItem:back];
Set Right Bar Button Item
self.navigationItem.leftBarButtonItem=[[UIBarButtonItem alloc]init];
UIImage *img1=[UIImage imageNamed:#"edit"];
CGRect frameimg1 = CGRectMake(0, 0, img1.size.width, img1.size.height);
UIButton *signOut=[[UIButton alloc]initWithFrame:frameimg1];
[signOut setBackgroundImage:img1 forState:UIControlStateNormal];
[signOut addTarget:self action:#selector(btnEditClicked:)
forControlEvents:UIControlEventTouchUpInside];
// [signOut setShowsTouchWhenHighlighted:YES];
UIBarButtonItem *barButton=[[UIBarButtonItem alloc]initWithCustomView:signOut];
self.navigationItem.rightBarButtonItem=barButton;
Set Left Bar Button Item
UIImage *img11=[UIImage imageNamed:#"home"];
CGRect frameimg11 = CGRectMake(0, 0, img11.size.width, img11.size.height);
UIButton *signOut1=[[UIButton alloc]initWithFrame:frameimg11];
[signOut1 setBackgroundImage:img11 forState:UIControlStateNormal];
[signOut1 addTarget:self action:#selector(showLeftMenuPressed:)
forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *barButton1=[[UIBarButtonItem alloc]initWithCustomView:signOut1];
self.navigationItem.leftBarButtonItem=barButton1;
self.navigationController.navigationBar.barTintColor=ColorNav;
self.navigationController.navigationBar.translucent=FALSE;
Set Navigation Title & Color
self.title = titletext;
[[[self navigationController] navigationBar]setTitleTextAttributes:#{NSForegroundColorAttributeName: textColor}];
I have a view controller connected to a navigation controller. I want to add a right button to the navigation bar on the top that will push another view controller. If I add the right button with:
UIBarButtonItem *Button = [[UIBarButtonItem alloc] initWithTitle:#"Map" style:UIBarButtonItemStylePlain target:self action:[self forward]];
self.navigationItem.rightBarButtonItem = Button;
the button appears. However, if I add the following lines to the forward method, the button disappears again:
MapViewController *viewController = [self.navigationController.storyboard instantiateViewControllerWithIdentifier:#"map"];
[self.navigationController pushViewController:viewController animated:YES];
What is the correct way of doing this?
there is a problem with the line action:[self forward]] while declaring UIBarButtonItem in your code...change it to #selector(forward) or try this
UIBarButtonItem *nextButton = [[UIBarButtonItem alloc] initWithTitle:#"Next" style:UIBarButtonItemStylePlain target:self action:#selector(showNextVC)];
self.navigationItem.rightBarButtonItem = nextButton;
and in showNextVC:
-(void) showNextVC {
MapViewController *viewController = [self.storyboard instantiateViewControllerWithIdentifier:#"map"];
[self.navigationController pushViewController:viewController animated:YES];
}
Try this code
UIImage *rightBtnImage = [UIImage imageNamed:#"bulb-plus.png"];
UIButton *rightButton = [UIButton buttonWithType:UIButtonTypeCustom];
[rightButton setImage:rightBtnImage forState:UIControlStateNormal];
rightButton.frame = CGRectMake(0, 0, 26, 35);
[rightButton addTarget:self
action:#selector(rightBarButtonAction)
forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:rightButton];
self.navigationItem.rightBarButtonItem = rightBarButtonItem;
IBAction method for rightBarbutton
- (void)rightBarButtonAction {
[self performSegueWithIdentifier:#"IdeaDetailSegue" sender:self];
}
Hope this helps.
Beginning in iOS 7, the rightBarButtonItem in my UINavigationBar gets shifted down after dismissing a modal view controller. The top screen shot shows the correct alignment. The bottom screenshot shows the wrong alignment after dismissing the modal view controller.
- (void) viewDidLoad
{
[super viewDidLoad];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc]
initWithTitle:#""
style:UIBarButtonItemStyleDone
target:self
action:#selector(didPressRightBarButtonItem)
];
[self.navigationItem.rightBarButtonItem
setImage:[UIImage imageNamed:#"shareLightFlat"]
];
}
- (void) didPressRightBarButtonItem
{
[self.navigationController
presentViewController:[[SomePage alloc] init]
animated:YES
completion:nil];
}
In SomePage, I use this to dismiss itself:
[self dismissViewControllerAnimated:YES completion:nil];
you don't need to use initWithTitle: # ""
try this:
UIBarButtonItem *editBarButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:#"myImage"] style:UIBarButtonItemStyleDone target:self action:#selector(myAction:)];
self.navigationItem.rightBarButtonItems = #[editBarButton];
I have no idea why this is happening, but when I tested this, it worked ok if I changed the title of the button from #"" to #" ". See if that works for you (I got somewhat different results from you -- my button was always misplaced, not only after the presentation and dismissal).
You are allocating a UIBarButtonItemStyleDone style button then setting the image. I think it would work better to go with:
UIButton * aButton = [UIButton buttonWithType:UIButtonTypeCustom];
... // Set frame and addTarget
[aButton setImage:[UIImage imageNamed:#"shareLightFlat"] forState:UIControlStateNormal];
UIBarButtonItem * editBarButton = [[UIBarButtonItem alloc] initWithCustomView:aButton];
I have not seen any related issues with iOS7.
I am trying to make a view reveal inside a popover. Something I have done numerous times. However, for some reason this time, the popover is appearing but missing some (but not all) of it subviews.
More specifically, this view contains a label, a text field, a button, and also has a navigation bar at the top. When revealed, it displays a label, but not the text field, or button. Ive tried with and without a XIB and results are the same.
Here is the declaration of the popover.. (triggers on button click)
if (popover)
{
[popover dismissPopoverAnimated:NO];
popover = nil;
}
// create the settings view controller and display it in a popover
LoginViewController *loginViewController = [[LoginViewController alloc] init];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:loginViewController];
// Initialize the popover, set the parent view as the delegate and allocate the popover's origin on the screen
popover = [[UIPopoverController alloc] initWithContentViewController:nav];
popover.delegate = self;
[popover presentPopoverFromRect:button.frame inView:button.superview permittedArrowDirections:UIPopoverArrowDirectionDown animated:YES];
and in the view did load of the loginViewController I have
self.navigationItem.title = NSLocalizedString(#"POPOVER_TITLE_INFORMATION", nil);
// setup navigation buttons
UIBarButtonItem *cancelButton = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(#"BUTTON_TITLE_CANCEL", nil) style:UIBarButtonItemStyleBordered target:self action:#selector(cancel)];
UIBarButtonItem *searchButton = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(#"BUTTON_TITLE_SEARCH", nil) style:UIBarButtonItemStyleDone target:self action:#selector(search)];
self.navigationItem.rightBarButtonItem = searchButton;
self.navigationItem.leftBarButtonItem = cancelButton;
[_loginTextLabel setText:NSLocalizedString(#"DESCRIPTION_TEXT", nil)];
[_loginTextLabel setNumberOfLines:0];
_loginTextLabel.frame = CGRectMake(20, 30, 728, 40);
[self.view addSubview:_loginTextLabel];
_loginTextField.frame = CGRectMake(20, 80, 264, 30);
[self.view addSubview:_loginTextField];
[_loginSubmitButton setTitle:NSLocalizedString(#"BUTTON_TITLE_SUBMIT", nil) forState:UIControlStateNormal];
[_loginSubmitButton addTarget:self action:#selector(submitBtnClk:) forControlEvents:UIControlEventTouchUpInside];
[_loginSubmitButton setFrame:CGRectMake(20, 130, 208, 44)];
[self.view addSubview:_loginSubmitButton];
Nothing overly complex, however the label is the only thing that actually displays to the screen.
I found the solution.
It would seem that Popovers AutoResize their components, and the widths of the button and the textfield were not large enough. Essentially, the popover screen is smaller than a normal view covering the full window, so it was shrinking the widths of the textField and button all the way to 0 when i guess the popover was adjusting the view.
So basically, I had to jack up the widths of those subviews to compensate.