在代码中发现设置navigationBar的背景颜色都是将一个颜色绘制为 UIImage 然后 通过 setBackgroundImage()进行赋值,而没有使用常见的 backgroundColor。
尝试直接给 navigationBar 直接设置 backgroundColor 发现并没有正常工作,只有在 UINavigationBarAppearance().backgroundColor 上赋值才会有用,所以查找资料了解了一下navigationBar的背景颜色
backgroundColor
直接添加
1 | backgroundColor = .green |
会被 navigationBar 的 isTranslucent 属性所影响:
isTranslucent = false
isTranslucent = true
也就是说 他是真正的背景颜色 navigationBar的颜色设置不来源于继承自UIView的 backgroundColor
附:在iOS15中 navigationBar 默认为全透明 所以此时的表现是这样:
barTintColor
barTintColor 才是真正设置 navigationBar 的 backgroundColor 的方法但是直接使用
1 | barTintColor = .orange |
的颜色并不是真正的 .orange 上面蒙了一层白色

查找官方文档后发现 isTranslucent属性默认为true 那如果将 isTranslucent 设为 false呢

附:tintColor是应用于导航项和按钮项的色调颜色
那我们如果既想使用半透明 又想要纯正的颜色呢 那就需要设置backgroundImage了:
backgroundImage
直接设置 backgroundImage 即可得到我们想要的效果(imge()为给UIColor添加的extension)
1 | setBackgroundImage(UIColor.yellow.image(), for: .default) |

但是如果我们设置一个半透明图片
1 | setBackgroundImage(UIColor.yellow.withAlphaComponent(0.5).image(), for: .default) |
则出现了和之前一样的问题 translucent 为 true 时 影响到了原来的布局。

translucent 和 setBackgroundImage
前面提到我们可以通过修改背景图片来修改导航栏的背景色,设置了背景图片后在有些页面我们会遇到一些奇怪的问题,发现原来布局正常的页面显示不对了,会多出一部分空白或者被导航栏遮挡住了。
通过打印出 translucent 的值我们发现设置了纯色的背景图后原来半透明的导航栏变成了不透明的,结合前面提到的 translucent 对布局起点的影响,如果页面是按照半透明情况,即 rootView 从(0,0)开始布局来设置子视图的 frame,那么设置了纯色背景图后 translucent 变成了 false,此时 rootview 从 navigationBar 下面开始布局 。为什么设置背景图片会影响 translucent 呢,通过查看文档发现了如下说明:
1 | /* |
也就是说背景图片如果包含 alpha 的色值,系统会默认将 translucent 设置为 true,没有包含 alpha 色值会将 translucent 设置为 false。这下真相大白了,原来我们前面设置了纯绿色的背景图片,是不包含 alpha 色值的,即系统默认将 translucent 设置成了 false。但这是针对没有手动设置 translucent 值的情况,如果我们手动设置了 translucent,那么系统就不会根据背景图片的 alpha 来修改 translucent。
至此,我们了解了苹果是如何使用这几个属性的:
- translucent 默认为 true,rootView 从(0,0)开始布局
- translucent 设置为 false,rootView 从导航栏底部开始布局
- automaticallyAdjustsScrollViewInsets 默认值是 true,用来纠正scrollview在全屏模式下的显示;
- 设置
UINavigationBar的背景图片可以改变导航栏背景色,如果背景图片包含 alpha 的色值,系统会默认将 translucent 设置为 true,没有包含 alpha 色值会将 translucent 设置为 false。但这是针对没有手动设置 translucent 值的情况,如果我们手动设置了 translucent,那么系统就不会根据背景图片的 alpha 来修改 translucent。
上面是在iOS13以前的 Legacy Customizations 在 iOS13 苹果提出了新的 UINavigationBarAppearance来配置navigationBar的 standardAppearance, compactAppearance, scrollEdgeAppearance 三种状态。
UINavigationBarAppearance 继承自 UIBarAppearance ,在这里我们可以自由的定义backgroundColor 等等各种属性。
苹果官网的介绍:https://developer.apple.com/documentation/uikit/uinavigationbar
Customize the Appearance of a Navigation Bar
Navigation bars have two standard appearance styles: white with dark text or black with light text. Use the
barStyleproperty to select the style. Any changes you make to other navigation bar appearance properties override those inferred from the bar style.Navigation bars are translucent by default; that is, their background color is semitransparent. You can make the navigation bar opaque by setting the
isTranslucentproperty tofalse.You can specify a custom tint color for a navigation bar background using the
barTintColorproperty. Setting this property overrides the default color inferred from the bar style. As with allUIViewsubclasses, you can control the color of the interactive elements within navigation bars, including button images and titles, using thetintColorproperty.The
titleTextAttributesproperty specifies the attributes for displaying the bar’s title text. You can specify the font, text color, text shadow color, and text shadow offset for the title in the text attributes dictionary using thefont,foregroundColor, andshadowkeys, respectively. For more information about string-formatting attributes, seeCharacter Attributes.Use the
setTitleVerticalPositionAdjustment(_:for:)method to adjust the vertical position of the title. This method allows you to specify the adjustment dependent on the bar height, which is represented by theUIBarMetricsenum. The following figure shows a navigation bar with custom tint color, title text attributes, and bar tint color.![]()
To allow complete customization over the appearance of navigation bars, you can additionally provide custom background and shadow images. To provide a custom background image, use the
setBackgroundImage(_:for:barMetrics:)method, providing aUIImageobject for the appropriate bar position and metrics values. Use aUIBarPositionvalue for the bar position argument to specify whether to use the supplied image at the bottom or the top of the window, and if it appears at the top, whether to extend it upward under the status bar. Similarly, you can specify that the image should be used for either compact or default bar metrics, with or without a prompt, by providing aUIBarMetricsvalue to the bar metrics argument.To add a shadow, provide a resizable
UIImageto theshadowImageproperty. To use the custom shadow image, you need to have specified a custom background image. The following figure shows a navigation bar with a custom background image, supplied usingsetBackgroundImage(_:for:barMetrics:)with a bar position value ofUIBarPosition.topAttachedand a bar metrics value ofUIBarMetrics.default. A custom image has also been provided to theshadowImageproperty.![]()
To see examples of customizing a navigation bar, see Customizing Your App’s Navigation Bar.