Увеличение собственного размера UIButton, когда он содержится в UIBarButtonItem - PullRequest
1 голос
/ 04 июля 2019

Я создал подкласс UIButton, вид которого находится за пределами кнопки.

Выглядит как на скриншоте:

button

Как видите, значок находится за пределами кнопки.Его центр привязан к верхнему правому углу кнопки.

Проблема заключается в том, что когда кнопка помещается внутри UIBarButtonItem, значок обрезается.

Инспектор иерархии представлений показывает, почему:

viewhierarchy

Как мне сообщить UIBarButtonItem, что размер кнопки больше, чем сама кнопка?Какие свойства UIButton мне нужно переопределить?

Код, который я использую для кнопки:


import UIKit
import BadgeSwift

@objc public class BadgeButton: UIButton {
    private lazy var badge: BadgeSwift = {
        let b = BadgeSwift()
        b.textColor = .white
        b.insets = CGSize(width: 0, height: 0)
        b.font = UIFont.preferredFont(forTextStyle: .caption1)
        return b
    }()

    public override init(frame: CGRect) {
        super.init(frame: frame)
        commonInit()
    }

    required public init?(coder: NSCoder) {
        super.init(coder: coder)
        commonInit()
    }

    private func commonInit() {
        addSubview(badge)
        badge.text = "1"
    }

    public override func layoutSubviews() {
        super.layoutSubviews()
        clipsToBounds = false
        badge.sizeToFit()
        badge.center = center
        badge.center = CGPoint(x: bounds.origin.x + bounds.size.width, y: bounds.origin.y)
    }
}

Для представления значка я использую следующую библиотеку: BadgeSwiftБиблиотека

Ответы [ 2 ]

0 голосов
/ 04 июля 2019

Исправлено добавлением четкой границы вокруг значка:


import UIKit
import BadgeSwift

@objc public class BadgeButton: UIButton {
    private lazy var badge: BadgeSwift = {
        let b = BadgeSwift()
        b.textColor = .white
        b.borderWidth = 1
        b.borderColor = .clear
        b.font = UIFont.preferredFont(forTextStyle: .footnote)
        return b
    }()

    public var badgeText: String? {
        get {
            return badge.text
        }
        set {
            badge.text = newValue
        }
    }

    public override init(frame: CGRect) {
        super.init(frame: frame)
        commonInit()
    }

    required public init?(coder: NSCoder) {
        super.init(coder: coder)
        commonInit()
    }

    private func commonInit() {
        addSubview(badge)
        badge.text = "1"
    }

    public override func layoutSubviews() {
        super.layoutSubviews()
        clipsToBounds = false
        badge.sizeToFit()
        badge.center = CGPoint(x: bounds.origin.x + bounds.size.width, y: bounds.origin.y)
    }
}

0 голосов
/ 04 июля 2019

Вы можете создать слой для вашего UIBarButtonItem и придать ему форму.

Создать файл .swift и вставить этот код

import UIKit


extension CAShapeLayer {
    func drawRoundedRect(rect: CGRect, andColor color: UIColor, filled: Bool) {
        fillColor = filled ? color.cgColor : UIColor.white.cgColor
        strokeColor = color.cgColor
        path = UIBezierPath(roundedRect: rect, cornerRadius: 7).cgPath
    }
}

private var handle: UInt8 = 0;

extension UIBarButtonItem {
     var badgeLayer: CAShapeLayer? {
        if let b: AnyObject = objc_getAssociatedObject(self, &handle) as AnyObject? {
            return b as? CAShapeLayer
        } else {
            return nil
        }
    }

    func setBadge(text: String?, withOffsetFromTopRight offset: CGPoint = CGPoint.zero, andColor color:UIColor = UIColor.red, andFilled filled: Bool = true, andFontSize fontSize: CGFloat = 11)
    {
        badgeLayer?.removeFromSuperlayer()

        if (text == nil || text == "") {
            return
        }

        addBadge(text: text!, withOffset: offset, andColor: color, andFilled: filled)
    }

    func addBadge(text: String, withOffset offset: CGPoint = CGPoint.zero, andColor color: UIColor = UIColor.red, andFilled filled: Bool = true, andFontSize fontSize: CGFloat = 11)
    {
        guard let view = self.value(forKey: "view") as? UIView else { return }

        var font = UIFont.systemFont(ofSize: fontSize)

        if #available(iOS 9.0, *) { font = UIFont.monospacedDigitSystemFont(ofSize: fontSize, weight: UIFont.Weight.regular) }
        let badgeSize = text.size(withAttributes: [NSAttributedString.Key.font: font])

        // Initialize Badge
        let badge = CAShapeLayer()

        let height = badgeSize.height;
        var width = badgeSize.width + 2 /* padding */

        //make sure we have at least a circle
        if (width < height) {
            width = height
        }

        //x position is offset from right-hand side
        let x = view.frame.width - width + offset.x

        let badgeFrame = CGRect(origin: CGPoint(x: x, y: offset.y), size: CGSize(width: width, height: height))

        badge.drawRoundedRect(rect: badgeFrame, andColor: color, filled: filled)
        view.layer.addSublayer(badge)

        // Initialiaze Badge's label
        let label = CATextLayer()
        label.string = text
        label.alignmentMode = CATextLayerAlignmentMode.center
        label.font = font
        label.fontSize = font.pointSize

        label.frame = badgeFrame
        label.foregroundColor = filled ? UIColor.white.cgColor : color.cgColor
        label.backgroundColor = UIColor.clear.cgColor
        label.contentsScale = UIScreen.main.scale
        badge.addSublayer(label)

        // Save Badge as UIBarButtonItem property
        objc_setAssociatedObject(self, &handle, badge, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
    }

    func removeBadge() {
        badgeLayer?.removeFromSuperlayer()
    }
}

Использование из вашего ViewController

//ADD BADGE
self.yourBarBtn.addBadge(text: String(7))

//REMOVE BADGE
self.pendingBarBtn.removeBadge()
...