【问题标题】:UINavigationBar tintColor with gradientUINavigationBar tintColor 带渐变
【发布时间】:2010-10-04 10:40:16
【问题描述】:

我想以编程方式更改 UINavigationBar 的 tintColor 并保持界面生成器中的渐变。

当我在代码中更改 tintColor 时,渐变会消失,但是当我在 Interface Builder 中更改 tintColor 时,渐变会保留。

有什么想法吗?

【问题讨论】:

    标签: iphone cocoa-touch interface-builder


    【解决方案1】:

    使用 maskView 的好方法

    // create gradient view
    let gradientView: UIView = UIView(frame: frame)
    let gradient: CAGradientLayer = CAGradientLayer()
    gradient.frame = gradientView.bounds
    gradient.colors = [UIColor.grayColor().CGColor, UIColor.clearColor().CGColor]
    gradientView.layer.insertSublayer(gradient, atIndex: 0)
    
    //set appearance 
    UINavigationBar.appearance().maskView = gradientView
    

    【讨论】:

      【解决方案2】:

      我只是把它写成 Swift 2.0 的 UIImage 扩展。也许有点用处。

      extension UIImage {
      
          class func convertGradientToImage(colors: [UIColor], frame: CGRect) -> UIImage {
      
              // start with a CAGradientLayer
              let gradientLayer = CAGradientLayer()
              gradientLayer.frame = frame
      
              // add colors as CGCologRef to a new array and calculate the distances
              var colorsRef : [CGColorRef] = []
              var locations : [NSNumber] = []
      
              for i in 0 ... colors.count-1 {
                  colorsRef.append(colors[i].CGColor as CGColorRef)
                  locations.append(Float(i)/Float(colors.count))
              }
      
              gradientLayer.colors = colorsRef
              gradientLayer.locations = locations
      
              // now build a UIImage from the gradient
              UIGraphicsBeginImageContext(gradientLayer.bounds.size)
              gradientLayer.renderInContext(UIGraphicsGetCurrentContext()!)
              let gradientImage = UIGraphicsGetImageFromCurrentImageContext()
              UIGraphicsEndImageContext()
      
              // return the gradient image
              return gradientImage
          }
      }
      

      这样称呼它:

      let colors = [
          UIColor.blueColor(),
          UIColor.greenColor()
          // and many more if you wish
      ]
      let gradientImage = UIImage.convertGradientToImage(colors, frame: navigationBar.bounds)
      navigationBar.setBackgroundImage(gradientImage, forBarMetrics: .Default)
      

      【讨论】:

      • 如果您在其中内置一些旋转控件会很好。
      • 我试过这个。它的工作。但是,状态栏背景颜色为黑色。导航栏单独使用预期的渐变效果很好。如何也改变状态栏????
      【解决方案3】:

      所以这是一个老问题,但是当我在搜索听起来像这个问题但不同的东西时,我偶然发现了它。希望它可以帮助其他人(或者其他人会告诉我更好的方法)......

      如何在 UINavigationBar 上实现自定义渐变?

      首先,让我们以通常的方式获取自定义渐变(作为 CALayer):

      - (CALayer *)gradientBGLayerForBounds:(CGRect)bounds
      {
          CAGradientLayer * gradientBG = [CAGradientLayer layer];
          gradientBG.frame = bounds;
          gradientBG.colors = @[ (id)[[UIColor redColor] CGColor], (id)[[UIColor purpleColor] CGColor] ];
          return gradientBG;
      }
      

      我们开始了,渐变看起来像是朋克摇滚乐的可疑化妆选择,这很好,因为此代码适用于假设的应用程序我的口袋里有一个口味可疑的朋克摇滚乐。我这个名字有点太长了..

      现在我想要 UINavigationBar 上的这一层,这应该很容易吧?只需将其添加为子图层,对吗?这里的问题是它会掩盖 UINavigationController 给你的美妙的按钮和东西。这很糟糕。

      相反,让我们看看 iOS5+ 中用于更改应用中所有 UINavigationBar(s) 外观的绝妙便捷方法:

      [[UINavigationBar appearance] setBackgroundImage:SOME_IMAGE
                                         forBarMetrics:UIBarMetricsDefault];
      

      这里唯一的问题是我们没有 UIImage,我们有一个 CALayer。朋克摇滚爱好者该怎么办?

      CALayer * bgGradientLayer = [self gradientBGLayerForBounds:ONE_OF_YOUR_NAV_CONTROLLERS.navigationBar.bounds];
      UIGraphicsBeginImageContext(bgGradientLayer.bounds.size);
      [bgGradientLayer renderInContext:UIGraphicsGetCurrentContext()];
      UIImage * bgAsImage = UIGraphicsGetImageFromCurrentImageContext();
      UIGraphicsEndImageContext();
      

      现在我们已经将 CALayer 转换为 UIImage(希望如此),剩下的就是设置它:

      if (bgAsImage != nil)
      {
          [[UINavigationBar appearance] setBackgroundImage:bgAsImage
                                             forBarMetrics:UIBarMetricsDefault];
      }
      else
      {
          NSLog(@"Failded to create gradient bg image, user will see standard tint color gradient.");
      }
      

      我喜欢这个解决方案的地方是

      • 我的应用中所有 UINavigationBar(s) 的集中式代码(在 AppDelegate 中)
      • tintColor 仍将适用于所有 UINavigation 按钮(返回、编辑等)
      • 如果 UIImage 创建失败,我的 UINavigationBar(s) 仍将遵循 tintColor
      • 我不必依赖实际的图像资源/易于更新

      但我仍然不相信这是最好的方法。所以,如果它对你有帮助,请尽情享受,如果可以的话,让我知道如何改进它。

      ~谢谢

      【讨论】:

      • 您的“我的口袋里有一个口味可疑的朋克摇滚乐手”应用程序什么时候推出?我还在等。
      • 好吧,我在最后一分钟换了方向,我想我现在要去动物方向了,也许是“嘻哈-奥波塔姆斯和我口袋里的朋友”,也许是 Bebop 和 Rocksteady 的许可形式TMNT,这样我还能用这个有问题的配色方案
      • 这是完美的——正是我所需要的。谢谢!!
      【解决方案4】:
      navigation.tintColor = [UIColor colorWithRed:0.47f green:0.23f blue:0.61f alpha:1.0f];
      

      【讨论】:

        【解决方案5】:

        将 barStyle 设置为 UIBarStyleBlackTranslucent 像这样设置 tintColor:

        navigationBar.tintColor = [UIColor colorWithRed:.7 green:.5 blue:.2 alpha:1];
        

        这将设置适当的渐变。使用您需要的任何组合。

        【讨论】:

        • 使仅 navigationBar.tintColor = [UIColor colorWithRed: ..etc..] tintColor 保留颜色,因此您的代码泄漏。
        • UIBarStyleBlackTranslucent 已被弃用。最好使用 navigationBar.barStyle = UIBarStyleBlack; navigationBar.translucent = YES;
        • 我尝试了 Amagrammer 的评论。但它只使状态栏颜色不会被导航栏更改。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-06-21
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多