更改 UITabBar 高度

Posted

技术标签:

【中文标题】更改 UITabBar 高度【英文标题】:Change UITabBar height 【发布时间】:2014-05-27 11:25:20 【问题描述】:

我使用UITabBarController 作为根视图,并且应用支持 ios 6 及更高版本。项目类层次结构如下。

UITabBarController
  - tab1
    - UINavigationController
      - UIViewController
      - UIViewController
      .
      .
  - tab2
    - UINavigationController
      - UIViewController
      - UIViewController
      .
      .
      .
  - tab3
    - UIViewController
  - tab4
    - UIViewController

我使用下面的代码在上面的层次结构中的一个 UIViewControllers(在 UINavigationController 内)中更改 UITabBar 的高度。

CGRect tabbarFrame = self.tabBarController.tabBar.frame;
tabbarFrame.size.height += 60;
self.tabBarController.tabBar.frame = tabbarFrame;

但它没有改变高度。 UITabBar 以默认高度显示。尽管记录其值会打印更改的值,如下所示。

<UITabBar: 0xb528f60; frame = (0 431; 320 109); autoresize = W+TM; layer = <CALayer: 0xb529080>>

我怎样才能改变UITabBar 的高度来达到这样的效果:?

【问题讨论】:

你可以改变默认的tabbar高度,但是你需要继承UITabBarController,我之前做过,我写在***.com/questions/16740824/tab-bar-with-large-icons/… 发现这行得通 -> ***.com/a/27494228/1484378 我想你也可以只设置一个高度限制,它似乎对我有用。 【参考方案1】:

我遇到了这个问题,我能够解决它。

您必须将以下代码添加到UITabBarController 类的子类中。

const CGFloat kBarHeight = 80;

- (void)viewWillLayoutSubviews 
    [super viewWillLayoutSubviews];

    CGRect tabFrame = self.tabBar.frame; //self.TabBar is IBOutlet of your TabBar
    tabFrame.size.height = kBarHeight;
    tabFrame.origin.y = self.view.frame.size.height - kBarHeight;
    self.tabBar.frame = tabFrame;

斯威夫特:

override func viewWillLayoutSubviews() 
    super.viewWillLayoutSubviews()

    tabBar.frame.size.height = kBarHeight
    tabBar.frame.origin.y = view.frame.height - kBarHeight

【讨论】:

您能再详细说明一下吗?我已将此代码添加到扩展 TabBarController 的类中,但什么也没发生 你的viewWillLayoutSubviews 实现应该调用super,可能是第一行。 @Dklionsk 它可以调用super,但它不必:The default implementation of this method does nothing.(来自文档) @dmirkitanov 对于UIViewController 是正确的,但对于UITabBarController 可能不是正确的 viewWillLayoutSubviews 更改为 viewDidLayoutSubviews 适用于 iOS 13。【参考方案2】:

对于iOS 8.2Xcode 6.2 Swift 语言:

为您的UITabBarControllerUITabBarController 类型)创建一个“DNMainTabVC.swift”(DeveloperNameMainTabViewController.swift 文件)并将其连接到您的故事板 VC。

添加以下行:

override func viewWillLayoutSubviews() 
    var tabFrame = self.tabBar.frame
    // - 40 is editable , the default value is 49 px, below lowers the tabbar and above increases the tab bar size
    tabFrame.size.height = 40
    tabFrame.origin.y = self.view.frame.size.height - 40
    self.tabBar.frame = tabFrame

这对我有用。

【讨论】:

@MS_iOSDeveloper:“将它连接到 Storyboard VC”是什么意思?如何连接它?谢谢! 你去你的故事板。点击viewcontroller,到Xcode右侧的“view inspector”。在第三个选项卡(看起来像报纸)下,您会找到“班级”标签。占位符灰色文本应显示“UIViewController”。在那里输入视图控制器文件的名称,例如。 “DNMainTabVC”。之后,“DNMainTabVC”旁边的框中将出现一个箭头。这意味着视图控制器文件 (.swift) 已连接到情节提要元素。您在“DNMainTabVC.swift”中写的任何内容都会对故事板 VC 产生影响。 @MS_iOSDeveloper 知道了。所以它正在选择自定义类。我以为你的意思是一些“拖动”动作来“连接”。我得到它的工作。谢谢你的解释!【参考方案3】:

Swift3.0、Swift 4.0 兼容

Pre-iPhone X 默认标签栏高度:49pt

iPhone X 默认标签栏高度:83pt

支持包括 iPhone X 屏幕尺寸在内的所有 iOS 设备的通用解决方案如下所示:

    捕获UITabBar的默认高度:

    fileprivate lazy var defaultTabBarHeight =  tabBar.frame.size.height ()
    

    调整UITabBar的高度:

        override func viewWillLayoutSubviews() 
            super.viewWillLayoutSubviews()
    
            let newTabBarHeight = defaultTabBarHeight + 16.0
    
            var newFrame = tabBar.frame
            newFrame.size.height = newTabBarHeight
            newFrame.origin.y = view.frame.size.height - newTabBarHeight
    
            tabBar.frame = newFrame
        
    

【讨论】:

这将使 tabBar 在动画视图更改时跳转(如隐藏状态栏) @jakedunc 我认为这是 S. Azzopardi 所说的问题,我将这段代码放在 viewDidLayoutSubviews() 中,它工作正常。 @ioio007 您好,这适用于 iPhone x 和其他设备。但是当我增加高度时,UIView 底部会根据增加值隐藏。帮我解决。 嗨@Saravanan,看起来您的问题与此答案下方的评论相同:***.com/a/44293634/7144402 UITabBarViewController 类中的 viewWillLayoutSubviews 改为 viewDidLayoutSubviews 就可以了。它对我有用。【参考方案4】:

XCode 9.0Swift 4

中测试

正如之前的答案所建议的那样——继承UITabBar并覆盖sizeThatFits,但将height标记为@IBInspectable,因此可以在Interface Builder中进行设置:

import UIKit

class CustomTabBar : UITabBar 
    @IBInspectable var height: CGFloat = 0.0

    override func sizeThatFits(_ size: CGSize) -> CGSize 
        var sizeThatFits = super.sizeThatFits(size)
        if height > 0.0 
            sizeThatFits.height = height
        
        return sizeThatFits
    

Identity Inspector (⌥⌘3) 中为UITabBar 设置CustomTabBar 类:

然后在属性检查器(⌥⌘4)中设置所需的Height(大于0.0):

【讨论】:

您是否考虑过制作一个扩展而不是自定义类。然后在扩展名中指定@IBInspectable var height。如果可能的话,可以避免指定自定义类的第二步。 在 iPhone X 上效果不佳。你必须使用这个解决方案:***.com/a/50346008/1702909【参考方案5】:

创建一个UITabBar类型的自定义子类,然后实现以下方法:

@implementation CustomTabBar
#define kTabBarHeight = // Input the height we want to set for Tabbar here
-(CGSize)sizeThatFits:(CGSize)size

    CGSize sizeThatFits = [super sizeThatFits:size];
    sizeThatFits.height = kTabBarHeight;

    return sizeThatFits;

@end

希望这会奏效。

【讨论】:

太棒了!到目前为止,这是我见过的最好的解决方案。因为它不直接修改框架,而是改变预期的大小!太好了! 这个答案在内部视图控制器的自动布局方面没有副作用,应该是公认的答案。 当我们以编程方式制作标签栏控制器时如何使用它?【参考方案6】:

斯威夫特 4

extension UITabBar 
    override open func sizeThatFits(_ size: CGSize) -> CGSize 
        var sizeThatFits = super.sizeThatFits(size)
        sizeThatFits.height = 60 // adjust your size here
        return sizeThatFits
    

【讨论】:

【参考方案7】:

Swift 2.0:

var tabBar:UITabBar?

override func viewWillLayoutSubviews() 
    var tabFrame: CGRect = self.tabBar!.frame
    tabFrame.size.height = 60
    tabFrame.origin.y = self.view.frame.size.height - 60
    self.tabBar!.frame = tabFrame

【讨论】:

在 Swift 2.2 中不再工作。它在原始标签栏框架下方留下了一个清晰的空间 @jaytrixz 有同样的问题。如果你把 Alvin 的代码放在 viewDidLoad() 中会出现空白,但如果你按照建议将它放在 viewWillLayoutSubviews() 中则不会出现【参考方案8】:

Swift 3.0+ 在下面的代码中将 200 替换为您想要的高度。

   extension UITabBar 
        override open func sizeThatFits(_ size: CGSize) -> CGSize 
            return CGSize(width: UIScreen.main.bounds.width, height: 200)
        
    

【讨论】:

小心!关于在运行时使用哪种方法实现的行为未定义 - 原始来自 UITabbar 类或您的扩展 像魅力一样工作 您应该使用 Swift 扩展(或 Objective-C 类别,就此而言)覆盖方法。如果您想使用sizeThatFits() 方法,请改用此解决方案:***.com/a/46425620/538491【参考方案9】:

Swift 4 & 兼容 iphone x

class CustomTabBar : UITabBar 

@IBInspectable var height: CGFloat = 65.0

override open func sizeThatFits(_ size: CGSize) -> CGSize 
    guard let window = UIApplication.shared.keyWindow else 
        return super.sizeThatFits(size)
    
    var sizeThatFits = super.sizeThatFits(size)
    if height > 0.0 

        if #available(iOS 11.0, *) 
            sizeThatFits.height = height + window.safeAreaInsets.bottom
         else 
            sizeThatFits.height = height
        
    
    return sizeThatFits


【讨论】:

我在 extension 中使用了这个方法定义,因为我正在以编程方式创建所有 UI 元素,并且当我尝试通过覆盖 @987654325 来设置 tabBarControllertabBar 时@属性,它显示一个空的tabBar(没有项目) guard let window = UIApplication.shared.keyWindow 在 iOS 13.0 中已弃用。所以请更新。【参考方案10】:

在以前的答案的基础上为 Swift 3 更新。

子类 UITabController 并确保将新的自定义类分配给 UITabController 的 Identity Inspector。

Swift 3.0

class MainTabBarController: UITabBarController 

    override func viewWillLayoutSubviews() 
        var newTabBarFrame = tabBar.frame

        let newTabBarHeight: CGFloat = 60
        newTabBarFrame.size.height = newTabBarHeight
        newTabBarFrame.origin.y = self.view.frame.size.height - newTabBarHeight

        tabBar.frame = newTabBarFrame
    

警告:如果您的标签栏下方有一个空白区域,请确保您确实将此代码放入了 viewWillLayoutSubviews() 而不是 viewDidLoad()。

【讨论】:

这可行,但是由于高度增加,一些视图被标签栏挡住了。知道如何解决这个问题吗? 嘿@john。您是否将它们固定在安全区域的底部边缘? 嗨@Kqtr,我将视图固定到底部视图,例如:NSLayoutConstraint(item: tableView, attribute: NSLayoutAttribute.bottom, relatedBy: NSLayoutAttribute.equal, toItem: view, attribute: NSLayoutAttribute.bottom, multiplier: 1, constant: 0) 我找到了safeAreaInsetssafeAreaLayoutGuide,但该功能仅适用于iOS 11 及更高版本。你指的是这个吗? 是的,您可以尝试在 iOS 11 及更高版本上使用 view.safeAreaLayoutGuide.bottomAnchor,其中 view 是 VC 的主视图。在 iOS 11 下,固定到 VC 的 bottomLayoutGuide.topAnchor。目前,您正在使用视图的底部,并且视图可能会低于这些底部参考线。 @john 也,仅供参考,为方便起见,我在 VC 扩展中创建了 4 个变量,提供了简单的使用约束(重复左右和顶部):扩展 UIViewController var safeBottomAnchor: NSLayoutYAxisAnchor if #available (iOS 11.0, *) return view.safeAreaLayoutGuide.bottomAnchor else return bottomLayoutGuide.topAnchor 【参考方案11】:

出于某种原因,@Rushikesh 的回答在 iOS 10 之前运行良好,但我在 iOS 11Swift 3.2 上遇到了一些问题>.

每次我触摸一个新标签时,tabBar 都会改变它的框架。

我通过将代码放入 viewDidLayoutSubviews() 函数而不是 viewWillLayoutSubviews() 来解决此问题

斯威夫特 3:

override func viewDidLayoutSubviews() 

    super.viewDidLayoutSubviews()
    var tabFrame            = tabBar.frame
    tabFrame.size.height    = 65
    tabFrame.origin.y       = view.frame.size.height - 65
    tabBar.frame            = tabFrame

【讨论】:

【参考方案12】:

Xamarin 实现:

public override void ViewWillLayoutSubviews()

    base.ViewWillLayoutSubviews();
    const float newTabBarHeight = 40f;
    TabBar.Frame = new CGRect(TabBar.Frame.X, TabBar.Frame.Y + (TabBar.Frame.Height - newTabBarHeight), TabBar.Frame.Width, newTabBarHeight);

【讨论】:

【参考方案13】:

使用安全区域编辑了 Kiarash Asar 的答案:

override func viewWillLayoutSubviews() 
    super.viewWillLayoutSubviews()

    var safeAreaBottomInset: CGFloat = 0.0

    if #available(iOS 11.0, *) 
        safeAreaBottomInset = view.safeAreaInsets.bottom
    

    let newTabBarHeight: CGFloat = myDesiredHeight + safeAreaBottomInset

    var newFrame = tabBar.frame
    newFrame.size.height = newTabBarHeight
    newFrame.origin.y = view.frame.size.height - newTabBarHeight

    tabBar.frame = newFrame

【讨论】:

【参考方案14】:

您可以通过子类化来修改标签栏的高度。实际上我很久以前就这样做了。 xcode 6.0

override func sizeThatFits(_ size: CGSize) -> CGSize 
    return CGSize(width: super.sizeThatFits(size).width, height: 60)

这应该返回其默认宽度,高度为 60pts。

【讨论】:

【参考方案15】:

这也是一种方法

extension UITabBar 

override public func sizeThatFits(size: CGSize) -> CGSize 
    super.sizeThatFits(size)
    var sizeThatFits = super.sizeThatFits(size)
    sizeThatFits.height = 71 // or whatever height you need
    return sizeThatFits
    

【讨论】:

【参考方案16】:

适用于所有屏幕尺寸: 将 tabBarHeight 设置为(tabBar 的原始高度 - 20)这很重要,因此您可以稍后在 viewDidLayoutSubviews 中使用它,这也比硬编码您想要的大小更好。因为该尺寸可能不适用于所有屏幕。

窗口安全区域插图在标签栏高度的底部保持必要的填充,以保持与屏幕底部边缘的距离。

var tabBarHeight = CGFloat()

override func viewDidLoad() 
        super.viewDidLoad()
        tabBarHeight = self.tabBar.frame.height - 20
    

    override func viewDidLayoutSubviews() 
        super.viewDidLayoutSubviews()
        var tabFrame = self.tabBar.frame
        guard let window = UIApplication.shared.keyWindow else return
        tabFrame.size.height = tabBarHeight + window.safeAreaInsets.bottom
        self.tabBar.frame = tabFrame
    

【讨论】:

【参考方案17】:

Swift 5.3.1、XCode 11+、iOS 14:

import UIKit

class CustomTabBar: UITabBar 
    let height: CGFloat = 62
    
    override open func sizeThatFits(_ size: CGSize) -> CGSize 
        guard let window = UIApplication.shared.connectedScenes
                .filter($0.activationState == .foregroundActive)
                .map($0 as? UIWindowScene)
                .compactMap($0)
                .first?.windows
                .filter($0.isKeyWindow).first else 
            return super.sizeThatFits(size)
        

        var sizeThatFits = super.sizeThatFits(size)
        if #available(iOS 11.0, *) 
            sizeThatFits.height = height + window.safeAreaInsets.bottom
         else 
            sizeThatFits.height = height
        
        return sizeThatFits
    

【讨论】:

【参考方案18】:

只需在安全区域底部添加更多插图:

additionalSafeAreaInsets.bottom = 40

【讨论】:

这结合向下移动标签栏项目标题和图像,使它们居中可能是最简洁的解决方案。谢谢!【参考方案19】:

iPhoneX 有不同的高度,所以如果我们移动到较小的高度,那么 iPhoneX 中的标签栏形状会很糟糕

- (void)viewWillLayoutSubviews

    int requiredHeight = 55;
    CGRect tabFrame = self.tabBar.frame;
    if (tabFrame.size.height < requiredHeight)
    
        tabFrame.size.height = requiredHeight;
        tabFrame.origin.y = self.view.frame.size.height - requiredHeight;
        self.tabBar.frame = tabFrame;
    

【讨论】:

【参考方案20】:
class TabBarVC: UITabBarController 

    //MARK:- Variable
    let HEIGHT_TAB_BAR:CGFloat = 500

    override func viewDidLoad() 
        super.viewDidLoad()
    
        // Do any additional setup after loading the view.
    


    override func viewDidLayoutSubviews() 
        super.viewDidLayoutSubviews()
        var tabFrame = self.tabBar.frame
        tabFrame.size.height = HEIGHT_TAB_BAR
        tabFrame.origin.y = self.view.frame.size.height - HEIGHT_TAB_BAR
        self.tabBar.frame = tabFrame
    



对我来说工作得很好。

【讨论】:

【参考方案21】:

它帮助了我

override func viewDidLayoutSubviews() 
        super.viewWillLayoutSubviews()

        tabBar.frame.size.height = 60
        tabBar.frame.origin.y = view.frame.height - 60

【讨论】:

这与this other answer(和其他)中的解决方案相同。 在回答已有答案的旧问题时,请确保提供新颖的解决方案或比现有答案更好的解释。 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center。【参考方案22】:

对于 UITabBarController 子类

从 UITabBar 创建一个子类

class CustomTabBar : UITabBar 
    override open func sizeThatFits(_ size: CGSize) -> CGSize 
        super.sizeThatFits(size)
        var sizeThatFits = super.sizeThatFits(size)
        sizeThatFits.height = 200
        return sizeThatFits
    

并在构造函数中设置类

init() 
    super.init(nibName: nil, bundle: nil)
    object_setClass(self.tabBar, CustomTabBar.self)

【讨论】:

以上是关于更改 UITabBar 高度的主要内容,如果未能解决你的问题,请参考以下文章

UINavigationBar + UITabBar 的可用屏幕高度

计算UITabBar的高度

iOS 5 中的 UITabBar 高度

Objective-C中带有圆角和自定义高度的UITabbar

iOS 8、iOS 9、iOS 10 和 iOS 11 上的 UITabBar 的高度是多少?

swift UITabBar在Swift中具有自定义高度