Visual_Novel_iOS/crush/Crush/Src/Components/UI/Buttons/ChipButtons.swift

567 lines
16 KiB
Swift
Raw Normal View History

2025-10-09 10:29:35 +00:00
//
// ChipButtons.swift
// Crush
//
// Created by Leon on 2025/7/18.
//
import SnapKit
import UIKit
// MARK: - Base Class
class EPChipButton: CLControl {
// MARK: - Constants
let chipButtonHeight: CGFloat = 32
// MARK: - Properties
lazy var stack: UIStackView = {
let stack = UIStackView()
stack.alignment = .fill
stack.distribution = .fill
stack.alignment = .center
stack.axis = .horizontal
stack.spacing = 8
return stack
}()
lazy var imageView: UIImageView = {
let imageView = UIImageView()
imageView.contentMode = .scaleAspectFill
imageView.isUserInteractionEnabled = true
return imageView
}()
lazy var textLabel: UILabel = {
let label = UILabel()
label.font = CLSystemToken.font(token: .tlm)
label.isUserInteractionEnabled = true
return label
}()
lazy var iconView: UIImageView = {
let iconView = UIImageView()
iconView.contentMode = .scaleAspectFit
iconView.isUserInteractionEnabled = true
return iconView
}()
var text: String? {
didSet {
textLabel.text = text
setNeedsLayout()
}
}
var iconCode: IconCode = .sort {
didSet {
iconView.isHidden = (iconCode.rawValue <= 0)
iconView.image = defaultIcon
}
}
var defaultIconColor: UIColor? {
didSet {
iconView.image = defaultIcon
}
}
var defaultIcon: UIImage? {
let color = defaultIconColor ?? UIColor.c.ctsn
return MWIconFont.image(fromIconInt: iconCode.rawValue, size: iconSize, color: color, edgeInsets: .zero)
}
var selectedIcon: UIImage? {
nil // Subclasses override
}
var defaultImage: UIImage? {
nil // Subclasses override
}
var selectedImage: UIImage? {
nil // Subclasses override
}
var paddingInsets: UIEdgeInsets {
.zero // Subclasses override
}
var iconSize: CGSize {
.zero // Subclasses override
}
var imageSize: CGSize {
.zero // Subclasses override
}
// MARK: - Initialization
override init(frame: CGRect) {
super.init(frame: frame)
clipsToBounds = true
layer.cornerRadius = chipButtonHeight * 0.5
setupTheme()
}
@available(*, unavailable)
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// MARK: - Setup
func setupTheme() {
textLabel.textColor = .c.ctpn // EPSystemToken.color(.txtPrimaryNormal)
}
// MARK: - Hit Testing
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
guard isUserInteractionEnabled, alpha != 0, !isHidden else { return nil }
if self.point(inside: point, with: event) {
return self
}
return super.hitTest(point, with: event)
}
}
// MARK: - EPChipFilterButton
/// 16 height 32
class EPChipFilterButton: EPChipButton {
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = .c.csen // EPSystemToken.color(.surfaceElementNormal)
layer.borderWidth = 0
addSubview(textLabel)
textLabel.snp.makeConstraints { make in
make.edges.equalTo(self).inset(paddingInsets).priority(.high)
make.height.equalTo(chipButtonHeight)
}
}
override func setupTheme() {
super.setupTheme()
layer.borderColor = UIColor.c.cpvn.cgColor // EPSystemToken.color(.primaryVariantNormal).cgColor
}
override var paddingInsets: UIEdgeInsets {
UIEdgeInsets(top: 0, left: 16, bottom: 0, right: 16)
}
override var intrinsicContentSize: CGSize{
return CGSize(width: textLabel.size.width + 32, height: chipButtonHeight)
}
override var isHighlighted: Bool {
didSet {
backgroundColor = isSelected
? (isHighlighted ? UIColor.c.cpp : UIColor.c.cpn)
: (isHighlighted ? UIColor.c.csep : UIColor.c.csen)
}
}
override var isSelected: Bool {
didSet {
backgroundColor = isSelected
? UIColor.c.cpn
: UIColor.c.csen
layer.borderWidth = isSelected ? 1 : 0
}
}
override var isEnabled: Bool {
didSet {
textLabel.textColor = isEnabled
? UIColor.c.ctpn
: UIColor.c.ctd
backgroundColor = isEnabled
? UIColor.c.csen
: UIColor.c.csed
}
}
}
class EPChipCenterIconButton: EPChipButton {
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = .c.csen // EPSystemToken.color(.surfaceElementNormal)
layer.borderWidth = 0
defaultIconColor = .c.ctpn
addSubview(iconView)
iconView.snp.makeConstraints { make in
make.center.equalToSuperview()
// make.height.equalTo(chipButtonHeight)
}
}
override func setupTheme() {
super.setupTheme()
layer.borderColor = UIColor.c.cpvn.cgColor // EPSystemToken.color(.primaryVariantNormal).cgColor
}
override var iconSize: CGSize {
return .init(width: 20, height: 20)
}
override var isHighlighted: Bool {
didSet {
backgroundColor = isSelected
? (isHighlighted ? UIColor.c.cpp : UIColor.c.cpn)
: (isHighlighted ? UIColor.c.csep : UIColor.c.csen)
}
}
override var isSelected: Bool {
didSet {
backgroundColor = isSelected
? UIColor.c.cpn
: UIColor.c.csen
layer.borderWidth = isSelected ? 1 : 0
}
}
override var isEnabled: Bool {
didSet {
textLabel.textColor = isEnabled
? UIColor.c.ctpn
: UIColor.c.ctd
backgroundColor = isEnabled
? UIColor.c.csen
: UIColor.c.csed
}
}
override func layoutSubviews() {
super.layoutSubviews()
layer.cornerRadius = bounds.size.height * 0.5
}
}
// MARK: - EPChipDropdownButton
class EPChipDropdownButton: EPChipButton {
var needTransform: Bool = true
override init(frame: CGRect) {
super.init(frame: frame)
stack.spacing = 4
addSubview(stack)
stack.snp.makeConstraints { make in
make.edges.equalTo(self).inset(paddingInsets)
make.height.equalTo(chipButtonHeight)
}
stack.addArrangedSubview(textLabel)
stack.addArrangedSubview(iconView)
iconView.snp.makeConstraints { make in
make.size.equalTo(iconSize)
}
}
override func setupTheme() {
super.setupTheme()
textLabel.textColor = isSelected
? UIColor.c.cpvn
: UIColor.c.ctpn
iconView.image = isSelected ? selectedIcon : defaultIcon
}
override var paddingInsets: UIEdgeInsets {
UIEdgeInsets(top: 0, left: 16, bottom: 0, right: 8)
}
override var iconSize: CGSize {
CGSize(width: 12, height: 12)
}
override var defaultIcon: UIImage? {
let color = UIColor.c.ctsn // EPSystemToken.color(.txtSecondaryNormal)
return MWIconFont.image(fromIconInt: iconCode.rawValue, size: iconSize, color: color, edgeInsets: .zero)
}
override var selectedIcon: UIImage? {
let color = UIColor.c.cpvn // EPSystemToken.color(.primaryVariantNormal)
return MWIconFont.image(fromIconInt: iconCode.rawValue, size: iconSize, color: color, edgeInsets: .zero)
}
override var isHighlighted: Bool {
didSet {
backgroundColor = isHighlighted ? UIColor.c.csep : nil
}
}
override var isSelected: Bool {
didSet {
textLabel.textColor = isSelected
? UIColor.c.cpvn
: UIColor.c.ctpn
UIView.animate(withDuration: 0.2) {
if self.needTransform {
self.iconView.transform = self.isSelected ? CGAffineTransform(rotationAngle: .pi) : .identity
}
self.iconView.image = self.isSelected ? self.selectedIcon : self.defaultIcon
}
}
}
}
// MARK: - EPChipRemovableButton
class EPChipRemovableButton: EPChipButton {
override init(frame: CGRect) {
super.init(frame: frame)
stack.spacing = 8
addSubview(stack)
stack.snp.makeConstraints { make in
make.edges.equalTo(self).inset(paddingInsets).priority(998)
make.height.equalTo(chipButtonHeight)
}
stack.addArrangedSubview(textLabel)
stack.addArrangedSubview(iconView)
iconView.snp.makeConstraints { make in
make.size.equalTo(iconSize)
}
}
override func setupTheme() {
super.setupTheme()
backgroundColor = .c.csen
iconView.image = defaultIcon
}
override var paddingInsets: UIEdgeInsets {
UIEdgeInsets(top: 0, left: 12, bottom: 0, right: 12)
}
override var iconSize: CGSize {
CGSize(width: 16, height: 16)
}
override var defaultIcon: UIImage? {
let color = UIColor.c.ctsn // EPSystemToken.color(.txtSecondaryNormal)
return MWIconFont.image(fromIconInt: iconCode.rawValue, size: iconSize, color: color, edgeInsets: .zero)
}
override var selectedIcon: UIImage? {
let color = UIColor.c.cpvn
return MWIconFont.image(fromIconInt: iconCode.rawValue, size: iconSize, color: color, edgeInsets: .zero)
}
override var isHighlighted: Bool {
didSet {
backgroundColor = isHighlighted
? UIColor.c.csep
: UIColor.c.csen
}
}
func widthPreCal(tagHeight: CGFloat) -> CGFloat {
let paddingInsets = self.paddingInsets
return textLabel.sizeThatFits(CGSize(width: .greatestFiniteMagnitude, height: tagHeight)).width +
paddingInsets.left + paddingInsets.right + iconSize.width + stack.spacing
}
func setupHasImageMode() {
stack.insertArrangedSubview(imageView, at: 0)
imageView.isHidden = false
imageView.snp.makeConstraints { make in
make.size.equalTo(imageSize)
}
}
}
// MARK: - EPChipAssistButton
/// egInterestsAdd
class EPChipAssistButton: EPChipButton {
var iconTextSpacing: CGFloat = 8 {
didSet {
stack.spacing = iconTextSpacing
}
}
var buttonHeight: CGFloat = 32 {
didSet {
layer.cornerRadius = buttonHeight * 0.5
stack.snp.updateConstraints { make in
make.height.equalTo(buttonHeight)
}
}
}
override init(frame: CGRect) {
super.init(frame: frame)
stack.spacing = 8
addSubview(stack)
stack.snp.makeConstraints { make in
make.edges.equalTo(self).inset(paddingInsets)
make.height.equalTo(chipButtonHeight)
}
stack.addArrangedSubview(iconView)
stack.addArrangedSubview(textLabel)
iconView.snp.makeConstraints { make in
make.size.equalTo(iconSize)
}
}
override func setupTheme() {
super.setupTheme()
backgroundColor = .c.csen // EPSystemToken.color(.surfaceElementNormal)
iconView.image = defaultIcon
}
override var paddingInsets: UIEdgeInsets {
UIEdgeInsets(top: 0, left: 12, bottom: 0, right: 12)
}
override var iconSize: CGSize {
CGSize(width: 16, height: 16)
}
override var defaultIcon: UIImage? {
let color = defaultIconColor ?? UIColor.c.ctsn // EPSystemToken.color(.txtSecondaryNormal)
return MWIconFont.image(fromIconInt: iconCode.rawValue, size: iconSize, color: color, edgeInsets: .zero)
}
// override var isHighlighted: Bool {
// didSet {
// backgroundColor = isHighlighted
// ? UIColor.c.csep
// : UIColor.c.csen
// }
// }
override var isSelected: Bool {
didSet {
backgroundColor = isSelected
? UIColor.c.cpn
: UIColor.c.csen
//layer.borderWidth = isSelected ? 1 : 0
}
}
func setDefaultImage(_ image: UIImage?) {
iconView.image = image
}
func setIconSize(_ size: CGSize) {
iconView.snp.updateConstraints { make in
make.size.equalTo(size)
}
}
func widthPreCal(tagHeight: CGFloat) -> CGFloat {
let paddingInsets = self.paddingInsets
return textLabel.sizeThatFits(CGSize(width: .greatestFiniteMagnitude, height: tagHeight)).width +
paddingInsets.left + paddingInsets.right + iconSize.width + stack.spacing
}
}
// MARK: - EPChipContrastButton:EPChipAssistButton
/// Like EPIconContrastTertiaryButton,
class EPChipContrastButton:EPChipAssistButton {
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = .c.csedn
buttonHeight = 48
defaultIconColor = .white
textLabel.font = .t.tll
}
override var paddingInsets: UIEdgeInsets {
UIEdgeInsets(top: 0, left: 32, bottom: 0, right: 32)
}
override var iconSize: CGSize {
CGSize(width: 24, height: 24)
}
}
// MARK: - EPChipImageIconButton
/// image++iconFont
class EPChipImageIconButton: EPChipFilterButton {
override init(frame: CGRect) {
super.init(frame: frame)
stack.spacing = 8
addSubview(stack)
stack.snp.makeConstraints { make in
make.edges.equalTo(self).inset(paddingInsets)
make.height.equalTo(chipButtonHeight)
}
stack.addArrangedSubview(imageView)
stack.addArrangedSubview(textLabel)
stack.addArrangedSubview(iconView)
imageView.snp.makeConstraints { make in
make.size.equalTo(imageSize)
}
iconView.snp.makeConstraints { make in
make.size.equalTo(iconSize)
}
imageView.isHidden = true
iconView.isHidden = true
}
override var paddingInsets: UIEdgeInsets {
UIEdgeInsets(top: 0, left: 16, bottom: 0, right: 16)
}
override var iconSize: CGSize {
CGSize(width: 16, height: 16)
}
override var imageSize: CGSize {
CGSize(width: 16, height: 16)
}
override var defaultIcon: UIImage? {
let color = UIColor.c.ctsn // EPSystemToken.color(.txtSecondaryNormal)
return MWIconFont.image(fromIconInt: iconCode.rawValue, size: iconSize, color: color, edgeInsets: .zero)
}
override var selectedIcon: UIImage? {
let color = UIColor.c.cswn // EPSystemToken.color(.surfaceWhiteNormal)
return MWIconFont.image(fromIconInt: iconCode.rawValue, size: iconSize, color: color, edgeInsets: .zero)
}
override var isSelected: Bool {
didSet {
iconView.image = isSelected ? selectedIcon : defaultIcon
imageView.image = isSelected ? selectedImage : defaultImage
}
}
func reloadPadding(showImage: Bool, showIcon: Bool) {
var leftPadding: CGFloat = 16
var rightPadding: CGFloat = 16
if showImage {
leftPadding = 12
}
if showIcon {
rightPadding = 12
}
stack.snp.remakeConstraints { make in
make.edges.equalTo(self).inset(UIEdgeInsets(top: 0, left: leftPadding, bottom: 0, right: rightPadding))
make.height.equalTo(chipButtonHeight)
}
}
}