Move UINavigationController's toolbar to the top to lie underneath navigation bar

北战南征 提交于 2019-11-30 20:49:35

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!