I'm trying to add a UISegmentedControl programmatically as the titleView in a UINavigationController. But it did not show up. Upon further investigation, I found out that the titleView property is ignored if the leftBarButtonItem is not set to nil according to the Apple docs. So I set it to nil but still the segmented control does not show up!
Below is my code.
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationItem.leftBarButtonItem = nil;
UISegmentedControl *statFilter = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:#"Personnal", #"Department", #"Company", nil]];
[statFilter setSegmentedControlStyle:UISegmentedControlStyleBar];
self.navigationItem.titleView = statFilter;
}
What should I do? What am I missing here?
Thanks.
EDIT :
Thanks for all the responses. However, none of them worked for me so I took a deeper look. It must be the way I have laid out my application. I probably should have mentioned that earlier. Apologies.
What I'm creating is a Storyboard app. The main controller is a UITabBarController. When a certain tab is clicked, I want to show a UITableViewController. Since you cannot display a Navigation bar in a UITableViewController, I found out that I must add a UINavigationController and implement a UITableViewController inside it. This is how my app basically look like,
That Dashboard View Controller is connected to a class inheriting from UINavigationController
class. Maybe this is where the issue resides?
Because I just created a small test app, put a UIViewController, embedded in a UINavigationController and wrote the code I have posted in my original question above inside the UIViewController's ViewDidLoad and the segmented control shows up just fine. Now I don't know how to do the same in my main app because there's no other view controllers or anything connected to the navigation controller.
Sorry if I made things even worse. Please comment if anything is unclear.
I guess you have to make the UISegmentedControll a UIBarButtonItem:
UPDATE:
This Code makes the SegmentedControll centered:
- (void)viewDidLoad{
self.title = nil;
UISegmentedControl *statFilter = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:#"Personnal", #"Department", #"Company", nil]];
[statFilter setSegmentedControlStyle:UISegmentedControlStyleBar];
NSMutableArray *buttonArray = [[NSMutableArray alloc] init];
UIBarButtonItem *flexibleSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
[buttonArray addObject:flexibleSpace];
[buttonArray addObject:[[UIBarButtonItem alloc] initWithCustomView:statFilter]];
[buttonArray addObject:flexibleSpace];
self.navigationItem.leftBarButtonItems = buttonArray;
[buttonArray release];
}
I hope this helps you out!
Use this i hope this will help you
- (void)viewDidLoad
{
[super viewDidLoad];
UIView * navview = [[UIView alloc] initWithFrame:CGRectMake(10, 10, 160,80)];
self.navigationItem.leftBarButtonItem = nil;
UISegmentedControl *statFilter = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:#"Personnal", #"Department", #"Company", nil]];
[navview addSubview:statFilter];
self.navigationItem.titleView = navview;
}
Related
I want to change the title of post buttons in SLComposeServiceViewController.
I managed to get the UIButton:
NSArray* subviews =[self.navigationController.navigationBar subviews];
UIButton* postButton =[subviews lastObject];
and i tried to set title like this:
[postButton setTitle:#"Save" forState:UIControlStateNormal];
but the title not changed.
Can anyone help me with this?
I saw Evernote's share extension on my iPad and it looks like this:
UPDATE
My Solution:
I found solution for my question,I removed the original navigation bar and create custom nav bar.
I have two nav bar:
1. with "cancel"\"save" buttons
2. with "back" button
and I change them when navigate to other viewcontroller
(in my case I needed to upload file and user need select location from list)
NOTE: if you not implement configurationItems you need only the first nav bar. (just call to set custom nav bar from viewDidAppear
So my code is here:
#property (strong, nonatomic) UINavigationBar *customNavBar;
-(void) viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
self.customNavBar = [[UINavigationBar alloc] initWithFrame:self.navigationController.navigationBar.bounds];
[self.navigationController.navigationBar removeFromSuperview];
[self.navigationController.view addSubview:self.customNavBar];
[self setCancelSaveNavigationItem];
}
setCancelSaveNavigationItem--> called from viewDidAppear of shareViewController
-(void)setCancelSaveNavigationItem
{
UINavigationItem *newItem = [[UINavigationItem alloc] init];
UIBarButtonItem *cancelBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(#"Cancel",nil) style:UIBarButtonItemStylePlain target:self action:#selector(cancelButtonTapped:)];
UIBarButtonItem *saveBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(#"Done",nil) style:UIBarButtonItemStyleDone target:self action:#selector(saveButtonTapped:)];
newItem.leftBarButtonItem = cancelBarButtonItem;
newItem.rightBarButtonItem = saveBarButtonItem;
[self.customNavBar setItems:#[newItem]];
[self.navigationItem setBackBarButtonItem:cancelBarButtonItem];
[self.navigationItem setRightBarButtonItem:saveBarButtonItem];
if(self.item.value == nil){
saveBarButtonItem.enabled = NO;
}
}
setBackNavigationItem--> called in configurationItems -->in self.item.tapHandler function
-(void)setBackNavigationItem
{
UINavigationItem *newItem = [[UINavigationItem alloc] init];
UIBarButtonItem *selectBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(#"Select",nil) style:UIBarButtonItemStylePlain target:self action:#selector(selectButtonTapped:)];
UIBarButtonItem *backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:[NSString stringWithFormat:#"❮ %#", NSLocalizedString(#"Back",nil)] style:UIBarButtonItemStylePlain target:self action:#selector(backButtonTapped:)];
newItem.leftBarButtonItem = backBarButtonItem;
newItem.rightBarButtonItem = selectBarButtonItem;
[self.customNavBar setItems:#[newItem]];
[self.navigationItem setBackBarButtonItem:backBarButtonItem];
[self.navigationItem setRightBarButtonItem:selectBarButtonItem];
}
Handle buttons tapped:
- (void)backButtonTapped:(id)sender {
if([self.navigationController.viewControllers count] ==2){
[self setCancelSaveNavigationItem];
}
[self.navigationController popViewControllerAnimated:YES];
}
- (void)cancelButtonTapped:(id)sender {
[self cancel];
}
- (void)selectButtonTapped:(id)sender {
...
[self setCancelSaveNavigationItem];
[self popConfigurationViewController];
}
- (void)saveButtonTapped:(id)sender {
...
[self cancel];
}
And it's work for me!!!
The result:
Simply in viewDidAppear
self.navigationController?.navigationBar.topItem?.rightBarButtonItem?.title = "Save"
Your code:
NSArray* subviews =[self.navigationController.navigationBar subviews];
UIButton* postButton =[subviews lastObject];
...is a really bad idea. It only works because the post button is in subviews and is the last item in the array. But the content of subviews is undocumented and might change at any time. Also, since there's no public API for this button, it's entirely possible that there's framework code to prevent or override changes to the button text-- so even if we assume you have the right UI element, you still might not be able to change it.
Evernote's UI is almost certainly a full custom design that only resembles SLComposeServiceViewController. Share extensions are not required to use SLComposeServiceViewController, that's just there for convenience. If it doesn't meet your needs, design your own.
Update: out of curiosity I unzipped the Evernote IPA and had a look at EvernoteShare.appex with nm. There's no reference to SLComposeServiceViewController, which confirms that Evernote is not using that class in their extension.
**Background** When my app loads a UINavigationController is programmatically added and given a leftBarButtonItem and a rightBarButtonItem. During launch a check is made to see if new data is required and if so a method is run to go and get new data from our web server. During this time, the rightBarButtonItem is changed to a UIActivityIndicatorView which will show a spinning activity indicator. When the data download is done, the rightBarButtonItem returns to a UIBarButtonItem. This works fine.
On another UIViewController I need to allow the user to manually get new data and send their data to us. During this time I need the rightBarButtonItem to change to a UIActivityIndicatorView as before. But when I try to do so, the data is downloaded ok but the rightBarButtonItem is never changed.
I think my problem may have something to do with me not being able to reference the UINavigationController and its navigationItems.
**Code** My first UIViewController's implementation where the rightBarButtonItem is changed:
-(void)statusIsLoading{
UIActivityIndicatorView *uiLoading = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
uiLoading.hidesWhenStopped = YES;
NSLog(#"Start animating");
[uiLoading startAnimating];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:uiLoading];
}
-(void)statusFinishedLoading{
UIActivityIndicatorView *uiLoading = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
uiLoading.hidesWhenStopped = YES;
[uiLoading stopAnimating];
UIBarButtonItem *showSettingsButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:#"Settings.png"] style:UIBarButtonItemStylePlain target:self action:#selector(showSettings:)];
self.navigationItem.rightBarButtonItem = showSettingsButton;
}
**What I have tried** I have tried setting the self.navigationItem.rightBarButtonItem in the second UIViewController but this does nothing. I have also tried running the method that calls the above two methods from an instantiated class:
InitViewController *ivcInstance = [[InitViewController alloc] init];
[ivcInstance performUpdate];
This runs the 'performUpdate' code just fine, the 'performUpdate' method called the 'statusIsLoading' and 'statusFinishedLoading' methods but the rightBarButtonItem does not change.
I think there is something very simple I am missing here. Thanks.
**Edit** I have just tried checking for the current value of the rightBarButtonItem on the pageLoad of the second UIViewController and it appears to be nil:
UIBarButtonItem *newItem = self.navigationItem.rightBarButtonItem;
Here newItem = nil. Am I not targeting the correct navigationItem? should it be something other than 'self'?
**Edit 2**
In the second UIViewController I can alter the properties of the navigationBar:
[self.navigationController.navigationBar setBarTintColor:[UIColor colorWithRed:0.6 green:0.01 blue:0.36 alpha:2.0f]];
But if I try the same with the barButtonItem then nothing happens, why is this?
[self.navigationController.navigationItem setRightBarButtonItem:[[UIBarButtonItem alloc] initWithCustomView:uiLoading]];
same with:
[self.navigationItem setRightBarButtonItem:[[UIBarButtonItem alloc] initWithCustomView:uiLoading]];
In your statusFinishedLoading you have some unused codes like below
-(void)statusFinishedLoading
{
/*UIActivityIndicatorView *uiLoading = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
uiLoading.hidesWhenStopped = YES;
[uiLoading stopAnimating];*/ //These are unused codes.
UIBarButtonItem *showSettingsButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:#"Settings.png"] style:UIBarButtonItemStylePlain target:self action:#selector(showSettings:)];
self.navigationItem.rightBarButtonItem = showSettingsButton;
}
Also put NSLog in statusFinishedLoading methods and check whether this method called or not.
Thanks!
Try to set the rightBarButtonItem within a main-thread block. Once you have received the response, it should not block the UI.
-(void)statusFinishedLoading
{
UIActivityIndicatorView *uiLoading = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
uiLoading.hidesWhenStopped = YES;
[uiLoading stopAnimating];
UIBarButtonItem *showSettingsButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:#"Settings.png"] style:UIBarButtonItemStylePlain target:self action:#selector(showSettings:)];
//Use a block to set the rightBarButton.
dispatch_async(dispatch_get_main_queue(), ^{
self.navigationItem.rightBarButtonItem = showSettingsButton;
});
}
Hope this does the trick.
Edit : You need to create a UINavgationitem in the storyboard, connect the outlet to the .h file and call it statusNavigationItem then reference this navigationItem object to set the rightBarButton.
I have made a barbuttonitem programmatically on a toolbar overlay. All of this appears when my camera is accessed. The button functions fine and the selector is fully capable of calling it.
Here's the overlay in .m , take a look at the doneButton selector.
- (UIView*)CommomOverlay {
//Both of the 428 values stretch the overlay bottom to top for overlay function. It
doesn't cover it.
UIView* view = [[UIView alloc] initWithFrame:CGRectMake(0,0,320,420)];
UIImageView *FrameImg = [[UIImageView alloc] initWithFrame:CGRectMake(0,0,320,420)];
[FrameImg setImage:[UIImage imageNamed:#"newGraphicOverlay.png"]];
FrameImg.userInteractionEnabled = YES;
UIToolbar *myToolBar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 428, 320, 50)];
UIBarButtonItem *doneButton = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self
action:#selector(doneButtonPressed)];
[myToolBar setItems:[NSArray arrayWithObjects: cancelButton, flexiSpace2, flexiSpace,
doneButton, nil] animated:YES];
[view addSubview:FrameImg];
[view addSubview:myToolBar];
return view;
}
Here's method I'm using for my void function.
//NewViewController is the nib I want to bring up when done is clicked.
-(void)doneButtonPressed {
NewViewController *UIView = [[NewViewController alloc] initWithNibName:nil bundle:nil];
UIView.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentModalViewController:UIView animated:NO];
[UIView release];
NSLog(#"Acknowledged!");
}
The button is being called, but nothing happens. As you can see I added an NSLog function to see whether it was being called or not. "Acknowledged" shows up in the log when the button is clicked, so it's not a problem with the selector. The app doesn't crash when i use the button either, which should occur had I done some heavily faulty coding (in fact I don't even get any warnings about it), as far as Xcode is considered, everything is fine which, needless to say isn't.
I also have my .h files of NewViewController in place correctly in the view controller in which this code is being implemented.
UIView is the name of a class. Don't use it as the name of a variable. At best it is hugely confusing and is a probable reason for your problems. Rename UIView to something like myView everywhere in doneButtonPressed.
- (void)viewDidLoad
{
[super viewDidLoad];
ac = [[AddContacts alloc]init];
self.navigationController = [[UINavigationController alloc] initWithRootViewController:ac];
[self.view addSubview:navigationController.view];
UIBarButtonItem *anotherButton = [[UIBarButtonItem alloc] initWithTitle:#"Show" style:UIBarButtonItemStylePlain target:self action:#selector(refreshPropertyList:)];
self.navigationController.navigationItem.rightBarButtonItem = anotherButton;
}
Why is my button not being added on the navigation controller?
The UIBarButtonItems are not controlled by the navigation controller, but by each of the view controllers it contains - each UIViewController can have different buttons. Try:
ac = [[AddContacts alloc]init];
UIBarButtonItem *anotherButton = [[UIBarButtonItem alloc] initWithTitle:#"Show" style:UIBarButtonItemStylePlain target:self action:#selector(refreshPropertyList:)];
ac.navigationItem.rightBarButtonItem = anotherButton;
Then initialize the UINavigationController as you have been doing.
There are a few things here that could be causing issues.
Probably what the main issue is this line:
self.navigationController.navigationItem.rightBarButtonItem = anotherButton;
I am pretty sure that what you want to be setting is the right bar button item on the ac view controller's navigation item.
ac.navigationItem.rightBarButtonItem = anotherButton
A few other things though:
Don't have two letter variable names. "ac" is very ambiguous, "addContacts" would provide more information, "addContactsViewController" would provide even more
Are you implementing your own navigationController property in a UIViewController subclass? This is not recommended as it is overriding the navigationController property that UIViewController already has. Give it a different name.
Is the -viewDidLoad method on the parent view controller the place to be assigning the right bar button of your AddContacts object? Consider instead putting the code to set the bar button in the implementation of AddContacts instead.
On an iPad application, I want to be able to have multiple buttons in the top bar of a popover. I'm launching it like this:
UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:vc];
pop = [[UIPopoverController alloc] initWithContentViewController:nc];
[pop presentPopoverFromRect:CGRectInset([tableView rectForRowAtIndexPath:indexPath], 10, 10)
inView:tableView
permittedArrowDirections:UIPopoverArrowDirectionAny
animated:YES];
pop.delegate = self;
[nc release];
In the viewDidLoad I want to set the titleView to contain multiple UIBarButtonItems. This is ok on a normal UINavigationController but I need to be able to do this and keep the custom style of the navigation bar on the popover.
I have tried setting the rightBarButtonItem to have a toolbar that contains buttons, but they take the format of the toolbar, which itself will not take the format/style of the popover.
It's a bit hackish, but you can create a truly transparent UIToolbar by subclassing and overriding drawRect: with an empty method. This will still draw the UIBarButtonItems on the toolbar, but not the toolbar itself.
Then, as Nils describes, you can create a bar button item out of the custom toolbar instance and add it as the rightBarButtonItem.
Why you don't use a custom UIView with a UIToolbar or UINavigationBar instead of UIPopoverController?
The effect, is the same!
First you need to set a delegate to the UINavigationController and then implement the nabigationController:willShowViewController:animated: method. In this method you can adjust the left and right bar button items.
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated{
viewController.navigationItem.leftBarButtonItem = [[[UIBarButtonItem alloc]
initWithTitle:#"Image Source"
style:UIBarButtonItemStylePlain
target:self
action:#selector(cancelPressed)] autorelease];
}
I had the same problem, and here is what I did :
UIBarButtonItem *uiBarRefresh = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self action:#selector(forcerefresh)];
UIBarButtonItem *uiBarCurl = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemPageCurl target:self action:#selector(showlist)];
UIToolbar_transparent* tools = [[UIToolbar_transparent alloc] initWithFrame:CGRectMake(0, 0, 133, 44.01)];
tools.barStyle = UIBarStyleBlackTranslucent;
tools.translucent = YES;
tools.backgroundColor = [UIColor clearColor];
tools.tintColor = self.navigationController.navigationBar.tintColor;
[tools setItems:[NSArray arrayWithObjects:flexItem,uiBarRefresh,uiBarCurl,nil] animated:NO];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:tools];
This way you avoid the dull grey background, the pesky white underline, and you can completely customize how you want them positioned, by using fixed or flex spacings.
Best of luck with your project :]