111

Normally on each tab of a UITabBar you have a small image and a title naming the tab. The image is positioned/centred towards the top of the tab to accommodate the title underneath. My question is: if you want to have a tabBar with just an image and no title is there a way to move the image down so it centers better within the tab?

I am using (see below) currently:

[tabBarItem setFinishedSelectedImage:tabSelected withFinishedUnselectedImage:tabUnselected];

but would prefer to use to larger image with no title, at the moment if I make the image bigger than about 70pixels@2x it starts edging off the top of the UITabBar whilst leaving a lot of unused space at the bottom.

Marcus Adams
  • 53,009
  • 9
  • 91
  • 143
fuzzygoat
  • 26,573
  • 48
  • 165
  • 294

11 Answers11

195

Try adjusting tabBarItem's imageInsets (for moving the icon image) and setting the controllers title to nil (so no title is displayed). Put something like this to -init or -viewDidLoad method in view controller:

Objective-C

self.tabBarItem.imageInsets = UIEdgeInsetsMake(6, 0, -6, 0);
self.title = nil;

Swift

self.tabBarItem.imageInsets = UIEdgeInsets(top: 6, left: 0, bottom: -6, right: 0)
self.title = nil

UITabBarItem is a subclass of UIBarItem which has UIEdgeInsets imageInsets property. Play a little with the insets until it looks good (depending on your tabbar icon images)

iPad specific adjustments

Tab Bar items on iPad are distributed horizontally (icon and label next to each other).

To adjust space between icon and label, adjust horizontal imageInsets instead of vertical ones.

Lukas Kukacka
  • 7,604
  • 2
  • 25
  • 50
155

You can do it via storyboard too. Select your tabbaritem, go to size inspector and assign the appropriate insets.

enter image description here

*Demonstrated on Xcode, Version 7.3.1 (7D1014)

Neil Galiaskarov
  • 5,015
  • 2
  • 27
  • 46
55

Make a subclass of UITabBarController, and in its viewDidLoad:

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self.viewControllers enumerateObjectsUsingBlock:^(UIViewController *vc, NSUInteger idx, BOOL *stop) {
        vc.tabBarItem.title = nil;
        vc.tabBarItem.imageInsets = UIEdgeInsetsMake(5, 0, -5, 0);
    }];
}

Swift 3:

for vc in self.viewControllers! {
    vc.tabBarItem.title = nil
    vc.tabBarItem.imageInsets = UIEdgeInsetsMake(5, 0, -5, 0)
}
Brian
  • 30,156
  • 15
  • 86
  • 87
  • this worked for me. just that for swift the method enumerateObjectsUsingBlock is not available any more – Junchao Gu Jun 21 '15 at 06:54
  • don't subclass, instead put this in to your AppDelegate – Laszlo Apr 22 '16 at 14:13
  • 1
    putting this snippet in `AppDelegate` also works, but it's not obviously better than subclassing it. You can have your own preference though :) – Brian Apr 25 '16 at 03:26
11

This worked for me

Swift 4

let array = tabBarController?.customizableViewControllers
for controller in array! {
    controller.tabBarItem.imageInsets = UIEdgeInsetsMake(5, 0, -5, 0)
}
Ahmadreza
  • 6,950
  • 5
  • 50
  • 69
10

If you're using Xamarin, this works:

screen.TabBarItem.ImageInsets = new UIEdgeInsets(5, 0, -5, 0);
screen.TabBarItem.Title = "";
Jelle
  • 365
  • 3
  • 11
2

SWIFT 3.0

You can set image lnsets, set top,left,bottom and right according desing.

self.tabBarItem.imageInsets = UIEdgeInsets(top: 5, left: 0, bottom: 0, right: 0)
krish
  • 3,856
  • 2
  • 24
  • 28
2

For iOS 11 you need to override TraitCollection method apart from setting ImageInsets. Please add the method in your subclassed UITabBarController class

public override UITraitCollection TraitCollection {
 get {
  return UITraitCollection.FromHorizontalSizeClass(horizontalSizeClass: UIUserInterfaceSizeClass.Compact);
 }
}
Prashant
  • 244
  • 2
  • 16
  • Good tip that helped me solve an issue related to the image position for tab bar item on iPad and iOS 11. But it's too harsh to override the trait collection at the view controller level, it's better to subclass the UITabBar class and override the traitCollection property there. Also returning a trait collection with only the horizontal class, will drop other trait collection properties. `return UITraitCollection(traitsFrom: [ super.traitCollection, UITraitCollection(horizontalSizeClass: .compact)])` did the trick for me. – Emmanuel Paris Jan 09 '18 at 20:30
2

In Swift 4.2, UIEdgeInsetsMake is depricated, instead we should use UIEdgeInsets,

let array = tabBarController?.customizableViewControllers
    for controller in array! {
        controller.tabBarItem.imageInsets = UIEdgeInsets(top: 5, left: 0, bottom: -5, right: 0)
    }
Bappaditya
  • 9,494
  • 3
  • 20
  • 29
1

These didn't work for me, the only solution that worked was setting the alignmentRectInsets when adding the image. Here's what mine looked like:

let newsView = NewsViewController()
let newsIcon = UITabBarItem(title: nil, image: UIImage(systemName: "newspaper")?.withAlignmentRectInsets(UIEdgeInsets(top: 8.5, left: 0, bottom: -8.5, right: 0)), tag: 0)
newsView.tabBarItem = newsIcon
let viewControllers = [newsNavController]
self.viewControllers = viewControllers
Michael
  • 748
  • 8
  • 11
1

In 2021, Objective-C

I try all the approaches, no one is worked. Eventually I found that is because of using SF symbol as tabbaritem image. If I replace it with custom image, things worked.

    NSArray *tabItems = [self.tabBar items];
    // set tabItem icon, remove blue image with render mode set.
    UIImage *image1 = [[UIImage imageNamed:@"myIcon"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
    
    // set title offset
    [tabItems[0] setTitlePositionAdjustment:UIOffsetMake(0, 20)];
    [tabItems[1] setTitlePositionAdjustment:UIOffsetMake(-20, 20)];
    [tabItems[2] setTitlePositionAdjustment:UIOffsetMake(20, 20)];
    [tabItems[3] setTitlePositionAdjustment:UIOffsetMake(0, 20)];

    // set image offset
    [tabItems[0] setImageInsets:UIEdgeInsetsMake(0, 0, -30, 0)];
    ...

For uitabbaritem image resolution, 50x50px for @2x, and 75x75px for @3x.

Zhou Haibo
  • 1,681
  • 1
  • 12
  • 32
1
//On tabbar viewDidload
override func viewDidLoad() {
    super.viewDidLoad()
    self.delegate = self
    
    tabBar.items![0].imageInsets = UIEdgeInsets(top: 6, left: 0, bottom: -6, right: 0)
}
  • how can i achieve this using swiftui? inside onAppear/init() i tried to do something like this UITabBar.appearance().items?[0].imageInsets = UIEdgeInsets(top: 6, left: 0, bottom: -6, right: 0) but that doesnt seem to work, any pointers? – Natto May 22 '23 at 05:34