4

So I have a .png that's 428x176 px:

enter image description here

I want to use it as a tab bar background image for when an item is in the selected state. The problem is that the image is too big. So now, I'm exploring the different resolution suffixes: @1x, @2x, @3x. But regardless of which I append to the image filename, the image remains too big for the tab bar item's background, although it does get smaller as I increase the resolution factor. How do I determine what the correct dimensions for this image should be?

Keep in mind that this is a background image for when any particular UITabBarItem is in the selected state. It is meant to be the entire width and height of the UITabBarItem. My tab bar will have three items laid across the width of the screen.

Update:

A lot of answers are providing swift based solutions, but what I'm asking for is what dimensions my image should be in pixels, in other words, what sized images should I be including in my bundle, so that the image will fit in the tab bar at all screen sizes. I imagine that since a UITabBar by default expects a UIImage for its selectionIndicatorImage field and not a UIImageView that there must be a solution that doesn't involve hacking around the UITabBar and adding a UIImageView as a subview of it and managing what position the image view should be in, manually, based on which UITabBarItem is currently selected.

shoe
  • 952
  • 1
  • 20
  • 44

6 Answers6

5

Making my answer for this question how to make UITabBar selection indicator image fill the whole space? as reference:

Subclass the UITabBarController

It works for multiple devices even with rotation.

Notes:

  1. Make your images' rendering mode as Original.
  2. Assign this class below to your UITabBarController in your Storyboard or as your base class if you're doing your screen programmatically.

    //
    //  BaseTabBarController.swift
    //  MyApp
    //
    //  Created by DRC on 1/27/17.
    //  Copyright © 2017 PrettyITGirl. All rights reserved.
    //
    
    import UIKit
    
    class BaseTabBarController: UITabBarController {
    
        let numberOfTabs: CGFloat = 4
        let tabBarHeight: CGFloat = 60
    
        override func viewWillAppear(_ animated: Bool) {
            super.viewWillAppear(animated)
    
            updateSelectionIndicatorImage()
        }
    
        override func viewWillLayoutSubviews() {
            super.viewWillLayoutSubviews()
    
            updateSelectionIndicatorImage()
        }
    
        func updateSelectionIndicatorImage() {
            let width = tabBar.bounds.width
            var selectionImage = UIImage(named:"myimage.png")
            let tabSize = CGSize(width: width/numberOfTabs, height: tabBarHeight)
    
            UIGraphicsBeginImageContext(tabSize)
            selectionImage?.draw(in: CGRect(x: 0, y: 0, width: tabSize.width, height: tabSize.height))
            selectionImage = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
    
            tabBar.selectionIndicatorImage = selectionImage
        }
    
    }
    
Glenn Posadas
  • 12,555
  • 6
  • 54
  • 95
3

There's no clear cut answer for this as the tab bar itself isn't of fixed size on various iOS versions and various iOS devices.

Starting iOS 11, tab bar will have smaller height and titles will move to right in landscape mode.

So the idea is to have a stretchable image that can be stretched along all all edges - top/leading/bottom/trailing.

For your reference - http://macoscope.com/blog/stretchable-images-using-interface-builder/

Here are few images from above blog post to help make it clear - enter image description here enter image description here enter image description here

Hope this helps.

Tarun Tyagi
  • 9,364
  • 2
  • 17
  • 30
  • yes, but for any given device it is of fixed size, and because we can determine the device in the app, there is a clear-cut answer – shoe Jul 27 '17 at 23:00
2

Use the below two lines.

self.tabBarController.tabBar.autoresizesSubviews = NO;
self.tabBarController.tabBar.clipsToBounds = YES;

Xcode works with point, not pixels, so the width will always be 320. In the case of retina display one point is 2x2 pixels and in normal mode it is 1x1.

I think the height for the tab bar should be 320x49 for normal and 640x98 for retina.

the retina image should have the same name as the normal one with the @2x at the end.

Rename your image to tabbarBack@2x.png. This is called pixel doubling for the Retina Display.

Without the @2x iOS doesn't know that it should apply a scale factor and it will be used as it is and though it should be halved.

  • tabbarBack.png (45 px or so)

  • tabbarBack@2x.png

    [[[self tabBarController] tabBar] setBackgroundImage:[UIImage imageNamed:@"tabbarBack.png"]];

Community
  • 1
  • 1
Nikhlesh Bagdiya
  • 4,316
  • 1
  • 19
  • 29
0

Have you tried with adding imageView as subview of tabbar

var bgView: UIImageView = UIImageView(image: UIImage(named: "background.png"))
bgView.frame = CGRectMake(0, 420, 320, 60)//you might need to modify this frame to your tabbar frame
self.view.addSubview(bgView)

If we talk about height & width of tabbar ,it is 320*49 / 640*98 @2x for standard tabbar. so if you want to keep same dimension try with these width/height ratio.

Ellen
  • 5,180
  • 1
  • 12
  • 16
  • this is *only* for when the button is in the selected state, and there are multiple items – shoe Jul 27 '17 at 22:55
0

To add to Tarun Tyagi's answer: If you add the image to the asset store you can also do visual slicing with the system tools.

  1. Create an asset catalog
  2. Drag & Drop your image into the asset catalog.
  3. Select that image in the asset catalog and click on the "Show Slicing" button on the bottom right Slicing Button
  4. Click on "Start Slicing" and slice that image

Jan
  • 1,032
  • 11
  • 26
-1

Try resizing the image to the tab bar size. Or Add an imageView to the tabBar as subview, and then use the image in that imageView. Subclass the TabBarController and add imageview there:

class YourTabBarController: UITabBarController {

override func viewDidLoad() {
    super.viewDidLoad()

    let backgroundImage = UIImageView(image: UIImage(named: "gray background"))
    backgroundImage.frame = backgroundImage.bounds
    self.view.addSubview(backgroundImage)


}
Abdullah Md. Zubair
  • 3,312
  • 2
  • 30
  • 39