Browse Source

添加自定义气泡view

jsonwang 3 years ago
parent
commit
01926db19e

+ 114 - 0
BFFramework/Classes/BFModules/BFCustomViews/views/NXBadgeView/NXBadgeControl.swift

@@ -0,0 +1,114 @@
+//
+//  NXBadgeControl.swift
+//  NXFramework-Swift
+//
+//  Created by ak on 2020/11/11.
+//
+
+
+import UIKit
+
+
+open class NXBadgeControl: UIControl {
+    
+    /// 记录Badge的偏移量 Record the offset of Badge
+    public var offset: CGPoint = CGPoint(x: 0, y: 0)
+    
+    /// Badge伸缩的方向, Default is NXBadgeViewFlexModeTail
+    public var flexMode: NXBadgeViewFlexMode = .tail
+    
+    private lazy var textLabel: UILabel = UILabel()
+    
+    private lazy var imageView: UIImageView = UIImageView()
+    
+    private var badgeViewColor: UIColor?
+    private var badgeViewHeightConstraint: NSLayoutConstraint?
+    
+    public class func `default`() -> Self {
+        return self.init(frame: .zero)
+    }
+    
+    required override public init(frame: CGRect) {
+        super.init(frame: frame)
+        setupSubviews()
+    }
+    
+    required public init?(coder aDecoder: NSCoder) {
+        super.init(coder: aDecoder)
+        fatalError("init(coder:) has not been implemented")
+    }
+    
+    /// Set Text
+    open var text: String? {
+        didSet {
+            textLabel.text = text
+        }
+    }
+    
+    /// Set AttributedText
+    open var attributedText: NSAttributedString? {
+        didSet {
+            textLabel.attributedText = attributedText
+        }
+    }
+    
+    /// Set Font
+    open var font: UIFont? {
+        didSet {
+            textLabel.font = font
+        }
+    }
+    
+    /// Set background image
+    open var backgroundImage: UIImage? {
+        didSet {
+            imageView.image = backgroundImage
+            if let _ = backgroundImage {
+                if let constraint = heightConstraint() {
+                    badgeViewHeightConstraint = constraint
+                    removeConstraint(constraint)
+                }
+                backgroundColor = UIColor.clear
+            } else {
+                if heightConstraint() == nil, let constraint = badgeViewHeightConstraint {
+                    addConstraint(constraint)
+                }
+                backgroundColor = badgeViewColor
+            }
+        }
+    }
+    
+    open override var backgroundColor: UIColor? {
+        didSet {
+            super.backgroundColor = backgroundColor
+            if let color = backgroundColor, color != .clear {
+                badgeViewColor = backgroundColor
+            }
+        }
+    }
+    
+    private func setupSubviews() {
+        layer.masksToBounds = true
+        layer.cornerRadius = 9.0
+        translatesAutoresizingMaskIntoConstraints = false
+        backgroundColor = UIColor.red
+        textLabel.textColor = UIColor.white
+        textLabel.font = UIFont.systemFont(ofSize: 13)
+        textLabel.textAlignment = .center
+        addSubview(textLabel)
+        addSubview(imageView)
+        addLayout(with: imageView, leading: 0, trailing: 0)
+        addLayout(with: textLabel, leading: 5, trailing: -5)
+    }
+    
+    private func addLayout(with view: UIView, leading: CGFloat, trailing: CGFloat) {
+        view.translatesAutoresizingMaskIntoConstraints = false
+        let topConstraint = NSLayoutConstraint(item: view, attribute: .top, relatedBy: .equal, toItem: self, attribute: .top, multiplier: 1.0, constant: 0)
+        let leadingConstraint = NSLayoutConstraint(item: view, attribute: .leading, relatedBy: .equal, toItem: self, attribute: .leading, multiplier: 1.0, constant: leading)
+        let bottomConstraint = NSLayoutConstraint(item: view, attribute: .bottom, relatedBy: .equal, toItem: self, attribute: .bottom, multiplier: 1.0, constant: 0)
+        let trailingConstraint = NSLayoutConstraint(item: view, attribute: .trailing, relatedBy: .equal, toItem: self, attribute: .trailing, multiplier: 1.0, constant: trailing)
+        leadingConstraint.priority = UILayoutPriority(rawValue: 999)
+        trailingConstraint.priority = UILayoutPriority(rawValue: 999)
+        addConstraints([topConstraint, leadingConstraint, bottomConstraint, trailingConstraint])
+    }
+}

+ 28 - 0
BFFramework/Classes/BFModules/BFCustomViews/views/NXBadgeView/NXBadgeView.swift

@@ -0,0 +1,28 @@
+//
+//  NXBadgeView.swift.swift
+//  NXFramework-Swift
+//
+//  Created by ak on 2020/11/11.
+//
+
+
+import UIKit
+
+public struct NX<Base> {
+    public let base: Base
+    public init(_ base: Base) {
+        self.base = base
+    }
+}
+
+public extension NSObjectProtocol {
+    var nx: NX<Self> {
+        return NX(self)
+    }
+}
+
+public enum NXBadgeViewFlexMode {
+    case head    // 左伸缩 Head Flex    : <==●
+    case tail    // 右伸缩 Tail Flex    : ●==>
+    case middle  // 左右伸缩 Middle Flex : <=●=>
+}

+ 125 - 0
BFFramework/Classes/BFModules/BFCustomViews/views/NXBadgeView/UIBarButtonItem+NXBadgeView.swift

@@ -0,0 +1,125 @@
+//
+//  UIBarButtonItem+NXBadgeView.swift
+//  NXFramework-Swift
+//
+//  Created by ak on 2020/11/11.
+//
+
+import UIKit
+
+public extension NX where Base: UIBarButtonItem {
+    
+    public var badgeView: NXBadgeControl {
+        return _bottomView.nx.badgeView
+    }
+    
+    /// 添加带文本内容的Badge, 默认右上角, 红色, 18pts
+    ///
+    /// Add Badge with text content, the default upper right corner, red backgroundColor, 18pts
+    ///
+    /// - Parameter text: 文本字符串
+     public  func addBadge(text: String) {
+        _bottomView.nx.addBadge(text: text)
+    }
+    
+    /// 添加带数字的Badge, 默认右上角,红色,18pts
+    ///
+    /// Add the Badge with numbers, the default upper right corner, red backgroundColor, 18pts
+    ///
+    /// - Parameter number: 整形数字
+     public  func addBadge(number: Int) {
+        _bottomView.nx.addBadge(number: number)
+    }
+    
+    /// 添加带颜色的小圆点, 默认右上角, 红色, 8pts
+    ///
+    /// Add small dots with color, the default upper right corner, red backgroundColor, 8pts
+    ///
+    /// - Parameter color: 颜色
+     public  func addDot(color: UIColor?) {
+        _bottomView.nx.addDot(color: color)
+    }
+    
+    /// 设置Badge的偏移量, Badge中心点默认为其父视图的右上角
+    ///
+    /// Set Badge offset, Badge center point defaults to the top right corner of its parent view
+    ///
+    /// - Parameters:
+    ///   - x: X轴偏移量 (x<0: 左移, x>0: 右移) axis offset (x <0: left, x> 0: right)
+    ///   - y: Y轴偏移量 (y<0: 上移, y>0: 下移) axis offset (Y <0: up,   y> 0: down)
+     public  func moveBadge(x: CGFloat, y: CGFloat) {
+        _bottomView.nx.moveBadge(x: x, y: y)
+    }
+    
+    /// 设置Badge伸缩的方向
+    ///
+    /// Setting the direction of Badge expansion
+    ///
+    /// NXBadgeViewFlexModeHead,    左伸缩 Head Flex    : <==●
+    /// NXBadgeViewFlexModeTail,    右伸缩 Tail Flex    : ●==>
+    /// NXBadgeViewFlexModeMiddle   左右伸缩 Middle Flex : <=●=>
+    /// - Parameter flexMode : Default is PPBadgeViewFlexModeTail
+     public  func setBadge(flexMode: NXBadgeViewFlexMode = .tail) {
+        _bottomView.nx.setBadge(flexMode: flexMode)
+    }
+    
+    /// 设置Badge的高度,因为Badge宽度是动态可变的,通过改变Badge高度,其宽度也按比例变化,方便布局
+    ///
+    /// (注意: 此方法需要将Badge添加到控件上后再调用!!!)
+    ///
+    /// Set the height of Badge, because the Badge width is dynamically and  variable.By changing the Badge height in proportion to facilitate the layout.
+    ///
+    /// (Note: this method needs to add Badge to the controls and then use it !!!)
+    ///
+    /// - Parameter points: 高度大小
+     public  func setBadge(height: CGFloat) {
+        _bottomView.nx.setBadge(height: height)
+    }
+    
+    /// 显示Badge
+     public  func showBadge() {
+        _bottomView.nx.showBadge()
+    }
+    
+    /// 隐藏Badge
+     public  func hiddenBadge() {
+        _bottomView.nx.hiddenBadge()
+    }
+    
+    // MARK: - 数字增加/减少, 注意:以下方法只适用于Badge内容为纯数字的情况
+    // MARK: - Digital increase /decrease, note: the following method applies only to cases where the Badge content is purely numeric
+    /// badge数字加1
+     public  func increase() {
+        _bottomView.nx.increase()
+    }
+    
+    /// badge数字加number
+     public  func increaseBy(number: Int) {
+        _bottomView.nx.increaseBy(number: number)
+    }
+    
+    /// badge数字加1
+     public  func decrease() {
+        _bottomView.nx.decrease()
+    }
+    
+    /// badge数字减number
+     public  func decreaseBy(number: Int) {
+        _bottomView.nx.decreaseBy(number: number)
+    }
+
+    /// 通过Xcode视图调试工具找到UIBarButtonItem的Badge所在父视图为:UIImageView
+    private var _bottomView: UIView {
+        let navigationButton = (self.base.value(forKey: "_view") as? UIView) ?? UIView()
+        let systemVersion = (UIDevice.current.systemVersion as NSString).doubleValue
+        let controlName = (systemVersion < 11.0 ? "UIImageView" : "UIButton" )
+        for subView in navigationButton.subviews {
+            if subView.isKind(of: NSClassFromString(controlName)!) {
+                subView.layer.masksToBounds = false
+                return subView
+            }
+        }
+        return navigationButton
+    }
+}
+

+ 126 - 0
BFFramework/Classes/BFModules/BFCustomViews/views/NXBadgeView/UITabBarItem+NXBadgeView.swift

@@ -0,0 +1,126 @@
+
+//
+//  UITabBarItem+NXBadgeView.swift
+//  NXFramework-Swift
+//
+//  Created by ak on 2020/11/11.
+//
+
+import Foundation
+
+public extension NX where Base: UITabBarItem {
+    
+    var badgeView: NXBadgeControl {
+        return _bottomView.nx.badgeView
+    }
+    
+    /// 添加带文本内容的Badge, 默认右上角, 红色, 18pts
+    ///
+    /// Add Badge with text content, the default upper right corner, red backgroundColor, 18pts
+    ///
+    /// - Parameter text: 文本字符串
+    func addBadge(text: String) {
+        _bottomView.nx.addBadge(text: text)
+        _bottomView.nx.moveBadge(x: 4, y: 3)
+    }
+    
+    /// 添加带数字的Badge, 默认右上角,红色,18pts
+    ///
+    /// Add the Badge with numbers, the default upper right corner, red backgroundColor, 18pts
+    ///
+    /// - Parameter number: 整形数字
+    func addBadge(number: Int) {
+        _bottomView.nx.addBadge(number: number)
+        _bottomView.nx.moveBadge(x: 4, y: 3)
+    }
+    
+    /// 添加带颜色的小圆点, 默认右上角, 红色, 8pts
+    ///
+    /// Add small dots with color, the default upper right corner, red backgroundColor, 8pts
+    ///
+    /// - Parameter color: 颜色
+    func addDot(color: UIColor?) {
+        _bottomView.nx.addDot(color: color)
+    }
+    
+    /// 设置Badge的偏移量, Badge中心点默认为其父视图的右上角
+    ///
+    /// Set Badge offset, Badge center point defaults to the top right corner of its parent view
+    ///
+    /// - Parameters:
+    ///   - x: X轴偏移量 (x<0: 左移, x>0: 右移) axis offset (x <0: left, x> 0: right)
+    ///   - y: Y轴偏移量 (y<0: 上移, y>0: 下移) axis offset (Y <0: up,   y> 0: down)
+    func moveBadge(x: CGFloat, y: CGFloat) {
+        _bottomView.nx.moveBadge(x: x, y: y)
+    }
+    
+    /// 设置Badge伸缩的方向
+    ///
+    /// Setting the direction of Badge expansion
+    ///
+    /// PPBadgeViewFlexModeHead,    左伸缩 Head Flex    : <==●
+    /// PPBadgeViewFlexModeTail,    右伸缩 Tail Flex    : ●==>
+    /// PPBadgeViewFlexModeMiddle   左右伸缩 Middle Flex : <=●=>
+    /// - Parameter flexMode : Default is PPBadgeViewFlexModeTail
+    func setBadge(flexMode: NXBadgeViewFlexMode = .tail) {
+        _bottomView.nx.setBadge(flexMode: flexMode)
+    }
+    
+    /// 设置Badge的高度,因为Badge宽度是动态可变的,通过改变Badge高度,其宽度也按比例变化,方便布局
+    ///
+    /// (注意: 此方法需要将Badge添加到控件上后再调用!!!)
+    ///
+    /// Set the height of Badge, because the Badge width is dynamically and  variable.By changing the Badge height in proportion to facilitate the layout.
+    ///
+    /// (Note: this method needs to add Badge to the controls and then use it !!!)
+    ///
+    /// - Parameter height: 高度大小
+    func setBadge(height: CGFloat) {
+        _bottomView.nx.setBadge(height: height)
+    }
+    
+    
+    /// 显示Badge
+    func showBadge() {
+        _bottomView.nx.showBadge()
+    }
+    
+    /// 隐藏Badge
+    func hiddenBadge() {
+        _bottomView.nx.hiddenBadge()
+    }
+    
+    // MARK: - 数字增加/减少, 注意:以下方法只适用于Badge内容为纯数字的情况
+    // MARK: - Digital increase /decrease, note: the following method applies only to cases where the Badge content is purely numeric
+    /// badge数字加1
+    func increase() {
+        _bottomView.nx.increase()
+    }
+    
+    /// badge数字加number
+    func increaseBy(number: Int) {
+        _bottomView.nx.increaseBy(number: number)
+    }
+    
+    /// badge数字加1
+    func decrease() {
+        _bottomView.nx.decrease()
+    }
+    
+    /// badge数字减number
+    func decreaseBy(number: Int) {
+        _bottomView.nx.decreaseBy(number: number)
+    }
+    
+    /// 通过Xcode视图调试工具找到UITabBarItem原生Badge所在父视图
+    private var _bottomView: UIView {
+        let tabBarButton = (self.base.value(forKey: "_view") as? UIView) ?? UIView()
+        for subView in tabBarButton.subviews {
+            guard let superclass = subView.superclass else { return tabBarButton }
+            if superclass == NSClassFromString("UIImageView") {
+                return subView
+            }
+        }
+        return tabBarButton
+    }
+}

+ 260 - 0
BFFramework/Classes/BFModules/BFCustomViews/views/NXBadgeView/UIView+NXBadgeView.swift

@@ -0,0 +1,260 @@
+//
+//  UIView+NXBadgeView.swift
+//  NXFramework-Swift
+//
+//  Created by ak on 2020/11/11.
+//
+
+import UIKit
+
+private var kBadgeView = "kNXBadgeView"
+
+// MARK: - add Badge
+public extension NX where Base: UIView {
+    
+    var badgeView: NXBadgeControl {
+        return base.badgeView
+    }
+    
+    /// 添加带文本内容的Badge, 默认右上角, 红色, 18pts
+    ///
+    /// Add Badge with text content, the default upper right corner, red backgroundColor, 18pts
+    ///
+    /// - Parameter text: 文本字符串
+    func addBadge(text: String?) {
+        showBadge()
+        base.badgeView.text = text
+        setBadge(flexMode: base.badgeView.flexMode)
+        if text == nil {
+            if base.badgeView.widthConstraint()?.relation == .equal { return }
+            base.badgeView.widthConstraint()?.isActive = false
+            let constraint = NSLayoutConstraint(item: base.badgeView, attribute: .width, relatedBy: .equal, toItem: base.badgeView, attribute: .height, multiplier: 1.0, constant: 0)
+            base.badgeView.addConstraint(constraint)
+        } else {
+            if base.badgeView.widthConstraint()?.relation == .greaterThanOrEqual { return }
+            base.badgeView.widthConstraint()?.isActive = false
+            let constraint = NSLayoutConstraint(item: base.badgeView, attribute: .width, relatedBy: .greaterThanOrEqual, toItem: base.badgeView, attribute: .height, multiplier: 1.0, constant: 0)
+            base.badgeView.addConstraint(constraint)
+        }
+    }
+    
+    /// 添加带数字的Badge, 默认右上角,红色,18pts
+    ///
+    /// Add the Badge with numbers, the default upper right corner, red backgroundColor, 18pts
+    ///
+    /// - Parameter number: 整形数字
+    func addBadge(number: Int) {
+        if number <= 0 {
+            addBadge(text: "0")
+            hiddenBadge()
+            return
+        }
+        addBadge(text: "\(number)")
+    }
+    
+    /// 添加带颜色的小圆点, 默认右上角, 红色, 8pts
+    ///
+    /// Add small dots with color, the default upper right corner, red backgroundColor, 8pts
+    ///
+    /// - Parameter color: 颜色
+    func addDot(color: UIColor? = .red) {
+        addBadge(text: nil)
+        setBadge(height: 8.0)
+        base.badgeView.backgroundColor = color
+    }
+    
+    /// 设置Badge的偏移量, Badge中心点默认为其父视图的右上角
+    ///
+    /// Set Badge offset, Badge center point defaults to the top right corner of its parent view
+    ///
+    /// - Parameters:
+    ///   - x: X轴偏移量 (x<0: 左移, x>0: 右移) axis offset (x <0: left, x> 0: right)
+    ///   - y: Y轴偏移量 (y<0: 上移, y>0: 下移) axis offset (Y <0: up,   y> 0: down)
+    func moveBadge(x: CGFloat, y: CGFloat) {
+        base.badgeView.offset = CGPoint(x: x, y: y)
+        base.centerYConstraint(with: base.badgeView)?.constant = y
+        
+        let badgeHeight = base.badgeView.heightConstraint()?.constant ?? 0
+        switch base.badgeView.flexMode {
+        case .head:
+            base.centerXConstraint(with: base.badgeView)?.isActive = false
+            base.leadingConstraint(with: base.badgeView)?.isActive = false
+            if let constraint = base.trailingConstraint(with: base.badgeView) {
+                constraint.constant = badgeHeight * 0.5 + x
+                return
+            }
+            let trailingConstraint = NSLayoutConstraint(item: base.badgeView, attribute: .trailing, relatedBy: .equal, toItem: base, attribute: .trailing, multiplier: 1.0, constant: badgeHeight * 0.5 + x)
+            base.addConstraint(trailingConstraint)
+            
+        case .tail:
+            base.centerXConstraint(with: base.badgeView)?.isActive = false
+            base.trailingConstraint(with: base.badgeView)?.isActive = false
+            if let constraint = base.leadingConstraint(with: base.badgeView) {
+                constraint.constant = x - badgeHeight * 0.5
+                return
+            }
+            let leadingConstraint = NSLayoutConstraint(item: base.badgeView, attribute: .leading, relatedBy: .equal, toItem: base, attribute: .trailing, multiplier: 1.0, constant: x - badgeHeight * 0.5)
+            base.addConstraint(leadingConstraint)
+            
+        case .middle:
+            base.leadingConstraint(with: base.badgeView)?.isActive = false
+            base.trailingConstraint(with: base.badgeView)?.isActive = false
+            base.centerXConstraint(with: base.badgeView)?.constant = x
+            if let constraint = base.centerXConstraint(with: base.badgeView) {
+                constraint.constant = x
+                return
+            }
+            let centerXConstraint = NSLayoutConstraint(item: base.badgeView, attribute: .centerX, relatedBy: .equal, toItem: base, attribute: .centerX, multiplier: 1.0, constant: x)
+            base.addConstraint(centerXConstraint)
+        }
+    }
+    
+    /// 设置Badge伸缩的方向
+    ///
+    /// Setting the direction of Badge expansion
+    ///
+    /// NXBadgeViewFlexModeHead,    左伸缩 Head Flex    : <==●
+    /// NXBadgeViewFlexModeTail,    右伸缩 Tail Flex    : ●==>
+    /// NXBadgeViewFlexModeMiddle   左右伸缩 Middle Flex : <=●=>
+    /// - Parameter flexMode : Default is PPBadgeViewFlexModeTail
+    func setBadge(flexMode: NXBadgeViewFlexMode = .tail) {
+        base.badgeView.flexMode = flexMode
+        moveBadge(x: base.badgeView.offset.x, y: base.badgeView.offset.y)
+    }
+    
+    /// 设置Badge的高度,因为Badge宽度是动态可变的,通过改变Badge高度,其宽度也按比例变化,方便布局
+    ///
+    /// (注意: 此方法需要将Badge添加到控件上后再调用!!!)
+    ///
+    /// Set the height of Badge, because the Badge width is dynamically and  variable.By changing the Badge height in proportion to facilitate the layout.
+    ///
+    /// (Note: this method needs to add Badge to the controls and then use it !!!)
+    ///
+    /// - Parameter height: 高度大小
+    func setBadge(height: CGFloat) {
+        base.badgeView.layer.cornerRadius = height * 0.5
+        base.badgeView.heightConstraint()?.constant = height
+        moveBadge(x: base.badgeView.offset.x, y: base.badgeView.offset.y)
+    }
+    
+    /// 显示Badge
+    func showBadge() {
+        base.badgeView.isHidden = false
+    }
+    
+    /// 隐藏Badge
+    func hiddenBadge() {
+        base.badgeView.isHidden = true
+    }
+    
+    // MARK: - 数字增加/减少, 注意:以下方法只适用于Badge内容为纯数字的情况
+    // MARK: - Digital increase /decrease, note: the following method applies only to cases where the Badge content is purely numeric
+    /// badge数字加1
+    func increase() {
+        increaseBy(number: 1)
+    }
+    
+    /// badge数字加number
+    func increaseBy(number: Int) {
+        let label = base.badgeView
+        let result = (Int(label.text ?? "0") ?? 0) + number
+        if result > 0 {
+            showBadge()
+        }
+        label.text = "\(result)"
+    }
+    
+    /// badge数字加1
+    func decrease() {
+        decreaseBy(number: 1)
+    }
+    
+    /// badge数字减number
+    func decreaseBy(number: Int) {
+        let label = base.badgeView
+        let result = (Int(label.text ?? "0") ?? 0) - number
+        if (result <= 0) {
+            hiddenBadge()
+            label.text = "0"
+            return
+        }
+        label.text = "\(result)"
+    }
+}
+
+extension UIView {
+    
+      public  func addBadgeViewLayoutConstraint() {
+        badgeView.translatesAutoresizingMaskIntoConstraints = false
+        let centerXConstraint = NSLayoutConstraint(item: badgeView, attribute: .centerX, relatedBy: .equal, toItem: self, attribute: .trailing, multiplier: 1.0, constant: 0)
+        let centerYConstraint = NSLayoutConstraint(item: badgeView, attribute: .centerY, relatedBy: .equal, toItem: self, attribute: .top, multiplier: 1.0, constant: 0)
+        let widthConstraint = NSLayoutConstraint(item: badgeView, attribute: .width, relatedBy: .greaterThanOrEqual, toItem: badgeView, attribute: .height, multiplier: 1.0, constant: 0)
+        let heightConstraint = NSLayoutConstraint(item: badgeView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: 18)
+        addConstraints([centerXConstraint, centerYConstraint])
+        badgeView.addConstraints([widthConstraint, heightConstraint])
+    }
+}
+
+// MARK: - getter/setter
+extension UIView {
+
+    public var badgeView: NXBadgeControl {
+        get {
+            if let aValue = objc_getAssociatedObject(self, &kBadgeView) as? NXBadgeControl {
+                return aValue
+            }
+            else {
+                let badgeControl = NXBadgeControl.default()
+                self.addSubview(badgeControl)
+                self.bringSubviewToFront(badgeControl)
+                self.badgeView = badgeControl
+                self.addBadgeViewLayoutConstraint()
+                return badgeControl
+            }
+        }
+        set {
+            objc_setAssociatedObject(self, &kBadgeView, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
+        }
+    }
+    
+       public  func topConstraint(with item: AnyObject?) -> NSLayoutConstraint? {
+        return constraint(with: item, attribute: .top)
+    }
+    
+       public  func leadingConstraint(with item: AnyObject?) -> NSLayoutConstraint? {
+        return constraint(with: item, attribute: .leading)
+    }
+    
+       public  func bottomConstraint(with item: AnyObject?) -> NSLayoutConstraint? {
+        return constraint(with: item, attribute: .bottom)
+    }
+
+       public  func trailingConstraint(with item: AnyObject?) -> NSLayoutConstraint? {
+        return constraint(with: item, attribute: .trailing)
+    }
+    
+       public  func widthConstraint() -> NSLayoutConstraint? {
+        return constraint(with: self, attribute: .width)
+    }
+    
+       public  func heightConstraint() -> NSLayoutConstraint? {
+        return constraint(with: self, attribute: .height)
+    }
+
+       public  func centerXConstraint(with item: AnyObject?) -> NSLayoutConstraint? {
+        return constraint(with: item, attribute: .centerX)
+    }
+    
+       public  func centerYConstraint(with item: AnyObject?) -> NSLayoutConstraint? {
+        return constraint(with: item, attribute: .centerY)
+    }
+    
+       public  func constraint(with item: AnyObject?, attribute: NSLayoutConstraint.Attribute) -> NSLayoutConstraint? {
+        for constraint in constraints {
+            if let isSame = constraint.firstItem?.isEqual(item), isSame, constraint.firstAttribute == attribute {
+                return constraint
+            }
+        }
+        return nil
+    }
+}