【问题标题】:Custom BarButtonItem Item: Add red dot on top right corner, Swift 4 IOS自定义 BarButtonItem 项:在右上角添加红点,Swift 4 IOS
【发布时间】:2018-12-19 07:16:29
【问题描述】:

我想在UIbarButtonItem 的右上角添加/设置未读标志为红点,请参阅附图

我应该怎么做才能在条形按钮项目上添加/设置红点? 一旦用户点击项目然后我想删除红点。

【问题讨论】:

标签: ios swift uinavigationbar uinavigationitem


【解决方案1】:

UIButton 子类

好的,让我们开始创建自定义UIButton 子类

class ButtonWithBadge: UIButton {
}

现在让我们创建UIView 来代表红点

let badgeView: UIView = {
    let view = UIView()
    view.layer.cornerRadius = 3
    view.backgroundColor = .red
    return view
}()

然后为这个子类覆盖init并在里面添加这个badgeView到你的按钮的右上角:设置它的约束(右和上等于按钮的锚点,宽度和高度是badgeView的cornerRadius的两倍值)

override init(frame: CGRect) {
    super.init(frame: frame)

    addSubview(badgeView)
    badgeView.translatesAutoresizingMaskIntoConstraints = false
    NSLayoutConstraint.activate([
        badgeView.rightAnchor.constraint(equalTo: rightAnchor, constant: 3),
        badgeView.topAnchor.constraint(equalTo: topAnchor, constant: 3),
        badgeView.heightAnchor.constraint(equalToConstant: badgeView.layer.cornerRadius*2),
        badgeView.widthAnchor.constraint(equalToConstant: badgeView.layer.cornerRadius*2)
    ])
}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

接下来创建代表按钮当前状态的变量:

var isRead: Bool = false

现在让我们创建一些方法,根据isRead 的值隐藏或取消隐藏badgeView

func setBadge() {
    badgeView.isHidden = isRead
}

现在我们有了函数,对吧?所以让我们在init 的末尾和isRead 变量的didSet 中调用这个函数

class ButtonWithProperty: UIButton {

var isRead: Bool = false {
    didSet {
        setBadge()
    }
}

override init(frame: CGRect) {
    ...
    setBadge()
}

添加到 ViewController

首先为按钮和视图创建变量

lazy var barButton: ButtonWithProperty = {
    let button = ButtonWithProperty()
    ... // set color, title, target, etc.
    return button
}()

现在例如在viewDidLoad 中添加这个barButtonUINavigationBar 并按照你想要的方式放置它:

override func viewDidLoad() {
    super.viewDidLoad()
    ...
    guard let navigationBar = self.navigationController?.navigationBar else { return }

    navigationBar.addSubview(barButton)
    barButton.translatesAutoresizingMaskIntoConstraints = false
    NSLayoutConstraint.activate([
        barButton.rightAnchor.constraint(equalTo: navigationBar.rightAnchor, constant: -20),
        barButton.bottomAnchor.constraint(equalTo: navigationBar.bottomAnchor, constant: -6)
    ])

}

现在,当您需要时,您可以轻松更改barButtonisRead 变量,红点消失或出现

barButton.isRead = true


class ButtonWithProperty: UIButton {

    var isRead: Bool = false {
        didSet {
            setBadge()
        }
    }

    lazy var badgeView: UIView = {
        let view = UIView()
        view.layer.cornerRadius = 3
        view.backgroundColor = .red
        return view
    }()

    override init(frame: CGRect) {
        super.init(frame: frame)

        addSubview(badgeView)
        badgeView.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            badgeView.rightAnchor.constraint(equalTo: rightAnchor, constant: 3),
            badgeView.topAnchor.constraint(equalTo: topAnchor, constant: 3),
            badgeView.heightAnchor.constraint(equalToConstant: badgeView.layer.cornerRadius*2),
            badgeView.widthAnchor.constraint(equalToConstant: badgeView.layer.cornerRadius*2)
        ])

        setBadge()
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    func setBadge() {
        badgeView.isHidden = isRead
    }

}

ViewController 内部:

class ViewController: UIViewController {

    lazy var barButton: ButtonWithProperty = {
        let button = ButtonWithProperty()
        ... // color, title, target, etc.
        return button
    }()

    ...

    override func viewDidLoad() {
        super.viewDidLoad()
        ...
        guard let navigationBar = self.navigationController?.navigationBar else { return }

        navigationBar.addSubview(barButton)
        barButton.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            barButton.rightAnchor.constraint(equalTo: navigationBar.rightAnchor, constant: -20),
            barButton.bottomAnchor.constraint(equalTo: navigationBar.bottomAnchor, constant: -6)
        ])

    }
    ...
}

【讨论】:

    【解决方案2】:

    我已经编写了一个自定义栏按钮类来处理这个问题,我使用CAShapeLayerUIBarButtonItem 上绘制一个点。

    // Custom Bar button
    class CustomBarButton: UIBarButtonItem
    {
        // Unread Mark
        private var unreadMark: CAShapeLayer?
    
        // Keep track of unread status
        var hasUnread: Bool = false
        {
            didSet
            {
                setUnread(hasUnread: hasUnread)
            }
        }
    
        // Toggles unread status
        private func setUnread(hasUnread: Bool)
        {
            if hasUnread
            {
                unreadMark            = CAShapeLayer();
                unreadMark?.path      = UIBezierPath(ovalIn: CGRect(x: (self.customView?.frame.width ?? 0) - 10, y: 5, width: 5, height: 5)).cgPath;
                unreadMark?.fillColor = UIColor.red.cgColor
                self.customView?.layer.addSublayer(unreadMark!)
            }
            else
            {
                unreadMark?.removeFromSuperlayer()
            }
    
        }
    }
    

    栏按钮项没有可用的图层属性,因此您需要使用自定义视图创建UIBarButtonItem

    // Bar button property
    var barButton:CustomBarButton!
    
    // Initialisation
    button       = UIButton(type: .custom)
    button.frame = CGRect(x: 0, y: 0, width: 70, height: 40)
    button.setTitle("Right", for: .normal)
    button.setTitleColor(UIColor.green, for: .normal)
    
    // Bar button
    barButton = CustomBarButton(customView: button)
    button.addTarget(self, action: #selector(toggleStatus(sender:)), for: UIControl.Event.touchUpInside)
    
    // Flexible space (Optional)
    let flexibleSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
    toolBar.items     = [flexibleSpace, barButton]
    

    IBAction 中,您可以使用hasUnread 属性切换状态:

    @objc func toggleStatus(sender: AnyObject)
    {
        barButton.hasUnread = !barButton.hasUnread
    }
    

    它看起来像:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-08-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多