【问题标题】:Change the alpha value of the navigation bar更改导航栏的 alpha 值
【发布时间】:2013-07-04 00:35:02
【问题描述】:

这可能吗?

我想更改视图控制器中导航栏的 alpha 值(在动画中),但如果我这样做 self.navigationController.navigationBar.alpha = 0.0;,导航栏占据的屏幕部分将完全消失并留下一个黑框,其中不是我想要的(我希望它是self.view 的背景颜色)。

【问题讨论】:

  • 您的视图是否实际上延伸到导航栏下方,或者您只是希望视图的背景颜色是在 alpha'd 栏下方看到的颜色?而且,您是否只需要这个来实现动画效果,还是需要让条形部分存在以进行用户交互?

标签: ios objective-c uiview uinavigationcontroller uinavigationbar


【解决方案1】:

由于我支持 Colin 的回答,我想给你一个额外的提示来自定义 UINavigationBar 的外观,包括 alpha。

诀窍是为您的 NavigationBar 使用 UIAppearance。这使您可以将 UIImage 分配给 NavigationBar 的 backgroundImage。您可以通过编程方式生成这些 UIImage 并用于该 UIColors 并根据需要设置 颜色的 alpha 属性。我已经在我自己的一个应用程序中完成了这项工作,并且按预期工作。

这里我给你一些代码sn-ps:

  1. 例如在您的 ..AppDelegate.m 中,在 didFinishLaunchingWithOptions 中添加这些行:

    //create background images for the navigation bar
    UIImage *gradientImage44 = nil; //replace "nil" with your method to programmatically create a UIImage object with transparent colors for portrait orientation
    UIImage *gradientImage32 = nil; //replace "nil" with your method to programmatically create a UIImage object with transparent colors for landscape orientation
    
    //customize the appearance of UINavigationBar
    [[UINavigationBar appearance] setBackgroundImage:gradientImage44 forBarMetrics:UIBarMetricsDefault];
    [[UINavigationBar appearance] setBackgroundImage:gradientImage32 forBarMetrics:UIBarMetricsLandscapePhone];
    [[UINavigationBar appearance] setBarStyle:UIBarStyleDefault];
    
  2. 实现方便的方法以编程方式创建 UIImage 对象,例如为 UIImage 创建一个新类别:

    //UIImage+initWithColor.h
    //
    #import <UIKit/UIKit.h>
    
    @interface UIImage (initWithColor)
    
    //programmatically create an UIImage with 1 pixel of a given color
    + (UIImage *)imageWithColor:(UIColor *)color;
    
    //implement additional methods here to create images with gradients etc.
    //[..]
    
    @end
    
    //UIImage+initWithColor.m
    //
    #import "UIImage+initWithColor.h"
    #import <QuartzCore/QuartzCore.h>
    
    @implementation UIImage (initWithColor)
    
    + (UIImage *)imageWithColor:(UIColor *)color
    {
        CGRect rect = CGRectMake(0, 0, 1, 1);
    
        // create a 1 by 1 pixel context 
        UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0);
        [color setFill];
        UIRectFill(rect);
    
        UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
    
        return image;
    }
    
  3. 在 1 中重新创建图像。(AppDelegate.m 中的#import "UIImage+initWithColor.h" 并替换 "nil"):

这是您感兴趣的地方:通过更改颜色的 alpha 属性,您也会影响 NavigationBar 的不透明度!

            UIImage *gradientImage44 = [UIImage imageWithColor:[UIColor colorWithRed:1.0 green:0.0 blue:1.0 alpha:0.2]];
            UIImage *gradientImage32 = [UIImage imageWithColor:[UIColor colorWithRed:1.0 green:0.0 blue:1.0 alpha:0.2]];

我创建了一个小型演示项目,并添加了两个屏幕截图: 视图本身具有黄色背景颜色。 NavigationBar 的 backgroundImages 具有红色。 屏幕截图 1 显示了一个具有 alpha = 0.2 值的 NavigationBar。 屏幕截图 2 显示了一个具有 alpha = 0.8 值的 NavigationBar。

【讨论】:

    【解决方案2】:

    最直接的做法是修改navigationBar背景视图的alpha组件,此时(iOS9)是第一个navigationBar子视图。但是请注意,我们永远不知道 Apple 在以后的版本中是否会更改子视图层次结构,所以要小心。

    let navigationBackgroundView = self.navigationController?.navigationBar.subviews.first
    navigationBackgroundView?.alpha = 0.7
    

    【讨论】:

      【解决方案3】:

      直接来自 Apple 开发者参考:

      “您只能对 导航栏。具体修改barStyle就可以了, tintColor 和 translucent 属性,但绝对不能直接 更改UIView 级别的属性,例如frame、bounds、 alpha 或 hidden 属性直接。”

      但是,您可以设置导航栏的半透明属性。如果你这样做[self.navigationController.navigationBar setTranslucent:YES]; 应该可以解决您的问题。您还可以尝试查看是否有任何 UIBarStyle 枚举是您想要的。

      【讨论】:

      • 半透明选项不起作用,似乎只是让导航栏变亮了一点。
      • @DougSmith 是的,但是道格,当您将栏设置为半透明时,视图会调整大小以使用整个屏幕(无状态栏),所以如果您使用 self.navigationController.navigationBar.alpha = 0.0; 制作动画将按您的预期工作,视图的内容将呈现在状态栏后面。刚刚在一个一次性项目中尝试过,它成功了。
      • 另外请记住,如果您将translucent 设置为YES,您将不得不调整视图的框架,因为它会向上移动以覆盖导航栏下方的空间(现在已变为透明) .
      • 是的 - @RobvanderVeer - 这似乎可以解决 self.edgesForExtendedLayout = []
      【解决方案4】:

      MickBraun 在 Swift 中的回答:

      1. 在 AppDelegate.swift 中,在 didFinishLaunchingWithOptions 中添加这些行:

        // create background images for the navigation bar
        let gradientImage44 = UIImage.imageWithColor(UIColor(red: 1.0, green: 0.0, blue: 1.0, alpha: 0.2))
        let gradientImage32 = UIImage.imageWithColor(UIColor(red: 1.0, green: 0.0, blue: 1.0, alpha: 0.2))
        
        // customize the appearance of UINavigationBar
        UINavigationBar.appearance().setBackgroundImage(gradientImage44, forBarMetrics: .Default)
        UINavigationBar.appearance().setBackgroundImage(gradientImage32, forBarMetrics: .Compact)
        UINavigationBar.appearance().barStyle = .Default
        
      2. 实现方便的方法以编程方式创建 UIImage 对象。

        class func imageWithColor(colour: UIColor) -> UIImage {
            let rect = CGRectMake(0, 0, 1, 1)
        
            // Create a 1 by 1 pixel content
            UIGraphicsBeginImageContextWithOptions(rect.size, false, 0.0)
            colour.setFill()
            UIRectFill(rect)
        
            let image = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
        
            return image
        }
        

      【讨论】:

      • 第 1 部分的最后一行实际上是 UINavigationBar.appearance().barStyle = .Default,至少在 Swift 2 和 iOS 9 中是这样。
      【解决方案5】:

      如果您只想以动画方式摆脱navigationBar,您可以这样做:

      [self.navigationController setNavigationBarHidden:YES animated:YES];
      

      如果您想控制动画并且需要将alpha 设置为0.0,请继续阅读:

      您看到的“黑匣子”来自底层视图或窗口。如果您只想让视图颜色而不是“黑匣子”,请执行以下操作:

      self.navigationController.view.backgroundColor = self.view.backgroundColor;
      
      [UIView animateWithDuration:1.0 delay:1.0 options:0 animations:^{
          self.navigationController.navigationBar.alpha = 0.0;
      } completion:NULL];
      

      如果您希望您的实际视图位于 navigationBar 所在的位置,则需要增加视图的 height:

      [UIView animateWithDuration:1.0 delay:1.0 options:0 animations:^{
          self.navigationController.navigationBar.alpha = 0.0;
      
          CGFloat navigationBarHeight = self.navigationController.navigationBar.frame.size.height;
      
          CGRect frame = self.view.frame;
          frame.origin.y -= navigationBarHeight;
          frame.size.height += navigationBarHeight;
          self.view.frame = frame;
      } completion:NULL];
      

      【讨论】:

      • 这会将状态栏的颜色从黑色更改为灰色。 ://
      • 三种方法中的哪一种?
      【解决方案6】:

      您有几个选项,部分取决于您的UINavigationBar 的 barStyle。主要是意识到您可能不一定必须为 alpha 属性设置动画才能获得您所描述的效果。

      UIBarStyleDefault 或 UIBarStyleBlackOpaque 选项 A 是将 UINavigationBar 半透明属性设置为 YES,然后为 alpha 设置动画:

                  navigationBar.translucent = YES; // ideally set this early, in the nib/storyboard, or viewDidLoad
      
      ...
      
                  [UIView animateWithDuration: 1.0
                                   animations: ^{
      
                                       // toggle:
                                       navigationBar.alpha = navigationBar.alpha == 0 ? 1.0 : 0.0;
      
                                   }];
      

      在这种情况下,您的视图将位于导航栏后面,即使它的 alpha 为 1.0。这种情况的缺点是,即使使用 1.0 alpha,您也可能会在 UINavigationBar 后面看到一点视图背景颜色。此外,您的所有子视图都需要位于距离顶部 44 点的位置。

      UIBarStyleDefault 或UIBarStyleBlackOpaque 选项B是在交叉溶解过渡动画中隐藏导航栏。这将公开UINavigationBar 的超级视图。如果您使用的是UINavigationController,那么您将看到UINavigationController 视图的黑色背景 - 但您可以设置UINavigationController 视图的背景颜色以匹配您的视图以获得您想要的效果:

          UINavigationBar* navigationBar = self.navigationController.navigationBar;
      
          self.navigationController.view.backgroundColor = self.view.backgroundColor;
          [UIView transitionWithView: navigationBar
                            duration: 1.0
                             options: UIViewAnimationOptionTransitionCrossDissolve
                          animations: ^{
                              // toggle:
                              navigationBar.hidden = !navigationBar.hidden;
                          }
                          completion: nil];
      

      如果UINavigationController 因为您隐藏了UINavigationBar 而更新了您的视图框架,则使用此解决方案需要注意的一点可能是布局问题。这很好,只是如果您的子视图锚定在左上角,它们可能会向上移动 44 像素。要解决这个问题,您可以考虑将子视图锚定到视图底部(使用弹簧或布局约束)。

      UIBarStyleDefault或UIBarStyleBlackOpaque选项C是用另一个视图覆盖UINavigationBar,再次使用交叉溶解过渡动画:

              UINavigationBar* navigationBar = self.navigationController.navigationBar;
      
              [UIView transitionWithView: navigationBar
                                duration: 1.0
                                 options: UIViewAnimationOptionTransitionCrossDissolve | UIViewAnimationOptionAllowAnimatedContent
                              animations: ^{
      
                                  // toggle:
                                  const int tag = 1111; 
                                  UIView* navOverlayView = [navigationBar viewWithTag: tag];
                                  if ( navOverlayView == nil )
                                  {
                                      navOverlayView = [[UIView alloc] initWithFrame: CGRectInset( navigationBar.bounds, 0, -3 ) ];
                                      navOverlayView.backgroundColor = self.view.backgroundColor;
                                      navOverlayView.tag = tag;
                                      [navigationBar addSubview: navOverlayView];
                                  }
                                  else
                                  {
                                      [navOverlayView removeFromSuperview];
                                  }
                              }
                              completion: nil];
      

      UIBarStyleBlackTranslucent:这个选项是最简单的,因为UINavigationBar 已经是半透明的,并且你的视图已经在它后面了。简单地为 alpha 设置动画:

          [UIView animateWithDuration: 1.0
                           animations: ^{
      
                               // toggle:
                               navigationBar.alpha = navigationBar.alpha == 0 ? 1.0 : 0.0;
      
                           }];
      

      【讨论】:

        【解决方案7】:

        你也可以尝试在导航栏下方设置一个背景视图,直接修改这个视图。

        private lazy var backgroundView: UIView = UIView()
        
        ...
        
        private func setupNavigationBarBackground() {
            guard let navigationBar = navigationController?.navigationBar else { return }
            navigationBar.setBackgroundImage(UIImage(), for: .default)
            navigationBar.isTranslucent = true
            view.addSubview(backgroundView)
            backgroundView.alpha = 0
            backgroundView.backgroundColor = .red
            backgroundView.translatesAutoresizingMaskIntoConstraints = false
            backgroundView.topAnchor.constraint(equalTo: topLayoutGuide.topAnchor).isActive = true
            backgroundView.bottomAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor).isActive = true
            backgroundView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
            backgroundView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
        }
        
        private func changeNavigationBarAlpha(to alpha: CGFloat) {
            backgroundView.alpha = alpha
        }
        

        【讨论】:

          【解决方案8】:

          这应该会得到你想要的效果:

          self.navigationController.navigationBar.alpha = 0.0;
          self.navigationController.navigationBar.frame = CGRectMake(0,0,320,0);
          

          没有在动画中尝试过,但在我的 viewDidAppear 中有效,希望它有效。

          【讨论】:

            【解决方案9】:

            Swift3

            var navAlpha = // Your appropriate calculation   
            self.navigationController!.navigationBar.backgroundColor =  UIColor.red.withAlphaComponent(navAlpha)
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2016-02-01
              • 1970-01-01
              • 1970-01-01
              • 2011-08-15
              • 2018-04-03
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多