Iphone 使用平滑动画显示/隐藏导航栏

Iphone 使用平滑动画显示/隐藏导航栏,iphone,objective-c,cocoa-touch,uinavigationcontroller,Iphone,Objective C,Cocoa Touch,Uinavigationcontroller,我有一个基于导航的应用程序。第一个视图(rootcontroller)仅以三个大按钮开始。没有导航栏。从那里开始,其他一切都是表视图,并有导航栏。我这样做是为了显示/隐藏导航栏: MyAppAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate]; appDelegate.navigationController.navigationBar.hidden = NO; 一旦我离开根控制器,导航栏将猛然进入位置并

我有一个基于导航的应用程序。第一个视图(rootcontroller)仅以三个大按钮开始。没有导航栏。从那里开始,其他一切都是表视图,并有导航栏。我这样做是为了显示/隐藏导航栏:

MyAppAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
appDelegate.navigationController.navigationBar.hidden = NO;

一旦我离开根控制器,导航栏将猛然进入位置并放在tableview的顶部,而不是将其向下推。它将剪辑tableview的顶部。在导航栏消失的过程中,返回到根控制器并不顺利。是否有更平滑/更好的方法来完成仅隐藏根控制器的导航栏?

您可以使用
[navigationController设置NavigationBarHidden:YES动画:YES]
平滑隐藏导航栏


这段漂亮的代码为导航栏隐藏设置了动画,没有UI问题:

[navigationController设置NavigationBarHidden:是动画:是]
但是…
  • 使用self.navigationController.navigationBarHidden属性检查代码,而不是使用self.navigationController.navigationBar.hidden属性。这将为您节省大量因意外的UI定位问题而带来的痛苦
  • 请注意将此方法放置在-(void)视图中,将在视图生命周期中显示:(BOOL)动画或更高版本。这是推荐的,因为如果您在-(void)viewdiload中执行此操作,您将在动画期间从显示其导航栏的视图到不显示其导航栏的视图得到一个丑陋的黑色矩形视图! 例如,如果主视图的导航栏处于隐藏状态,但其所有子视图都显示了导航栏,则当您弹出到主视图时,动画将显示一个黑色栏来代替导航栏,直到动画完成

  • 可以通过以下方法自定义导航栏动画和持续时间。一旦动画完成,它将为您提供回调

       // pass a param to describe the state change, an animated flag and a completion block matching UIView animations completion
        - (void)setNavigationBarVisible:(BOOL)visible animated:(BOOL)animated completion:(void (^)(BOOL))completion {
    
            // fail if the current state matches the desired state
            if ([self navigationBarIsVisible] == visible) return completion(YES);
    
            // get a frame calculation ready
            CGFloat nheight = self.navigationController.navigationBar.frame.size.height;
            CGFloat noffsetY = (visible)? -nheight : nheight;
    
            // zero duration means no animation
            CGFloat duration = (animated)? 0.3 : 0.0;
    
            [UIView animateWithDuration:duration animations:^{
                CGRect nframe = self.navigationController.navigationBar.frame;
                self.navigationController.navigationBar.frame = CGRectOffset(nframe, 0, noffsetY);
            } completion:completion];
        }
    
        // know the current state of the navigation bar
        - (BOOL)navigationBarIsVisible {
            return self.navigationController.navigationBar.frame.origin.y < CGRectGetMinY(self.view.frame);
        }
    
        // Show or Hide navigation bar
        [self setNavigationBarVisible:![self navigationBarIsVisible] animated:YES completion:^(BOOL finished) {
            NSLog(@"navigation bar finished");
        }];
    
    //传递一个参数来描述状态更改、动画标志和与UIView动画完成匹配的完成块
    -(void)setNavigationBarVisible:(BOOL)可视动画:(BOOL)动画完成:(void(^)(BOOL))完成{
    //如果当前状态与所需状态匹配,则失败
    如果([self-navigationBarIsVisible]==可见)返回完成(是);
    //准备好框架计算
    CGFloat nheight=self.navigationController.navigationBar.frame.size.height;
    CGFloat noffsetY=(可见)?-n右侧:右侧;
    //零持续时间意味着没有动画
    CGFloat持续时间=(动画)?0.3:0.0;
    [UIView animateWithDuration:持续时间动画:^{
    CGRect nframe=self.navigationController.navigationBar.frame;
    self.navigationController.navigationBar.frame=CGRectOffset(nframe,0,noffsetY);
    }完成:完成];
    }
    //了解导航栏的当前状态
    -(BOOL)导航栏可视{
    返回self.navigationController.navigationBar.frame.origin.y
    隐藏导航栏之前:

    隐藏导航栏后:

    混合navigationController.navigationBar.hidden=不与setNavigationBarHidden一起使用会导致一些奇怪的事情,隐藏对我来说根本不起作用。当使用单一方法时,效果很好。您建议什么时候在视图生命周期中执行此操作?@Whoa:我建议使用“ViewWillExample:”方法执行此操作。我从未将转换事件放置到元素中,其重要性与viewDidLoad中的导航栏相同。。。这样做是不明智的,特别是如果孩子和/或父母的风投有互动解雇。将导航栏动画放置在ViewWillDisplay中或在生命周期的更晚时间,如上所述。在iOS13 beta中,当从没有导航栏的主视图过渡到有导航栏的子VCs时,我再次看到丑陋的动画,即使代码在ViewWillDisplay中。主屏幕图形显示在大标题后面的区域中。有什么建议吗?我认为移动
    UINavigationController
    UINavigationBar
    不是一个好主意。
    UINavigationController
    的工作是管理该条,如果该条位于控制器认为之外的其他地方,则可能导致UI异常。