diff --git a/VDS/Components/BadgeIndicator/BadgeIndicator.swift b/VDS/Components/BadgeIndicator/BadgeIndicator.swift index 4554f11f..69ca0264 100644 --- a/VDS/Components/BadgeIndicator/BadgeIndicator.swift +++ b/VDS/Components/BadgeIndicator/BadgeIndicator.swift @@ -52,80 +52,41 @@ open class BadgeIndicator: View { } } - public enum TextSize: String, CaseIterable { + public enum Size: String, CaseIterable { case xxlarge = "2XLarge" case xlarge = "XLarge" case large = "Large" case medium = "Medium" case small = "Small" - - public var inset: CGFloat { - return textStyle.pointSize * 0.3333 -// switch self { -// case .xxlarge: -// return 8 -// case .xlarge: -// return 6 -// case .large: -// return 6 -// case .medium: -// return 6 -// case .small: -// return 4 -// } - } - - public var lineHeight: CGFloat { - switch self { - case .xxlarge: - return 29 - case .xlarge: - return 24 - case .large: - return 20 - case .medium: - return 18 - case .small: - return 16 - } - } public var textStyle: TextStyle { let style = TextStyle.bodySmall var pointSize: CGFloat = VDSTypography.fontSizeBody12 + var letterSpacing: CGFloat = 0.0 switch self { case .xxlarge: pointSize = VDSTypography.fontSizeTitle24 - + letterSpacing = VDSTypography.letterSpacingWide + case .xlarge: pointSize = VDSTypography.fontSizeTitle20 case .large: pointSize = VDSTypography.fontSizeBody16 + letterSpacing = VDSTypography.letterSpacingWide case .medium: pointSize = VDSTypography.fontSizeBody14 - + letterSpacing = VDSTypography.letterSpacingWide case .small: pointSize = VDSTypography.fontSizeBody12 } -// var ratio: CGFloat = 1.3333 // less than 14 -// if pointSize > 13 && pointSize < 16 { -// ratio = 1.28 -// } else if pointSize > 15 && pointSize < 19 { -// ratio = 1.25 -// } else if pointSize > 19 { -// ratio = 1.20 -// } - - let calculatedLineHeight = pointSize * 1.265//ratio - print("lineHeight\noriginal: \(lineHeight)\ncalculated:\(calculatedLineHeight)") return TextStyle(rawValue: "\(self.rawValue)BadgeIndicator", fontFace: style.fontFace, pointSize: pointSize, - lineHeight: calculatedLineHeight, - letterSpacing: style.letterSpacing) + lineHeight: 0, + letterSpacing: letterSpacing) } } @@ -171,7 +132,13 @@ open class BadgeIndicator: View { open var leadingCharacter: String? { didSet { setNeedsUpdate() }} - open var textSize: TextSize = .xxlarge { didSet { setNeedsUpdate() }} + open var size: Size = .xxlarge { didSet { setNeedsUpdate() }} + + open var dotSize: CGFloat? { didSet { setNeedsUpdate() }} + + open var verticalPadding: CGFloat? { didSet { setNeedsUpdate() }} + + open var horitonalPadding: CGFloat? { didSet { setNeedsUpdate() }} open var hideDot: Bool = false { didSet { setNeedsUpdate() }} @@ -179,31 +146,50 @@ open class BadgeIndicator: View { open var maxDigits: MaxDigits = .two { didSet { setNeedsUpdate() }} + open var width: CGFloat? { didSet { setNeedsUpdate() }} + + open var height: CGFloat? { didSet { setNeedsUpdate() }} + //-------------------------------------------------- // MARK: - Constraints //-------------------------------------------------- - private var labelWidthConstraint: NSLayoutConstraint? - private var labelHeightConstraint: NSLayoutConstraint? - private var defaultBadgeSize: CGFloat = 16 + private let layoutGuide = UILayoutGuide() + private var defaultBadgeSize: CGFloat { max(16.0, size.textStyle.font.lineHeight) } + private var widthConstraint: NSLayoutConstraint? + private var heightConstraint: NSLayoutConstraint? + private var labelContraints = NSLayoutConstraint.Container() + //-------------------------------------------------- // MARK: - Lifecycle //-------------------------------------------------- open override func setup() { super.setup() - + + addLayoutGuide(layoutGuide) + addSubview(label) accessibilityElements = [label] - addSubview(label) - label.pinToSuperView() + heightConstraint = layoutGuide.heightAnchor.constraint(greaterThanOrEqualToConstant: defaultBadgeSize) + heightConstraint?.isActive = true + widthConstraint = layoutGuide.widthAnchor.constraint(greaterThanOrEqualToConstant: defaultBadgeSize) + widthConstraint?.isActive = true + NSLayoutConstraint.activate([ - label.centerXAnchor.constraint(equalTo: centerXAnchor), - label.centerYAnchor.constraint(equalTo: centerYAnchor) - ]) - - labelWidthConstraint = label.widthGreaterThanEqualTo(constant: defaultBadgeSize).activate() - labelHeightConstraint = label.heightGreaterThanEqualTo(constant: defaultBadgeSize).activate() + layoutGuide.topAnchor.constraint(equalTo: topAnchor, constant: 1), + layoutGuide.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -1), + layoutGuide.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 1), + layoutGuide.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -1)]) + + labelContraints.topConstraint = label.pinTopGreaterThanOrEqualTo(anchor: layoutGuide.topAnchor) + labelContraints.bottomConstraint = label.pinBottomGreaterThanOrEqualTo(anchor: layoutGuide.bottomAnchor) + labelContraints.leadingConstraint = label.pinLeadingGreaterThanOrEqualTo(anchor: layoutGuide.leadingAnchor) + labelContraints.trailingConstraint = label.pinTrailingGreaterThanOrEqualTo(anchor: layoutGuide.trailingAnchor) + label.centerXAnchor.constraint(equalTo: layoutGuide.centerXAnchor).isActive = true + label.centerYAnchor.constraint(equalTo: layoutGuide.centerYAnchor).isActive = true + labelContraints.isActive = true + } open override func reset() { @@ -218,6 +204,21 @@ open class BadgeIndicator: View { setNeedsUpdate() } + private let defaultInset = VDSLayout.Spacing.space1X.value + + private var labelEdgeInset: UIEdgeInsets { + + if let verticalPadding, let horitonalPadding { + return .init(top: verticalPadding, left: horitonalPadding, bottom: verticalPadding, right: horitonalPadding) + } else if let verticalPadding { + return .init(top: verticalPadding, left: defaultInset, bottom: verticalPadding, right: defaultInset) + } else if let horitonalPadding { + return .init(top: defaultInset, left: horitonalPadding, bottom: defaultInset, right: horitonalPadding) + } else { + return .init(top: 0, left: defaultInset, bottom: 0, right: defaultInset) + } + } + //-------------------------------------------------- // MARK: - Configuration //-------------------------------------------------- @@ -266,10 +267,30 @@ open class BadgeIndicator: View { backgroundColor = backgroundColorConfiguration.getColor(self) - label.useAttributedText = true - label.edgeInset = .init(top: 0, left: textSize.inset, bottom: 0, right: textSize.inset) - label.font = textSize.textStyle.font - label.textColor = textColorConfiguration.getColor(self) + //height width + heightConstraint?.isActive = false + widthConstraint?.isActive = false + if let width, let height { + heightConstraint = layoutGuide.heightAnchor.constraint(equalToConstant: height) + widthConstraint = layoutGuide.widthAnchor.constraint(equalToConstant: width) + } else { + heightConstraint = layoutGuide.heightAnchor.constraint(greaterThanOrEqualToConstant: defaultBadgeSize) + widthConstraint = layoutGuide.widthAnchor.constraint(greaterThanOrEqualToConstant: defaultBadgeSize) + } + heightConstraint?.isActive = true + widthConstraint?.isActive = true + + //label constraints + let insets = labelEdgeInset + labelContraints.isActive = false + labelContraints.topConstraint?.constant = insets.top + labelContraints.bottomConstraint?.constant = -insets.bottom + labelContraints.leadingConstraint?.constant = insets.left + labelContraints.trailingConstraint?.constant = -insets.right + labelContraints.isActive = true + + //label properties + label.textStyle = size.textStyle label.textColorConfiguration = textColorConfiguration.eraseToAnyColorable() label.text = getText() label.surface = surface @@ -308,9 +329,6 @@ open class BadgeIndicator: View { open override func layoutSubviews() { super.layoutSubviews() - let size = textSize.textStyle.lineHeight - labelWidthConstraint?.constant = size - labelHeightConstraint?.constant = size layer.cornerRadius = frame.size.height / 2 if hideBorder { @@ -322,17 +340,19 @@ open class BadgeIndicator: View { layer.remove(layerName: "dot") if kind == .simple && !hideDot { - let dotSize: CGFloat = bounds.width * 0.1875 + var dot: CGFloat = bounds.width * 0.1875 + if let dotSize { + dot = dotSize + } let dotLayer = CAShapeLayer() dotLayer.name = "dot" - let centerX = (bounds.width - dotSize) / 2.0 - let centerY = (bounds.width - dotSize) / 2.0 + let centerX = (bounds.width - dot) / 2.0 + let centerY = (bounds.height - dot) / 2.0 - dotLayer.frame = .init(x: centerX, y: centerY, width: dotSize, height: dotSize) - dotLayer.path = UIBezierPath(ovalIn: .init(origin: .zero, size: .init(width: dotSize, height: dotSize))).cgPath + dotLayer.frame = .init(x: centerX, y: centerY, width: dot, height: dot) + dotLayer.path = UIBezierPath(ovalIn: .init(origin: .zero, size: .init(width: dot, height: dot))).cgPath dotLayer.fillColor = textColorConfiguration.getColor(self).cgColor - layer.addSublayer(dotLayer) } }