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

帅比萌擦擦* 提交于 2019-12-18 02:42:39

问题


I have a UITabBarController where I use this code to set selection indicator image:

let selectedBG = UIImage(named:"tabbarbgtest.png")?.resizableImageWithCapInsets(UIEdgeInsetsMake(0, 0, 0, 0))
UITabBar.appearance().selectionIndicatorImage = selectedBG

But the image does not fill the whole space - see image below:

The image is just a red square with a solution on 82x49px, but with a wider image it still does not fill the whole space. Hope you guys can help - thanks.


回答1:


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!
    }
}



回答2:


As of 2017, honestly Piyush's answer didn't work for me. After a couple of days searching for another solution, I found mine - by subclassing 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
        }
    
    }
    



回答3:


To support iPhone X(below code works for all versions), write your code in viewDidLayoutSubviews().

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    let tabWidth = (tabBar.frame.width/CGFloat(tabBar.items!.count))
    let tabHeight = tabBar.frame.height
    self.tabBar.selectionIndicatorImage = imageWithColor(color: UIColor.white, size: CGSize(width: tabWidth, height: tabHeight)).resizableImage(withCapInsets: UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0))
 }

Source: https://github.com/Ramotion/animated-tab-bar/issues/191




回答4:


you should take a look at this to make the tabbarbgtest.png resizable, then assign the image to selectionIndicatorImage, you can even do this in the storyboard editor.




回答5:


This relatively simple solution in objective c worked for me for iPhone X, wouldn't be hard to convert to swift:

CGFloat bottomPadding = 0;

if (@available(iOS 11.0, *)) {
  UIWindow *window = UIApplication.sharedApplication.keyWindow;
  bottomPadding = window.safeAreaInsets.bottom;
}

[UITabBar.appearance setSelectionIndicatorImage:[UIImage imageWithColor:[UIColor lightGrayColor] 
          andBounds:CGRectMake(0, 0, self.tabBar.frame.size.width/5, self.tabBar.frame.size.height + bottomPadding)]];



回答6:


This is an adaptation on Glenn's solution above...

    import UIKit

    class BaseTabBarController: UITabBarController {

        var tabBarBounds: CGRect? {
            didSet {
                guard tabBarBounds != oldValue else { return }
                updateSelectionIndicatorColor(UIColor.green)
            }
        }

        override func viewWillLayoutSubviews() {
            super.viewWillLayoutSubviews()
            tabBarBounds = tabBar.bounds
        }

        func updateSelectionIndicatorColor(_ tintColor: UIColor) {
            guard let tabBarItems = self.tabBar.items else { return }

            let tabWidth = tabBar.bounds.width
            let tabHeight = tabBar.bounds.height
            let tabSize = CGSize(width: tabWidth / CGFloat(tabBarItems.count), height: tabHeight)
            var selectionImage = UIImage(color: tintColor, size: tabSize)

            UIGraphicsBeginImageContext(tabSize)
            selectionImage?.draw(in: CGRect(x: 0, y: 0, width: tabSize.width, height: tabSize.height))
            selectionImage = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()

            tabBar.selectionIndicatorImage = selectionImage
        }

    }

    public extension UIImage {
        public convenience init?(color: UIColor, size: CGSize = CGSize(width: 1, height: 1)) {
            let rect = CGRect(origin: .zero, size: size)
            UIGraphicsBeginImageContextWithOptions(rect.size, false, 0.0)
            color.setFill()
            UIRectFill(rect)
            let image = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()

            guard let cgImage = image?.cgImage else { return nil }
            self.init(cgImage: cgImage)
        }
    }


来源:https://stackoverflow.com/questions/33868139/how-to-make-uitabbar-selection-indicator-image-fill-the-whole-space

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!