Reputation: 16702
I would like to dynamically hide a button in one of my views depending on a certain condition.
I tried adding some code to the view controller's -viewWillAppear
method, to make the button hidden before displaying the actual view, but I still don't know how to do that.
I have a reference to the button through an IBOutlet, but I'm not sure how to move forward from here. For reference, this is a UIBarButtonItem instance.
Upvotes: 36
Views: 47624
Reputation: 594
This answer is regarding text-based UIBarButtonItems, however, the same concept could be applied to other types of buttons as well. Note that this will allow one to both hide and show the item again. Many of the answers above (those setting the button's value to nil, for example, do not allow the button to be re-shown if that's desired).
TL;DR:
if (shouldShowMyBarButtonItem) {
self.myBarButtonItem.title = nil;
self.myBarButtonItem.action = nil;
} else if (!shouldShowMyBarButtonItem) {
self.myBarButtonItem.title = @"Title";
self.myBarButtonItem.action = @selector(mySelector:);
}
The long version:
The UIBarButtonItem I was trying to hide is in a UIToolbar, not a UINavigationBar so all the suggestions that access the left (or right) barButtonItem properties on the navigation item don't work for me. Also, as stated above, I wished to re-show the button when circumstances change.
Michael's suggestion came closest to working, however, with iOS 7 at least, there was still a very small sliver of the button displayed that was tappable. In my app, tapping the item when it's not supposed to be available was unacceptable. The above code both hides and, crucially, deactivates the button.
I call the above code in a private refresh method, which is called when a user event occurs.
Upvotes: 2
Reputation: 1086
Another hacky solution:
myButton.customView = [[UIView alloc] init];
Upvotes: 5
Reputation: 19
If you add a UIButton
to the UIBarButtonItem
rather than just use the UIBarButtonItem
.
You can then assign UIButton.hidden
to TRUE
or YES
and it (and the UIBarButtonItem
) will not be visible or active.
Hope that helps.
Upvotes: 1
Reputation: 519
This is a bit of a hack, but it works in my case (and it properly handles dynamic spacing):
To hide:
myButton.width = 0.1;
To show:
myButton.width = 0.0;
A width of 0.0 is "auto width", and with a width of 0.1, the button totally disappears (not even a "sliver" of a button, though I haven't tried this on a retina display).
Upvotes: 7
Reputation: 7918
Ben's answer is technically correct, though when I try it on my custom UIToolbar, the items space out in a way that I don't like, because I use UIBarButtonSystemItemFlexibleSpace items.
If you want your other items to stay in the same place, you'll either have to set your flexible spaces to fixed spaces, or try what I did:
[filterBarButton.customView setHidden:YES];
note: this only works if your UIBarButtonItem uses custom views.
Upvotes: 1
Reputation: 3501
The best solution to this is less technical. All you need to do is create your normal navigation bar (top) or toolbar (bottom), but without the optional button. Then create another identical, but shorter bar which you then place at the part you want the optional button and create your optional button on this second shorter bar.
Now you can call hidden = YES
on the whole additional bar.
The bars seamlessly overlap for me, your mileage may vary.
Upvotes: 2
Reputation: 480
If all that one is trying to hide is the back button in the navigation bar, there is an easier way:
self.navigationItem.hidesBackButton = YES;
Quote from developer documentation:
hidesBackButton
A Boolean value that determines whether the back button is hidden.
@property(nonatomic, assign) BOOL hidesBackButton
Discussion
YES if the back button is hidden when this navigation item is the top item; otherwise, NO. The default value is NO.
Availability
Available in iPhone OS 2.0 and later.
Upvotes: 10
Reputation: 1
So I tried Ben's winning approach but in the end I found it to be wrong for my purposes - though I'm sure it depends upon what you're trying to do. I was trying to show a nav bar button under certain conditions only and then hide it as soon as the condition was no longer met (in my case it's a "Done" button used to hide the keyboard associated with a UITextView. It should only be displayed when the user is typing in the text view). My steps were as follows:
I added a UIBarButtonItem as a property in my UIViewController class. I instantiate it in the initWithNibName method.
I assigned the UIBarButtonItem property as the rightBarButtonItem in the nav bar as soon as the user starts typing in the text view.
I set the UIBarButtonItem property to nil when the user is done typing.
It's working like a charm. I'm adding some code samples below.
First to instantiate the button in my view controller init method:
barButtonItemDone = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(done:)];
Then I set it as the right bar button in the delegate method that is called as soon as the user starts to edit the text view:
self.navigationItem.rightBarButtonItem=[self barButtonItemDone];
Finally, when the button itself is clicked, a method called "done" is called and I just set the rightBarButtonItem to nil inside that method:
self.navigationItem.rightBarButtonItem=nil;
Upvotes: 11
Reputation: 10745
This is what I did for button items that weren't part of the navigation bar (where Blank.png is a blank image I created that's the same size of the image it replaces):
theButton.enabled = NO;
theButton.image = [UIImage imageNamed: @"Blank.png"];
Upvotes: 1
Reputation:
Set the bar item to nil.
For example:
self.navigationItem.leftBarButtonItem = nil;
Upvotes: 20
Reputation: 85522
If you're trying to hide a UIBarButtonItem, you'll actually have to modify the contents of the parent bar. If it's a UIToolBar, you'll need to set the bar's items array to an array that doesn't include your item.
NSMutableArray *items = [[myToolbar.items mutableCopy] autorelease];
[items removeObject: myButton];
myToolbar.items = items;
Upvotes: 53
Reputation: 85522
Just set the button's hidden property to true:
myButton.hidden = YES;
Upvotes: -13