-
-
Save calt/7ea29a65b440c2aa8a1a to your computer and use it in GitHub Desktop.
// Does not work on iOS 14.0 or later, keeping the gist just for reference. | |
extension UITabBar { | |
override open func sizeThatFits(size: CGSize) -> CGSize { | |
super.sizeThatFits(size) | |
var sizeThatFits = super.sizeThatFits(size) | |
sizeThatFits.height = 71 | |
return sizeThatFits | |
} | |
} |
Solution that works across all devices including iPhone X. You may need to add a check for iOS 11 availability in the guard statement if developing for iOS 10 or lower.
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
}
very well,This solution is great!
Great job! working like a charm
thanks for solution!!!!
Hi,
The solution seems to be perfect. But where do I need to call this extension from? Is it from viewwilllayoutsubviews?
Thanks
Replace public
with open
.
extension UITabBar {
override open func sizeThatFits(size: CGSize) -> CGSize {
super.sizeThatFits(size)
var sizeThatFits = super.sizeThatFits(size)
sizeThatFits.height = 71
return sizeThatFits
}
}
Thanks, It worked nicely.
Thanks, you saved my day :)
It works at iOS 13.3 but didn't work at iOS 13.4 due to UITabBar.sizeThatFits() is never called
It works at iOS 13.3 but didn't work at iOS 13.4 due to UITabBar.sizeThatFits() is never called
The same for me. Have you got any solution?
Same problem here!
I have found a solution for iOS 13.4 that doesn't require too much to be changed.
First step is to change your code (I'll use the example above, but your code might be slightly different if you've done something custom);
Change from this;
extension UITabBar {
override open func sizeThatFits(size: CGSize) -> CGSize {
super.sizeThatFits(size)
var sizeThatFits = super.sizeThatFits(size)
sizeThatFits.height = 71
return sizeThatFits
}
}
To this;
class CustomTabBar : UITabBar {
override open func sizeThatFits(_ size: CGSize) -> CGSize {
super.sizeThatFits(size)
var sizeThatFits = super.sizeThatFits(size)
sizeThatFits.height = 71
return sizeThatFits
}
}
Then in your storyboard, click your "Tab Bar Controller"'s tab bar and change the class from UiTabBar to CustomTabBar. This ensures that sizeThatFits
is called.
If you've created your UITabBarController programmatically, you can set custom class for UITabBar class like this :
init() {
super.init(nibName: nil, bundle: nil)
object_setClass(self.tabBar, CustomTabbar.self)
/* some stuff here */
}
That's a bit weird because Apple don't let us set a custom instance of UITabBar.
If you've created your UITabBarController programmatically, you can set custom class for UITabBar class like this :
init() { super.init(nibName: nil, bundle: nil) object_setClass(self.tabBar, CustomTabbar.self) /* some stuff here */ }
That's a bit weird because Apple don't let us set a custom instance of UITabBar.
@RemiRodrigues thx, you saved me a lot of time
I have found a solution for iOS 13.4 that doesn't require too much to be changed.
First step is to change your code (I'll use the example above, but your code might be slightly different if you've done something custom);
Change from this;
extension UITabBar { override open func sizeThatFits(size: CGSize) -> CGSize { super.sizeThatFits(size) var sizeThatFits = super.sizeThatFits(size) sizeThatFits.height = 71 return sizeThatFits } }
To this;
class CustomTabBar : UITabBar { override open func sizeThatFits(_ size: CGSize) -> CGSize { super.sizeThatFits(size) var sizeThatFits = super.sizeThatFits(size) sizeThatFits.height = 71 return sizeThatFits } }
Then in your storyboard, click your "Tab Bar Controller"'s tab bar and change the class from UiTabBar to CustomTabBar. This ensures that
sizeThatFits
is called.
Thanks @jcrooke This is working awesomely.
I hope I'm missing something, but there's no way for me to make any of those solutions work.
In my project, UITabViewController is an initial controller and no matter what I do, the default size of the tab bar is loaded first and it changes to the new height defined with the override of sizeThatFits shortly after.
So I load the tab bar twice and it has this buggy look when the height of the tab bar changes.
I'm running iOS 14.1 and I' have tried older devices before iPhone X too in a simulator.
Any help is appreciated.
nothing from mentioned here works for me in iOS 14+
Same here unfortunately
Work for me in iOS 14+, and others
class WeiTabBarController: UITabBarController {
init() {
super.init(nibName: nil, bundle: nil)
object_setClass(self.tabBar, WeiTabBar.self)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
class WeiTabBar: UITabBar {
override func sizeThatFits(_ size: CGSize) -> CGSize {
var sizeThatFits = super.sizeThatFits(size)
sizeThatFits.height = 120
return sizeThatFits
}
}
}
@RemiRodrigues Thanks, you really saved me a lot of headaches.
@Wei18 Thank you man it works like a charm!
@Wei18 you are a champ
@Wei18 Thank you that's work for me too on iOS 14+
@Wei18 thank you! still working for swift 5+
New to Swift over here! - Trying to understand how I would use this in Views. Here is my Tabs View `struct Tabs: View {
@EnvironmentObject private var themeManager: ThemeManager
@Environment(.colorScheme) var mode: ColorScheme
@State private var selectedTab = 0
var body: some View {
TabView(selection: $selectedTab) {
DetailsView()
.tabItem {
Text("Home")
TabImage(name: "misty", size: CGSize(width: 42, height: 42))
}
.tag(0)
SettingsView()
.tabItem {
Text("Socials")
TabImage(name: "laptop", size: CGSize(width: 42, height: 42))
}
.tag(1)
}
.onAppear(perform: {
CustomTabBar().sizeThatFits(CGSize(width: 300, height: 400))
})
.accentColor(AppColors(mode: mode).jnjBorder)
}
}`
With the extension class CustomTabBar : UITabBar { override open func sizeThatFits(_ size: CGSize) -> CGSize { super.sizeThatFits(size) var sizeThatFits = super.sizeThatFits(size) sizeThatFits.height = 71 return sizeThatFits } }
However my emulator is still showing all clumped up. I've tried a few other ways to try and increase the height but nothing seems to work!
After testing many ways, this one works best for me:
final class CustomTabBar: UITabBar {
private let topLineLayer: CALayer = {
let obj = CALayer()
obj.backgroundColor = UIColor.appBorder.cgColor
return obj
}()
private let tabBarAppearance: UITabBarAppearance = {
let obj = UITabBarAppearance()
obj.stackedLayoutAppearance.normal.titleTextAttributes = [
.font: UIFont.interFont(ofSize: 12.sizeW, weight: .medium),
]
return obj
}()
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
topLineLayer.frame.size = CGSize(width: bounds.width, height: 1)
}
override func sizeThatFits(_ size: CGSize) -> CGSize {
var sizeThatFits = super.sizeThatFits(size)
sizeThatFits.height = 64 + safeAreaInsets.bottom // 64 is custom height
return sizeThatFits
}
}
// MARK: - Setup
extension CustomTabBar {
private func setup() {
standardAppearance = tabBarAppearance
tintColor = .appLabel
unselectedItemTintColor = .appStroke
layer.addSublayer(topLineLayer)
}
}
final class CustomTabBarController: UITabBarController {
private let customTabBar = CustomTabBar()
override func loadView() {
super.loadView()
setValue(customTabBar, forKey: "tabBar")
}
}
Thanks!