Пользовательский элемент BarButtonItem: добавьте красную точку в верхнем правом углу, Swift 4 IOS - PullRequest
0 голосов
/ 19 декабря 2018

Я хочу добавить / установить непрочитанный флаг в виде красной точки в правом верхнем углу на UIbarButtonItem, см. Прилагаемое изображение для этого

enter image description here

Что следуетя делаю, чтобы добавить / установить красную точку на панели кнопок?Как только пользователь нажмет на элемент, я хочу удалить красную точку.

Ответы [ 2 ]

0 голосов
/ 19 декабря 2018

Я написал собственный класс кнопок панели, чтобы справиться с этим, где я использую CAShapeLayer, чтобы нарисовать точку сверху UIBarButtonItem.

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

И это будет выглядеть так:

Unread Button

0 голосов
/ 19 декабря 2018

UIButton Subclass

Хорошо, давайте начнем с создания пользовательского UIButton подкласса

class ButtonWithBadge: UIButton {
}

Теперь давайте создадим UIView для представления красной точки

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

Затем переопределите init для этого подкласса и внутри добавьте это badgeView в верхний правый угол вашей кнопки: установите его ограничения (справа и сверху, равные якорям, ширине и высоте кнопки, равные удвоенному значению cornerRadius badgeView)

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

Теперь давайте создадим некоторый метод, который скрывает или показывает badgeView в зависимости от isRead значения

func setBadge() {
    badgeView.isHidden = isRead
}

Теперь у нас есть функция, верно?Так что давайте вызовем эту функцию в конце init и в didSet из isRead variable

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 добавьте barButton к UINavigationBar и расположите его так, как вы хотите:

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)
    ])

}

Теперь, когда вам нужно, вы можете легко изменитьbarButton isRead переменная и красная точка исчезает или появляется

barButton.isRead = true

enter image description here


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)
        ])

    }
    ...
}
...