我想以编程方式更改tintColor
UINavigationBar 的,并保持界面生成器中的渐变。
当我tintColor
在我的代码中更改时,渐变会消失,但是当我tintColor
在 Interface Builder 中更改时,渐变会被保留。
有任何想法吗?
我想以编程方式更改tintColor
UINavigationBar 的,并保持界面生成器中的渐变。
当我tintColor
在我的代码中更改时,渐变会消失,但是当我tintColor
在 Interface Builder 中更改时,渐变会被保留。
有任何想法吗?
所以这是一个老问题,但是当我在寻找听起来像这个问题但不同的东西时,我偶然发现了它。希望它可以帮助其他人(或者其他人会告诉我更好的方法)......
如何在 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;
}
我们开始了,一个看起来像是朋克摇滚乐的可疑化妆选择的渐变,这很好,因为此代码用于假设的应用程序I Have A Punk-Rocker With Questionable Tastes In My Pocket。我这个名字有点太长了..
现在我想要我的 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.");
}
我喜欢这个解决方案的地方是
但我仍然不相信这是最好的方法。所以,如果它对你有帮助,请尽情享受,如果可以的话,让我知道如何改进它。
~ 谢谢
将 barStyle 设置为 UIBarStyleBlackTranslucent 像这样设置 tintColor:
navigationBar.tintColor = [UIColor colorWithRed:.7 green:.5 blue:.2 alpha:1];
这将设置适当的渐变。使用您需要的任何组合。
我只是把它写成 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)
navigation.tintColor = [UIColor colorWithRed:0.47f green:0.23f blue:0.61f alpha:1.0f];
使用 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