When you create a UINavigationController
, you can reveal its default hidden UIToolbar
via setToolbarHidden:animated:
(or by checking Shows Toolbar in Interface Builder). This causes a toolbar to appear at the bottom of the screen, and this toolbar persists between pushing and popping of view controllers on the navigation stack. That is exactly what I need, except I need the toolbar to be located at the top of the screen. It appears that's exactly what Apple has done with the iTunes app:

How can one move UINavigationController
's toolbar to the top to lie underneath the navigation bar instead of at the bottom?
I've tried to implement the UIToolbarDelegate
, override positionForBar:
, and return UIBarPosition.TopAttached
or UIBarPosition.Top
after setting the delegate
of self.navigationController?.toolbar
to self
, but this did not even call the delegate method therefore it didn't change the bar position.
Note that I need the toolbar to be preserved between navigation, so I can't simply add a toolbar to a view controller and position it under the nav bar.
The solution for this problem is a two (and a half) step process:
First you have to add an observer to the toolbars 'center' member.
Second, inside your observeValueForKeyPath:ofObject:change:context:, relocate the toolbar to your target position every time it is moved by somebody (e.g. the navigation controller itself for example, when the device rotates).
I did this in my UINavigationController subclass. To avoid recursion, I've installed an local flag member 'inToolbarFrameChange'.
The last (half) step was a bit tricky to find out... you've to access the toolbars 'frame' member, to get the observer to be called at all... I guess, the reason for this might be, that 'frame' is implemented as an method inside UIToolbar and the base 'frame' value in UIView is only updated when the UIToolbar method is called ?!?
I did implement this 'frame' access in my overloaded setToolbarHidden:animated: method, which does nothing but to forward the call and to access the toolbars 'frame' value.
@interface MMMasterNavigationController ()
@property (assign, nonatomic) BOOL inToolbarFrameChange;
@end
@implementation MMMasterNavigationController
/*
awakeFromNib
*/
- (void)awakeFromNib {
[super awakeFromNib];
// ... other inits
self.inToolbarFrameChange = NO;
}
/*
viewDidLoad
*/
- (void)viewDidLoad {
[super viewDidLoad];
// 'center' instead of 'frame' from: http://stackoverflow.com/a/17977278/2778898
[self.toolbar addObserver:self
forKeyPath:@"center"
options:NSKeyValueObservingOptionNew
context:0];
}
/*
observeValueForKeyPath:ofObject:change:context:
*/
- (void)observeValueForKeyPath:(NSString *)pKeyPath
ofObject:(id)pObject
change:(NSDictionary<NSString *,id> *)pChange
context:(void *)pContext {
if ([pKeyPath isEqualToString:@"center"]) {
if (!self.inToolbarFrameChange) {
//NSLog(@"%s (0): %@", __PRETTY_FUNCTION__, pChange);
self.inToolbarFrameChange = YES;
CGRect tbFrame = self.toolbar.frame;
// maybe some other values are needed here for you
tbFrame = CGRectMake(0, 0, CGRectGetWidth(tbFrame), CGRectGetHeight(tbFrame));
self.toolbar.frame = tbFrame;
self.inToolbarFrameChange = NO;
}
} else {
[super observeValueForKeyPath:pKeyPath ofObject:pObject change:pChange context:pContext];
}
}
/*
setToolbarHidden:animated:
*/
- (void)setToolbarHidden:(BOOL)pHidden
animated:(BOOL)pAnimated {
FLog;
[super setToolbarHidden:pHidden animated:NO];
// Access the 'frame' member to let to observer fire
CGRect rectTB = self.toolbar.frame;
rectTB = CGRectZero;
}
You may create not UITableViewController but UIViewController. In view of UIViewController place UIToolBar below NavigationBar and UITableView. Delegate all necessary list of UITableView to UIViewController and thats all. Why should you use UIViewController instead UITableViewController? Because tableView will not have statical positions elements. You should have something that not contains ScrollView. In this situation it is only UIView. Also you may do some hack with UIScrollView of tableView but I think described method is easer.
来源:https://stackoverflow.com/questions/31492927/move-uinavigationcontrollers-toolbar-to-the-top-to-lie-underneath-navigation-ba