import Foundation
import UIKit
public struct Badge {
let lineType: LineType
let badgeType: BadgeType
let withIcon: Bool
let iconPosition: IconPosition
let text: String
let font: UIFont
public init(
lineType: LineType,
badgeType: BadgeType,
withIcon: Bool,
iconPosition: IconPosition,
text: String,
font: UIFont
) {
self.lineType = lineType
self.badgeType = badgeType
self.withIcon = withIcon
self.iconPosition = iconPosition
self.text = text
self.font = font
}
}
public final class CustomBadgeView: UIStackView {
private var label: GTBadgeLabel?
private var imageView: GTBadgeImageView?
public convenience init(
label: GTBadgeLabel?,
imageView: GTBadgeImageView?
) {
self.init()
self.label = label
self.imageView = imageView
setCustomBadgeStackView(label: label, imageView: imageView)
}
private func setCustomBadgeStackView(label: GTBadgeLabel?, imageView: GTBadgeImageView?) {
guard let label = label, let imageView = imageView else { return }
axis = .horizontal
distribution = .equalSpacing
alignment = .center
spacing = 1.0
backgroundColor = label.backgroundColor
addArrangedSubview(imageView)
addArrangedSubview(label)
translatesAutoresizingMaskIntoConstraints = false
}
}
public final class GTBadgeLabel: UILabel {
private var badge: Badge?
public convenience init(
badge: Badge?
) {
self.init()
self.badge = badge
setCustomBadgeLabel(badge: badge)
}
private func setCustomBadgeLabel(badge: Badge?) {
guard let badge else { return }
layer.masksToBounds = true
layer.cornerRadius = 5
backgroundColor = badge.badgeType.backgroundColor
numberOfLines = badge.lineType.rawValue
text = badge.text
textColor = badge.badgeType.textColor
textAlignment = .center
backgroundColor = badge.badgeType.backgroundColor
}
}
public final class GTBadgeImageView: UIImageView {
private var icon: String?
public convenience init(
icon: String?
) {
self.init()
self.icon = icon
}
private func setCustomBadgeImageView(iconName: String?) {
guard let iconName = iconName else { return }
image = UIImage(named: iconName)
}
}
public enum LineType: Int {
case singleLine = 1
case multipleLine = 0
}
public enum BadgeType {
case danger
case warning
case neutral
case counter
case common
var backgroundColor: UIColor {
switch self {
case .danger:
return .systemPink
case .warning:
return .yellow
case .neutral:
return .gray
case .counter:
return .blue
case .common:
return .white
}
}
var textColor: UIColor {
switch self {
case .danger:
return .red
case .warning:
return .black
case .neutral:
return .black
case .counter:
return .black
case .common:
return .black
}
}
}
public enum IconPosition {
case leftSide
case rightSide
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let stackView = CustomBadgeView(
label: GTBadgeLabel(
badge: Badge(
lineType: .singleLine,
badgeType: .common,
withIcon: true,
iconPosition: .leftSide,
text: "Selam",
font: UIFont.systemFont(ofSize: 8)
)
),
imageView: GTBadgeImageView(icon: "applications")
)
self.view.addSubview(stackView)
stackView.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: 50).isActive = true
stackView.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: -50).isActive = true
stackView.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 100).isActive = true
view.backgroundColor = .lightGray
}
}
the first part is where I create my custom components and the second part is where I call components
but in the end I did not get the result I wanted.
I shared the after build. You can see the final version in the screenshot
insert image description here
I tried to add constrait programmatically but I could not find a solution.
The icon does not appear and the stackview view is very different, and the label in the stackview sticks to the stackview, I think it will be like that when the icon appears.
How can I show the icon and give space to the ones in the stackview