【问题标题】:How to add border to UITabBar Badge?如何为 UITabBar 徽章添加边框?
【发布时间】:2018-11-29 10:58:30
【问题描述】:

如何在标签栏项中为徽章添加自定义边框?默认情况下,它在标签栏项目的右上角显示一个红点。我想给它加个边框。有一个选项可以更改徽章的颜色,但我找不到任何可以为徽章添加边框的东西。

【问题讨论】:

    标签: ios uitabbarcontroller uitabbaritem


    【解决方案1】:

    我认为没有官方的方法可以为徽章添加边框,但我也想这样做,最终我开发了自己的方法。我的解决方案更像是一个 hack,但它适用于 Xcode 10.1 和 iOS 12.1,不会让您的应用被拒绝,所以也许对您来说已经足够了。

    最难的部分是真正拿到徽章,这是带有 5 个标签的标签栏的视图层次结构:

    您可以看到,在我的项目中,最后一个选项卡包含徽章。但实际上它是第 4 个标签(带有index = 3 的标签),这是因为我在我的 UITabBarController 类中将第 4 个标签放在顶部,因此在显示更大值的情况下不会剪裁徽章。这是我获得徽章视图的方式(这是在 UITabBar 上下文中,所以 self 是 UITabBar):

    func badge(forIndex index: Int) -> UIView? {
        let sorted = self.subviews.sorted { (view1, view2) -> Bool in // I need to sort it by the frame.origin.x because the order in the subviews array cannot be trusted, I got random order there during my tests
            return view1.frame.origin.x < view2.frame.origin.x
        }
        let idx = index + 1 // the first view is actually a _UIBarBackground
        guard let barItemView = sorted[safe: idx] else {
            print("\(#file):\(#function):\(#line): Could not find a subview with index \(idx) in \(self)")
            return nil
        }
        if barItemView.subviews.count == 3 { // this is a hack, but I could not find a better way to get the badge without using private interfaces
            let view = barItemView.subviews.last
            return view
        }
        return nil
    }
    

    这为您提供了徽章视图,并且在最难(和最丑陋)的部分后面,我们现在可以添加边框(或像我在项目中所做的那样更改位置):

    if let badgeView = badge(forIndex: index) {
        // I found that it's easier to transform the layer here instead of the view, because it's instantaneous
        let badgeViewLayer = badgeView.layer
        badgeViewLayer.transform = CATransform3DMakeTranslation(BadgeTranslationX, BadgeTranslationY, 1) // you can change the position of the badge with this
    
        guard let badgeViewImageView = badgeView.subviews.first else {
            print("\(#file):\(#function):\(#line): No image view inside the badge view")
            return
        }
    
        badgeViewImageView.clipsToBounds = true // this is important, otherwise you may get artifacts when working with rounded corners etc.
        let layer = badgeViewImageView.layer
        layer.borderColor = UIColor.white.cgColor
        layer.borderWidth = 2
        layer.cornerRadius = 8
    }
    

    这是您使用上述代码得到的结果:

    当然,颜色可以是任何颜色:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多