【问题标题】:Increasing UIButton's intrinsic size when contained in UIBarButtonItem包含在 UIBarButtonItem 中时增加 UIButton 的固有大小
【发布时间】:2019-11-15 04:19:15
【问题描述】:

我创建了一个 UIButton 子类,其视图位于按钮边界之外。

如截图所示:

如您所见,徽章位于按钮之外。它的中心固定在按钮的右上角。

问题是当按钮放在UIBarButtonItem 中时,徽章会被剪掉。

视图层次结构检查器显示了原因:

如何与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 Library

【问题讨论】:

  • 你能发布完整的代码吗?导入 BadgeSwift ,我会试试的
  • 我已经用我用来绘制徽章的库的链接更新了我的问题。

标签: ios swift uibutton uikit uibarbuttonitem


【解决方案1】:

您可以为您的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()

【讨论】:

  • 问题是关于如何使UIBarButtonItem 中包含的UIButton 更大,而不是如何创建徽章。
  • 您似乎正在创建徽章。所以发布了这个。
【解决方案2】:

已通过在徽章周围添加清晰边框来修复:


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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-12-15
    • 1970-01-01
    • 1970-01-01
    • 2020-09-21
    • 2013-07-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多