更改UITabBar高度

76

我将UITabBarController用作根视图,该应用程序支持iOS 6及以上版本。项目类层次结构如下。

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

我在上述层次结构中的一个UIViewController中使用以下代码更改UITabBar的高度(该UIViewController位于UINavigationController中)。

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的高度,以实现类似于这样的效果?

输入图像描述


1
你可以更改默认的tabbar高度,但是你需要子类化UITabBarController,我以前做过这个,我在http://stackoverflow.com/questions/16740824/tab-bar-with-large-icons/16742065#16742065上写下了它。 - limon
发现这个可行 -> https://dev59.com/yGAf5IYBdhLWcg3wqUON#27494228 - keji
我认为你也可以只设置一个高度约束,这对我来说似乎有效。 - giovannipds
24个回答

143

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

您需要将以下代码添加到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
}

8
你的 viewWillLayoutSubviews 实现应该调用 super,通常作为第一行代码。 - Dklionsk
1
@Dklionsk 它可以调用 super,但不一定要这样做:此方法的默认实现什么也不做。(来自文档) - dmirkitanov
1
@dmirkitanov 这对于 UIViewController 是正确的,但对于 UITabBarController 可能不是正确的。 - Alex Pretzlav
Swift 3.0版本。导入基础框架和UI框架。类NavigationTabBarController: UITabBarController { let kBarHeight = CGFloat(80)override func viewWillLayoutSubviews() { var tabFrame = self.tabBar.frame //self.TabBar是你的TabBar的IBOutlet tabFrame.size.height = kBarHeight tabFrame.origin.y = self.view.frame.size.height - kBarHeight self.tabBar.frame = tabFrame }} - SaundersB
27
viewWillLayoutSubviews更改为viewDidLayoutSubviews可在iOS 13中使用。 - arlomedia
显示剩余6条评论

44

测试过在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 类:

Tab Bar Identity Inspector

然后在 Attributes Inspector (⌥⌘4) 中设置所需的 Height(大于0.0):

Tab Bar Attributes Inspector


你有没有考虑制作一个扩展(extension)而不是自定义类(Custom Class)。然后在扩展中指定@IBInspectable var height。如果可能的话,可以避免指定自定义类的第二步骤。 - Vipin Johney
2
在iPhone X上运行效果不佳。您需要使用此解决方案:https://dev59.com/M1YO5IYBdhLWcg3wL-vY#50346008 - Jindřich Skeldal

42

适用于Swift 3.0和Swift 4.0

iPhone X之前的默认标签栏高度为49pt

iPhone X的默认选项卡栏高度为83pt

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

  1. 获取UITabBar的默认高度:

  2. fileprivate lazy var defaultTabBarHeight = { tabBar.frame.size.height }()
    
  3. 调整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
        }
    

1
当视图发生变化时(如状态栏隐藏),这将使选项卡栏跳动。 - jakedunc
2
@jakedunc 我认为这是S. Azzopardi所说的问题,我将这段代码放在viewDidLayoutSubviews()中,它可以正常工作。 - ioio007
@ioio007 你好,这个程序在iPhone X和其他设备上运行正常。但是当我增加UIView的高度时,底部会被遮盖住,不受增加值的影响。请帮我找到解决方案。 - Saravanan
嗨,@Saravanan,看起来你的问题与以下答案下面的评论相同:https://dev59.com/FGAg5IYBdhLWcg3w5edk#44293634 - ioio007
在UITabBarViewController类中,将viewWillLayoutSubviews更改为viewDidLayoutSubviews。它会正常工作。对我来说它已经起作用了。 - Sahil Omer

41

对于 iOS 8.2Xcode 6.2 Swift 语言:

为您的 UITabBarController (类型为 UITabBarController) 创建一个 "DNMainTabVC.swift"(DeveloperNameMainTabViewController.swift 文件),并将其连接到故事板视图控制器。

添加以下行:

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”是什么意思?如何连接?谢谢! - Rock
1
你进入你的Storyboard。点击viewcontroller,然后转到Xcode右侧的“视图检查器”。在第三个选项卡下(看起来像报纸),您将找到一个“类”标签。占位符灰色文本应该说“UIViewController”。在那里,您输入您的viewcontroller文件的名称,例如“DNMainTabVC”。之后,“DNMainTabVC”旁边的框中会出现一个箭头。这意味着viewcontroller文件(.swift)与storyboard元素相连接。无论您在“DNMainTabVC.swift”中编写什么都会影响storyboard VC。 - MB_iOSDeveloper
@MS_iOSDeveloper,我明白了。所以这是选择自定义类。我以为你是指某种“拖动”操作来“连接”。我弄懂了。谢谢你的解释! - Rock

30

创建一个自定义的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

希望这个能行。


1
太好了!这是我看到的最好的解决方案。因为它不直接修改框架,而是改变了预期的大小!太棒了! - vilanovi
1
这个答案在内部视图控制器的自动布局方面没有副作用,应该被接受的答案。 - Taku
当我们在程序中以编程方式创建选项卡控制器时,我们该如何使用它? - Bhavin Bhadani

15

Swift 4

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

11

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
@jaytrixz 有同样的问题。如果你把Alvin的代码放在viewDidLoad()中,空白处会出现,但如果你按照建议将其放在viewWillLayoutSubviews()中,则不会出现。 - Kqtr

11

Swift 3.0+ 将以下代码中的200替换为您期望的高度。

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

小心!在运行时使用哪种方法实现 - UITabbar类的原始方法还是您的扩展方法,其行为是未定义的。 - Aleksandr Larionov
像魔法一样运作良好。 - rockdaswift
你不应该使用Swift扩展(或Objective-C类别)来覆盖方法。如果你想使用sizeThatFits()方法,请使用这个解决方案:https://dev59.com/FGAg5IYBdhLWcg3w5edk#46425620 - Roberto

11

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.connectedScenes
        .compactMap({$0 as? UIWindowScene})
        .first?.windows
        .filter({$0.isKeyWindow}).first 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 元素。当我尝试通过重写 tabBar 属性来设置我的 tabBarControllertabBar 时,它显示一个空的 tabBar(没有项目)。 - mauricioconde
1
请注意,guard let window = UIApplication.shared.keyWindow 在 iOS 13.0 中已经被弃用,请进行更新。 - Chandan Jee

7

在之前的答案基础上并更新至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()中。


这个可以运行,但是由于高度增加,一些视图被选项卡栏挡住了。有什么解决办法吗? - Dan
嘿@john。你是否将它们固定在安全区底部边缘? - Kqtr
嗨@Kqtr,我将视图固定在底部视图上,如下所示:NSLayoutConstraint(item: tableView, attribute: NSLayoutAttribute.bottom, relatedBy: NSLayoutAttribute.equal, toItem: view, attribute: NSLayoutAttribute.bottom, multiplier: 1, constant: 0)我发现了safeAreaInsetssafeAreaLayoutGuide,但这个功能只适用于iOS 11及以上版本。这是你所指的吗? - Dan
是的,你可以尝试在iOS 11及以上版本中使用view.safeAreaLayoutGuide.bottomAnchor,其中view是VC的主视图。而在iOS 11以下版本中,则将其固定到VC的bottomLayoutGuide.topAnchor上。目前,你正在使用视图的底部,而视图可能会低于这些底部指南。 - Kqtr
@john 另外,为了方便起见,我在一个VC扩展中创建了4个变量,提供了简单的约束使用(左右和顶部重复):extension UIViewController { var safeBottomAnchor: NSLayoutYAxisAnchor { if #available(iOS 11.0, *) { return view.safeAreaLayoutGuide.bottomAnchor } else { return bottomLayoutGuide.topAnchor } } } - Kqtr
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接