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

567 lines
16 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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