问题描述
App 开发中,有时候需要改变导航栏或者状态栏背景色、字体颜色,或者实现导航栏背景色渐变效果,那么,接下来的部分为你解答,请看下文!
自定义状态栏
状态栏字体默认是黑色,修改成白色,需要设置两个地方,如下所示:
第一步:工程配置文件 plist 中添加 View controller-based status bar appearance ,状态值设置为 NO,Source Code 如下:
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
第二步:设置 UIApplication 对象,可以在 AppDelegate 或者 导航控制器中设置,或者你需要改变的控制器中设置,如下所示:
// default 默认黑色 lightContent 白色
UIApplication.shared.statusBarStyle = .lightContent
自定义导航栏
导航栏设置颜色
导航栏设置字体颜色和大小,需要设置 titleTextAttributes 属性,背景色需要设置 barTintColor 属性,如下所示:
let attributes = [
NSForegroundColorAttributeName : UIColor.blue,
NSFontAttributeName: UIFont.systemFont(ofSize: 18)]
// 设置导航栏 字体 为 蓝色, 字体 大小 为 18 号字体
UINavigationBar.appearance().titleTextAttributes = attributes
// 设置导航栏 背景 为 红色
UINavigationBar.appearance().barTintColor = UIColor.red
效果图如下:
导航栏设置图片
导航栏设置背景图片,只能显示纯色图片,如果其他控制器中修改导航栏背景,会影响到之前的设置,代码如下:
self.navigationBar.backgroundColor = UIColor.clear
self.navigationBar.barTintColor = UIColor.clear
// 主要是下面这句,上面两句主要是防止干扰
self.navigationBar.setBackgroundImage(UIImage(named: "xxxxxx"), for: .default)
效果图如下:
注意:如果代码中有如下设置,会使导航栏设置的图片失效,代码如下:
if #available(iOS 9.0, *) {
navigationController?.navigationBar.subviews[0].subviews[0].isHidden = true;
} else {
navigationController?.navigationBar.subviews[0].subviews[1].isHidden = true;
}
导航栏设置渐变色
导航栏设置渐变色需要用到 CAGradientLayer 类,具体代码如下:
let gradientLayer = CAGradientLayer()
let startColor = UIColor.red
let endColor = UIColor.yellow
gradientLayer.colors = [startColor.cgColor, endColor.cgColor]
gradientLayer.locations = [0.3, 0.7]
gradientLayer.startPoint = CGPoint(x: 0, y: 0)
gradientLayer.endPoint = CGPoint(x: 1.0, y: 0)
// gradientLayer.frame = CGRect(x: 0, y: -20.0, width: self.view.width, height: 64.0)
gradientLayer.frame = CGRect(x: 0, y: 0, width: self.view.width, height: 64.0)
self.navigationBar.isTranslucent = false
// self.navigationBar.layer.addSublayer(gradientLayer)
if let barBackground = self.navigationBar.subviews.first {
barBackground.layer.insertSublayer(gradientLayer, at: 0)
}
注意:其中 isTranslucent 属性的使用,可以参考下面这篇文章:
http://www.cnblogs.com/gfxxbk/p/5999663.html
效果图如下:
特别强调:如果我们把注释掉的代码和相应的代码替换,会导致导航栏在 push 或者 pop 的过程中,导航栏标题和返回按钮不显示,如下所示:
let gradientLayer = CAGradientLayer()
let startColor = UIColor.red
let endColor = UIColor.yellow
gradientLayer.colors = [startColor.cgColor, endColor.cgColor]
gradientLayer.locations = [0.3, 0.7]
gradientLayer.startPoint = CGPoint(x: 0, y: 0)
gradientLayer.endPoint = CGPoint(x: 1.0, y: 0)
gradientLayer.frame = CGRect(x: 0, y: -20.0, width: self.view.width, height: 64.0)
// gradientLayer.frame = CGRect(x: 0, y: 0.0, width: self.view.width, height: 64.0)
self.navigationBar.isTranslucent = false
self.navigationBar.layer.addSublayer(gradientLayer)
// if let barBackground = self.navigationBar.subviews.first {
//
// barBackground.layer.insertSublayer(gradientLayer, at: 0)
// }
当 push 到子控制器,就会导致子控制器中的导航栏标题和返回按钮显示不出来,对应的效果如下:
所以我们需要将自定义 layer 添加到 self.navigationBar.subviews.first 对应的 layer 中,具体原因可能和导航栏的图层有关,正确的效果图如下:
视图层级调试
介绍
Debug View Hierarchy(视图层级调试)是 XCode 6 新出的一项功能,它可以让开发者在程序运行时,动态的查看当前界面的显示情况,包括视图的层次,控件的大小和位置,而且会以 3D 效果显示当前视图的层次。
使用
上面 为什么将自定义 layer 添加到 self.navigationBar.subviews.first 对应的 layer 中,正式根据 视图层级调试 模式得出来的。具体使用如下图所示:
运行程序进入视图层级调试模式:
查看视图层级关系: