Add a Line as a Selection Indicator to a Uitabbaritem in Swift

Add a line as a selection indicator to a UITabbarItem in Swift

I solved my problem.

Features of this tiny code snippet:

  • width is dynamic
  • it is animated
  • it is a lot more customizable for future features

    class FirstViewController: UIViewController {

    let rectShape = CAShapeLayer()
    let indicatorHeight: CGFloat = 5
    var indicatorWidth: CGFloat!
    let indicatorBottomMargin: CGFloat = 2
    let indicatorLeftMargin: CGFloat = 2

    override func viewDidLoad() {
    super.viewDidLoad()

    // setup tabbar indicator
    rectShape.fillColor = UIColor.redColor().CGColor
    indicatorWidth = view.bounds.maxX / 2 // count of items
    self.tabBarController!.view.layer.addSublayer(rectShape)
    self.tabBarController?.delegate = self

    // initial position
    updateTabbarIndicatorBySelectedTabIndex(0)
    }

    func updateTabbarIndicatorBySelectedTabIndex(index: Int) -> Void
    {
    let updatedBounds = CGRect( x: CGFloat(index) * (indicatorWidth + indicatorLeftMargin),
    y: view.bounds.maxY - indicatorHeight,
    width: indicatorWidth - indicatorLeftMargin,
    height: indicatorHeight)

    let path = CGPathCreateMutable()
    CGPathAddRect(path, nil, updatedBounds)
    rectShape.path = path
    }
    }

    extension FirstViewController: UITabBarControllerDelegate {

    func tabBarController(tabBarController: UITabBarController, didSelectViewController viewController: UIViewController) {
    updateTabbarIndicatorBySelectedTabIndex(tabBarController.selectedIndex)
    }
    }

iOS : How to add Underline in UITabBarItem

Please try this one.
I have used in my application once and hope it will help you too.

This is how I have created Tab bar programmatically:

      UITabBarController *tab = [[UITabBarController alloc]init];
ViewController1 *v1 = [[ViewController1 alloc]init];
ViewController1 *v2 = [[ViewController1 alloc]init];
ViewController1 *v3 = [[ViewController1 alloc]init];
ViewController1 *v4 = [[ViewController1 alloc]init];

tab.viewControllers = [NSArray
arrayWithObjects:v1,v2,v3,v4,nil];

[[tab.tabBar.items objectAtIndex:0]setImage:[UIImage imageNamed:@""]];
[[tab.tabBar.items objectAtIndex:1]setImage:[UIImage imageNamed:@""]];
[[tab.tabBar.items objectAtIndex:2]setImage:[UIImage imageNamed:@""]];
[[tab.tabBar.items objectAtIndex:3]setImage:[UIImage imageNamed:@""]];
int divide = 4;
if([UIDevice currentDevice].userInterfaceIdiom ==UIUserInterfaceIdiomPad)
divide =6;
}
UIView *view = [[UIView alloc]initWithFrame:CGRectMake(tab.tabBar.frame.origin.x,tab.tabBar.frame.origin.y, self.view.frame.size.width/divide, 56)];

UIImageView *border = [[UIImageView alloc]initWithFrame:CGRectMake(view.frame.origin.x,view.frame.size.height-6, self.view.frame.size.width/divide, 6)];
border.backgroundColor = “your color”;
[view addSubview:border];
[tab.tabBar setSelectionIndicatorImage:[self changeViewToImage:view]];

//This is the method that will draw the underline
-(UIImage ) changeViewToImage : (UIView ) viewForImage {
UIGraphicsBeginImageContext(viewForImage.bounds.size);
[viewForImage.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
}

UITab Bar - Selection Indicator Image - Change Position

You have to create translucent selectedTab (see zip file) with top white line and height should be 48 Pixel

check this link https://www.dropbox.com/s/j38mqj8sd0qgv8f/selectedTab.zip?dl=0

  [[UITabBar appearance] setSelectionIndicatorImage:[UIImage imageNamed:@"selectedTab.png"]];
[[UITabBar appearance] setBarTintColor:[UIColor blackColor]];

Results:
Sample Image

how to make UITabBar selection indicator image fill the whole space?

If you want to set red image on tab selection i will recommend you to set background color of active tab bar item, as per my opinion whenever you can do your stuff with the coding why to use image so its better to set selection color rather then image.
You can achieve that using following code.

    // set red as selected background color
let numberOfItems = CGFloat(tabBar.items!.count)
let tabBarItemSize = CGSize(width: tabBar.frame.width / numberOfItems, height: tabBar.frame.height)
tabBar.selectionIndicatorImage = UIImage.imageWithColor(color: UIColor.red, size: tabBarItemSize).resizableImage(withCapInsets: .zero)

// remove default border
tabBar.frame.size.width = self.view.frame.width + 4
tabBar.frame.origin.x = -2

Making use of the following extension of UIImage:

extension UIImage {
class func imageWithColor(color: UIColor, size: CGSize) -> UIImage {
let rect: CGRect = CGRect(x: 0, y: 0, width: size.width, height: size.height)
UIGraphicsBeginImageContextWithOptions(size, false, 0)
color.setFill()
UIRectFill(rect)
let image: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return image
}
}

Hope that will help you.

OR ANOTHER WAY IS HERE :

In your tabBarController, you can set the default UITabBar tintColor, barTintColor, selectionIndicatorImage (cheating a bit here) and renderingMode of the images, see comments below:

    class MyTabBarController: UITabBarController, UINavigationControllerDelegate {
...
override func viewDidLoad() {
...
// Sets the default color of the icon of the selected UITabBarItem and Title
UITabBar.appearance().tintColor = UIColor.red
// Sets the default color of the background of the UITabBar
UITabBar.appearance().barTintColor = UIColor.black

// Sets the background color of the selected UITabBarItem (using and plain colored UIImage with the width = 1/5 of the tabBar (if you have 5 items) and the height of the tabBar)
UITabBar.appearance().selectionIndicatorImage = UIImage().makeImageWithColorAndSize(color: UIColor.blue, size: CGSize(width: tabBar.frame.width/5, height: tabBar.frame.height))

// Uses the original colors for your images, so they aren't not rendered as grey automatically.
for item in (self.tabBar.items)! {
if let image = item.image {
item.image = image.withRenderingMode(.alwaysOriginal)
}
}
}
...
}

And you will want to extend the UIImage class to make the plain colored image with the size you need:

 extension UIImage {
func makeImageWithColorAndSize(color: UIColor, size: CGSize) -> UIImage {
UIGraphicsBeginImageContextWithOptions(size, false, 0)
color.setFill()
UIRectFill(CGRect(x: 0, y: 0, width: size.width, height: size.height))
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image!
}
}

UITabBar selection indicator image is not taking whole size of tabBar height in ObjectiveC

This should help you customise the indicator image however you need. You just set class of Tab Bar to this class in the interface builder

class MyCustomTabBar: UITabBar
{
var didInit = false
override func layoutSubviews()
{
super.layoutSubviews()

if didInit == false
{
didInit = true
for subview in subviews {
// can't hookup to subviews, so do layer.sublayers
subview.layer.addObserver(self, forKeyPath: "sublayers", options: .New, context: nil)
}
}
}

deinit
{
for subview in subviews
{
subview.layer.removeObserver(self, forKeyPath: "sublayers")
}
}

override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>)
{
// layer.delegate is usually the parent view
if let l = object as? CALayer, tbButton = l.delegate as? UIView where tbButton.window != nil
{
for v in tbButton.subviews
{
if String(v.dynamicType) == "UITabBarSelectionIndicatorView" {
// do whatever needed with v, this is your indicator view
}
}
}
}
}

Add Top border to selected TabBar

You can use the function to create borders on any side -

enum Side: String {
case top, left, right, bottom
}

extension UIImage {
func createSelectionIndicator(color: UIColor, size: CGSize, lineThickness: CGFloat, side: Side) -> UIImage {
var xPosition = 0.0
var yPosition = 0.0
var imgWidth = 2.0
var imgHeight = 2.0
switch side {
case .top:
xPosition = 0.0
yPosition = 0.0
imgWidth = size.width
imgHeight = lineThickness
case .bottom:
xPosition = 0.0
yPosition = size.height - lineThickness
imgWidth = size.width
imgHeight = lineThickness
case .left:
xPosition = 0.0
yPosition = 0.0
imgWidth = lineThickness
imgHeight = size.height
case .right:
xPosition = size.width - lineThickness
yPosition = 0.0
imgWidth = lineThickness
imgHeight = size.height
}
UIGraphicsBeginImageContextWithOptions(size, false, 0)
color.setFill()
UIRectFill(CGRect(x: xPosition, y: yPosition, width: imgWidth, height: imgHeight))
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image!
}
}

tabBar.selectionIndicatorImage = UIImage().createSelectionIndicator(color: BLUE, size: CGSize(width: tabBar.frame.width/CGFloat(tabBar.items!.count), height: tabBar.frame.height), lineThickness: 2.0, side: .top)

Let me know if this was useful or you need any other help.
Happy Coding :)

UITabBar appearance setSelectionIndicatorImage does not work on first launch iOS7

Setting the selection indicator image for the tab bar directly once again, apart from doing it via appearance, worked for me!

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
....

UITabBarController *tabBarContr = (UITabBarController *)self.window.rootViewController;
...
[[UITabBar appearance] setSelectionIndicatorImage:[UIImage imageNamed:@"tab_bar_selection_indicator.png"]];

// iOS7 hack: to make selectionIndicatorImage appear on the selected tab on the first app run
[[tabBarContr tabBar] setSelectionIndicatorImage:[UIImage imageNamed:@"tab_bar_selection_indicator.png"]];

return YES;
}


Related Topics



Leave a reply



Submit