You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

新手求教:如何从UI Button创建带徽章的UIBarButtonItem类

实现带徽章的顶部栏按钮(SSBadgeButton完整方案)

Hey there! 作为iOS新手想做带徽章的导航栏按钮,你找的SSBadgeButton思路完全靠谱,我帮你把这个类的代码补全,再加上清晰的使用说明,这样你就能快速搞定想要的效果啦~

完整的SSBadgeButton实现代码

import UIKit

class SSBadgeButton: UIButton {
    // 徽章标签
    private let badgeLabel = UILabel()
    
    // 徽章内容,设置后自动更新UI
    var badge: String? {
        didSet {
            addBadgeToButton(badge: badge)
        }
    }
    
    // 自定义配置属性
    public var badgeBackgroundColor = UIColor.red {
        didSet {
            badgeLabel.backgroundColor = badgeBackgroundColor
        }
    }
    
    public var badgeTextColor = UIColor.white {
        didSet {
            badgeLabel.textColor = badgeTextColor
        }
    }
    
    public var badgeFont = UIFont.systemFont(ofSize: 12, weight: .bold) {
        didSet {
            badgeLabel.font = badgeFont
        }
    }
    
    public var badgeCornerRadius: CGFloat = 8 {
        didSet {
            badgeLabel.layer.cornerRadius = badgeCornerRadius
            badgeLabel.clipsToBounds = true
        }
    }
    
    // 徽章相对于按钮右上角的偏移量
    public var badgeOffset: CGPoint = CGPoint(x: 8, y: -8) {
        didSet {
            updateBadgePosition()
        }
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupBadgeLabel()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        setupBadgeLabel()
    }
    
    // 初始化徽章标签的基础配置
    private func setupBadgeLabel() {
        badgeLabel.translatesAutoresizingMaskIntoConstraints = false
        badgeLabel.textAlignment = .center
        badgeLabel.isHidden = true // 默认隐藏徽章
        addSubview(badgeLabel)
        
        // 设置初始约束(后续会根据偏移量调整)
        NSLayoutConstraint.activate([
            badgeLabel.topAnchor.constraint(equalTo: topAnchor),
            badgeLabel.trailingAnchor.constraint(equalTo: trailingAnchor),
            badgeLabel.widthAnchor.constraint(greaterThanOrEqualToConstant: 16),
            badgeLabel.heightAnchor.constraint(equalToConstant: 16)
        ])
    }
    
    // 更新徽章内容和显示状态
    private func addBadgeToButton(badge: String?) {
        guard let badgeText = badge, !badgeText.isEmpty else {
            badgeLabel.isHidden = true
            return
        }
        
        badgeLabel.text = badgeText
        badgeLabel.isHidden = false
        updateBadgePosition()
    }
    
    // 根据偏移量调整徽章位置
    private func updateBadgePosition() {
        badgeLabel.transform = CGAffineTransform(translationX: badgeOffset.x, y: badgeOffset.y)
    }
}

关键功能说明

  • 自动更新UI:通过badge属性的didSet监听,只要设置徽章内容,就会自动显示/隐藏徽章并更新文本
  • 高度可定制:你可以自定义徽章的背景色、文字颜色、字体、圆角大小,甚至调整徽章相对于按钮的偏移位置
  • 自适应布局:徽章宽度会根据文本自动调整(最小宽度16pt),保证数字多的时候也能正常显示

如何在导航栏使用

在你的ViewController的viewDidLoad方法里添加以下代码,就能快速创建带徽章的导航栏按钮:

override func viewDidLoad() {
    super.viewDidLoad()
    
    // 创建徽章按钮
    let notificationButton = SSBadgeButton(type: .system)
    notificationButton.setImage(UIImage(systemName: "bell.fill"), for: .normal)
    notificationButton.tintColor = .black
    
    // 设置徽章属性
    notificationButton.badge = "5" // 显示未读数量
    notificationButton.badgeBackgroundColor = .systemOrange
    notificationButton.badgeCornerRadius = 10 // 更圆润的徽章
    notificationButton.badgeOffset = CGPoint(x: 6, y: -6) // 微调位置
    
    // 添加到导航栏右侧
    navigationItem.rightBarButtonItem = UIBarButtonItem(customView: notificationButton)
}

额外小技巧

如果想要实现“徽章显示小红点(无数字)”的效果,只需要设置badge = "",然后把badgeCornerRadius设为徽章高度的一半(比如8pt),就能得到圆形小红点啦~

内容的提问来源于stack exchange,提问作者Agung

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:56:49