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

后端 未结 4 1544
走了就别回头了
走了就别回头了 2020-12-09 19:18

I wanna use a thick line at the bottom of a UITabbarItems as a selection indicator. Due to the fact that the App must work on different phone sizes, I cannot use a image as

相关标签:
4条回答
  • 2020-12-09 19:42

    You can do it with add custom image, that will be created in your code, to selectionIndicatorImage on your UITabBar object. For example you can create extension for UIImage class like this:

    extension UIImage {
        func createSelectionIndicator(color: UIColor, size: CGSize, lineWidth: CGFloat) -> UIImage {
            UIGraphicsBeginImageContextWithOptions(size, false, 0)
            color.setFill()
            UIRectFill(CGRectMake(0, size.height - lineWidth, size.width, lineWidth))
            let image = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            return image
        }
    }
    

    And call it in your first loaded ViewController like this:

    class FirstViewController: UIViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            let tabBar = self.tabBarController!.tabBar
            tabBar.selectionIndicatorImage = UIImage().createSelectionIndicator(UIColor.blueColor(), size: CGSizeMake(tabBar.frame.width/CGFloat(tabBar.items!.count), tabBar.frame.height), lineWidth: 2.0)
        }
    
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
            // Dispose of any resources that can be recreated.
        }
    }
    

    In this case result will be like this:

    0 讨论(0)
  • 2020-12-09 19:47

    Swift 3:

    extension UIImage {
        func createSelectionIndicator(color: UIColor, size: CGSize, lineHeight: CGFloat) -> UIImage {
            UIGraphicsBeginImageContextWithOptions(size, false, 0)
            color.setFill()
            UIRectFill(CGRect(origin: CGPoint(x: 0,y :size.height - lineHeight), size: CGSize(width: size.width, height: lineHeight)))
            let image = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            return image!
        }
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        let tabBar = self.tabBarController!.tabBar
        tabBar.selectionIndicatorImage = UIImage().createSelectionIndicator(color: UIColor.blue, size: CGSize(width: tabBar.frame.width/CGFloat(tabBar.items!.count), height: tabBar.frame.height), lineHeight: 2.0)
    }
    
    0 讨论(0)
  • 2020-12-09 19:58

    Swift 4.x
    Xcode 10.x

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

    Use

    tabBar.selectionIndicatorImage = UIImage().createSelectionIndicator(color: BLUE, size: CGSize(width: tabBar.frame.width/CGFloat(tabBar.items!.count), height:  tabBar.frame.height), lineWidth: 2.0)
    
    0 讨论(0)
  • 2020-12-09 19:59

    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)
      }
      }
      
    0 讨论(0)
提交回复
热议问题