如何更正 iPhone X 上的 Tab Bar 高度问题
How to correct Tab Bar height issue on iPhone X
我的应用程序在测试 iPhone X 时遇到问题。我不确定如何调整这个问题,以及如何不让它成为非 iPhone 的问题X尺寸。这似乎只是 iPhone X 模拟器上的问题。
invalidateIntrinsicContentSize of UITabBar in viewWillLayoutSubviews 可能对你有帮助。
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
self.tabBar.invalidateIntrinsicContentSize()
}
"File inspector" 从 Xcode 故事板右侧开始,启用安全区域指南布局以支持您在 iPhone
中的应用
描述的真好。
受限 -
如果您将底部 space 与 "Bottom Layout Guide" 一起使用,则会出现此问题。
解法:
关于 superview 的底部 space。这将 100% 完美。
我的解决方案是自定义 UITabBar 高度设置,如下所示:
override func viewWillLayoutSubviews() {
var tabFrame = tabBar.frame
tabFrame.size.height = 60
tabFrame.origin.y = self.view.frame.size.height - 60
tabBar.frame = tabFrame
}
删除它,标签栏将在 iPhone X 上正确显示。
这对我有用,因为我正在使用选择图像。
tabBar.selectionIndicatorImage = UIImage.imageWithColor(color: UIColor.NewDesignColor.yellow, size: tabBarItemSize).resizableImage(withCapInsets: UIEdgeInsets.init(top: 0, left: 0, bottom: 20, right: 0))
添加底部插图对我的情况有帮助。
希望这也适用于您。
谢谢
对于 iOS 11.3 这对我有用:
func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
tabBar.invalidateIntrinsicContentSize()
}
我遇到了类似的问题。我在 viewDidLoad() 中设置了 selectionIndicatorImage。将代码移至 viewDidLayoutSubviews() 解决了我的问题。
使用以下代码创建一个单独的文件:
extension UITabBar {
override open func sizeThatFits(_ size: CGSize) -> CGSize {
super.sizeThatFits(size)
guard let window = UIApplication.shared.keyWindow else {
return super.sizeThatFits(size)
}
var sizeThatFits = super.sizeThatFits(size)
sizeThatFits.height = window.safeAreaInsets.bottom + 40
return sizeThatFits
}
}
只需将 UITabBar 的底部与超级视图对齐,而不是与安全区域对齐。如果将它对齐到安全区域,它将是这样的:
并且当与父视图对齐时,它将正确显示:
我认为这是因为 Apple 为标签栏项目提供了默认的底部边距,如果它位于 iPhone X 上,因为他们希望将标签栏扩展到屏幕底部以避免浮动栏.
按照以下指南设置 UITabbar selectionIndicatorImage。
- UITabBar.appearance().selectionIndicatorImage = #YOUR_IMAGE
- 确保您的图片高度为 48。
tabbar selectionIndicatorImage默认高度为49,但在iPhoneX中设置图片高度等于48。
在 iOS 12.1 我已经通过覆盖 UITabBar 子类中的 safeAreaInsets 解决了这个问题:
class TabBar: UITabBar {
private var cachedSafeAreaInsets = UIEdgeInsets.zero
override var safeAreaInsets: UIEdgeInsets {
let insets = super.safeAreaInsets
if insets.bottom < bounds.height {
cachedSafeAreaInsets = insets
}
return cachedSafeAreaInsets
}
}
iOS 13.0 以上,
class TabBar: UITabBar {
private var cachedSafeAreaInsets = UIEdgeInsets.zero
let keyWindow = UIApplication.shared.connectedScenes
.filter { [=11=].activationState == .foregroundActive }
.compactMap { [=11=] as? UIWindowScene }
.first?.windows
.filter { [=11=].isKeyWindow }
.first
override var safeAreaInsets: UIEdgeInsets {
if let insets = keyWindow?.safeAreaInsets {
if insets.bottom < bounds.height {
cachedSafeAreaInsets = insets
}
}
return cachedSafeAreaInsets
}
}
有 UITabBar
子类解决了我所有关于 iPhone X iOS 11
/ iOS 12
的问题
class TabBar: UITabBar {
private var _safeAreaInsets = UIEdgeInsets.zero
private var _subviewsFrames: [CGRect] = []
@available(iOS 11.0, *)
override func safeAreaInsetsDidChange() {
super.safeAreaInsetsDidChange()
if _safeAreaInsets != safeAreaInsets {
_safeAreaInsets = safeAreaInsets
invalidateIntrinsicContentSize()
superview?.setNeedsLayout()
superview?.layoutSubviews()
}
}
override func sizeThatFits(_ size: CGSize) -> CGSize {
var size = super.sizeThatFits(size)
if #available(iOS 12.0, *) {
let bottomInset = safeAreaInsets.bottom
if bottomInset > 0 && size.height < 50 && (size.height + bottomInset < 90) {
size.height += bottomInset
}
}
return size
}
override var frame: CGRect {
get {
return super.frame
}
set {
var tmp = newValue
if let superview = superview, tmp.maxY !=
superview.frame.height {
tmp.origin.y = superview.frame.height - tmp.height
}
super.frame = tmp
}
}
override func layoutSubviews() {
super.layoutSubviews()
let state = subviews.map { [=10=].frame }
if (state.first { [=10=].width == 0 } == nil) {
_subviewsFrames = state
} else {
zip(subviews, _subviewsFrames).forEach { (view, rect) in
view.frame = rect
}
}
}
}
Apple 现已在 iOS 12.1.1
中修复了此问题
这看起来很疯狂,但我只需要在我的代码中删除这一行
self.view.layoutIfNeeded()
我只是猜测在屏幕上没有出现的视图上调用 layoutIfNeeded 会导致这个问题发生。
无论如何,@mohamed-ali 的解决方案也可以正常工作。非常感谢。
在viewDidLoad中添加这段代码
DispatchQueue.main.async {
let size = CGSize(width: self.tabBar.frame.width / numberOfTabsFloat,
height: self.tabBar.frame.height)
let image = UIImage.drawTabBarIndicator(color: UIColor.white,
size: size,
onTop: false)
UITabBar.appearance().selectionIndicatorImage = image
self.tabBar.selectionIndicatorImage = image
}
并添加此扩展程序
extension UIImage{
//Draws the top indicator by making image with filling color
class func drawTabBarIndicator(color: UIColor, size: CGSize, onTop: Bool) -> UIImage {
let indicatorHeight = size.height
let yPosition = onTop ? 0 : (size.height - indicatorHeight)
UIGraphicsBeginImageContextWithOptions(size, false, 0)
color.setFill()
UIRectFill(CGRect(x: 0, y: yPosition, width: size.width, height: indicatorHeight))
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image!
}
}
如果您的 UIViewController 是可旋转的,请将其放入您的 UITabBarViewController 以更正 TabBar 高度。
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
tabBar.sizeToFit()
}
这对我有用。
[self.tabBar.bottomAnchor constraintEqualToAnchor:self.view.layoutMarginsGuide.bottomAnchor].active = YES;
我只在 iOS 11.0 和 12.0 以下遇到这个外观问题。
我有一个继承自 UITabBar 的 CustomTabBar class。
我重写了如下的框架方法:
- (CGRect)frame{
return self.bounds;
}
它在大多数 iOS 版本 11.0 *
中解决了这个问题
虽然我的回答晚了,但我向您保证,如果您在 iphone x、xs 或最大屏幕上遇到任何此类问题,请确保您上传的图片尺寸必须符合高度 = 宽度 * 48pxHeight.
在尝试了一些解决方案后,对我有用的是将以下行添加到 viewDidLoad:
[self.tabBar.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor].active = YES;
Jonah 和 Mehul Thakkar 的回答为我指明了正确的方向。
注意:我在情节提要中只有一个空白的标签栏控制器。标签栏图像和视图控制器是使用 tabBarItem
属性设置的(例如,视图控制器上的 tabBarItem.title
)。
我的应用程序在测试 iPhone X 时遇到问题。我不确定如何调整这个问题,以及如何不让它成为非 iPhone 的问题X尺寸。这似乎只是 iPhone X 模拟器上的问题。
invalidateIntrinsicContentSize of UITabBar in viewWillLayoutSubviews 可能对你有帮助。
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
self.tabBar.invalidateIntrinsicContentSize()
}
"File inspector" 从 Xcode 故事板右侧开始,启用安全区域指南布局以支持您在 iPhone
中的应用受限 -
如果您将底部 space 与 "Bottom Layout Guide" 一起使用,则会出现此问题。
解法:
关于 superview 的底部 space。这将 100% 完美。
我的解决方案是自定义 UITabBar 高度设置,如下所示:
override func viewWillLayoutSubviews() {
var tabFrame = tabBar.frame
tabFrame.size.height = 60
tabFrame.origin.y = self.view.frame.size.height - 60
tabBar.frame = tabFrame
}
删除它,标签栏将在 iPhone X 上正确显示。
这对我有用,因为我正在使用选择图像。
tabBar.selectionIndicatorImage = UIImage.imageWithColor(color: UIColor.NewDesignColor.yellow, size: tabBarItemSize).resizableImage(withCapInsets: UIEdgeInsets.init(top: 0, left: 0, bottom: 20, right: 0))
添加底部插图对我的情况有帮助。 希望这也适用于您。 谢谢
对于 iOS 11.3 这对我有用:
func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
tabBar.invalidateIntrinsicContentSize()
}
我遇到了类似的问题。我在 viewDidLoad() 中设置了 selectionIndicatorImage。将代码移至 viewDidLayoutSubviews() 解决了我的问题。
使用以下代码创建一个单独的文件:
extension UITabBar {
override open func sizeThatFits(_ size: CGSize) -> CGSize {
super.sizeThatFits(size)
guard let window = UIApplication.shared.keyWindow else {
return super.sizeThatFits(size)
}
var sizeThatFits = super.sizeThatFits(size)
sizeThatFits.height = window.safeAreaInsets.bottom + 40
return sizeThatFits
}
}
只需将 UITabBar 的底部与超级视图对齐,而不是与安全区域对齐。如果将它对齐到安全区域,它将是这样的:
并且当与父视图对齐时,它将正确显示:
我认为这是因为 Apple 为标签栏项目提供了默认的底部边距,如果它位于 iPhone X 上,因为他们希望将标签栏扩展到屏幕底部以避免浮动栏.
按照以下指南设置 UITabbar selectionIndicatorImage。
- UITabBar.appearance().selectionIndicatorImage = #YOUR_IMAGE
- 确保您的图片高度为 48。
tabbar selectionIndicatorImage默认高度为49,但在iPhoneX中设置图片高度等于48。
在 iOS 12.1 我已经通过覆盖 UITabBar 子类中的 safeAreaInsets 解决了这个问题:
class TabBar: UITabBar {
private var cachedSafeAreaInsets = UIEdgeInsets.zero
override var safeAreaInsets: UIEdgeInsets {
let insets = super.safeAreaInsets
if insets.bottom < bounds.height {
cachedSafeAreaInsets = insets
}
return cachedSafeAreaInsets
}
}
iOS 13.0 以上,
class TabBar: UITabBar {
private var cachedSafeAreaInsets = UIEdgeInsets.zero
let keyWindow = UIApplication.shared.connectedScenes
.filter { [=11=].activationState == .foregroundActive }
.compactMap { [=11=] as? UIWindowScene }
.first?.windows
.filter { [=11=].isKeyWindow }
.first
override var safeAreaInsets: UIEdgeInsets {
if let insets = keyWindow?.safeAreaInsets {
if insets.bottom < bounds.height {
cachedSafeAreaInsets = insets
}
}
return cachedSafeAreaInsets
}
}
有 UITabBar
子类解决了我所有关于 iPhone X iOS 11
/ iOS 12
class TabBar: UITabBar {
private var _safeAreaInsets = UIEdgeInsets.zero
private var _subviewsFrames: [CGRect] = []
@available(iOS 11.0, *)
override func safeAreaInsetsDidChange() {
super.safeAreaInsetsDidChange()
if _safeAreaInsets != safeAreaInsets {
_safeAreaInsets = safeAreaInsets
invalidateIntrinsicContentSize()
superview?.setNeedsLayout()
superview?.layoutSubviews()
}
}
override func sizeThatFits(_ size: CGSize) -> CGSize {
var size = super.sizeThatFits(size)
if #available(iOS 12.0, *) {
let bottomInset = safeAreaInsets.bottom
if bottomInset > 0 && size.height < 50 && (size.height + bottomInset < 90) {
size.height += bottomInset
}
}
return size
}
override var frame: CGRect {
get {
return super.frame
}
set {
var tmp = newValue
if let superview = superview, tmp.maxY !=
superview.frame.height {
tmp.origin.y = superview.frame.height - tmp.height
}
super.frame = tmp
}
}
override func layoutSubviews() {
super.layoutSubviews()
let state = subviews.map { [=10=].frame }
if (state.first { [=10=].width == 0 } == nil) {
_subviewsFrames = state
} else {
zip(subviews, _subviewsFrames).forEach { (view, rect) in
view.frame = rect
}
}
}
}
Apple 现已在 iOS 12.1.1
中修复了此问题这看起来很疯狂,但我只需要在我的代码中删除这一行
self.view.layoutIfNeeded()
我只是猜测在屏幕上没有出现的视图上调用 layoutIfNeeded 会导致这个问题发生。 无论如何,@mohamed-ali 的解决方案也可以正常工作。非常感谢。
在viewDidLoad中添加这段代码
DispatchQueue.main.async {
let size = CGSize(width: self.tabBar.frame.width / numberOfTabsFloat,
height: self.tabBar.frame.height)
let image = UIImage.drawTabBarIndicator(color: UIColor.white,
size: size,
onTop: false)
UITabBar.appearance().selectionIndicatorImage = image
self.tabBar.selectionIndicatorImage = image
}
并添加此扩展程序
extension UIImage{
//Draws the top indicator by making image with filling color
class func drawTabBarIndicator(color: UIColor, size: CGSize, onTop: Bool) -> UIImage {
let indicatorHeight = size.height
let yPosition = onTop ? 0 : (size.height - indicatorHeight)
UIGraphicsBeginImageContextWithOptions(size, false, 0)
color.setFill()
UIRectFill(CGRect(x: 0, y: yPosition, width: size.width, height: indicatorHeight))
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image!
}
}
如果您的 UIViewController 是可旋转的,请将其放入您的 UITabBarViewController 以更正 TabBar 高度。
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
tabBar.sizeToFit()
}
这对我有用。
[self.tabBar.bottomAnchor constraintEqualToAnchor:self.view.layoutMarginsGuide.bottomAnchor].active = YES;
我只在 iOS 11.0 和 12.0 以下遇到这个外观问题。
我有一个继承自 UITabBar 的 CustomTabBar class。 我重写了如下的框架方法:
- (CGRect)frame{
return self.bounds;
}
它在大多数 iOS 版本 11.0 *
中解决了这个问题虽然我的回答晚了,但我向您保证,如果您在 iphone x、xs 或最大屏幕上遇到任何此类问题,请确保您上传的图片尺寸必须符合高度 = 宽度 * 48pxHeight.
在尝试了一些解决方案后,对我有用的是将以下行添加到 viewDidLoad:
[self.tabBar.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor].active = YES;
Jonah 和 Mehul Thakkar 的回答为我指明了正确的方向。
注意:我在情节提要中只有一个空白的标签栏控制器。标签栏图像和视图控制器是使用 tabBarItem
属性设置的(例如,视图控制器上的 tabBarItem.title
)。