// // TagPickerView.swift // VenusKitto // // Created by Neoa on 2025/8/25. // import Foundation import UIKit final class TagPickerView: UIView { private let overlay = UIControl() private let panel = UIView() private var tagStackView: UIStackView! private var selectedTags: Set = [] private let titleLabel = UILabel() private let closeButton = UIButton(type: .system) private let backButton = UIButton(type: .system) var onTagSelected: ((String) -> Void)? override init(frame: CGRect) { super.init(frame: frame) setupUI() } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } private func setupUI() { backgroundColor = UIColor.black.withAlphaComponent(0.5) // overlay to close picker overlay.addTarget(self, action: #selector(closeTagPicker), for: .touchUpInside) overlay.isHidden = true overlay.alpha = 0 addSubview(overlay) // panel (the actual tag picker view) panel.backgroundColor = .white panel.layer.cornerRadius = 16 panel.isHidden = true panel.alpha = 0 addSubview(panel) // titleLabel titleLabel.text = "选择标签" titleLabel.font = .systemFont(ofSize: 18, weight: .semibold) titleLabel.textColor = UIColor(hex: "#2B2B2B") titleLabel.textAlignment = .center // close button closeButton.setImage(UIImage(named: "AddPet384")?.withRenderingMode(.alwaysOriginal), for: .normal) closeButton.tintColor = UIColor(hex: "#2B2B2B") closeButton.addTarget(self, action: #selector(closeTagPicker), for: .touchUpInside) // back button backButton.setImage(UIImage(named: "backIcon")?.withRenderingMode(.alwaysOriginal), for: .normal) backButton.tintColor = UIColor(hex: "#2B2B2B") backButton.addTarget(self, action: #selector(backButtonTapped), for: .touchUpInside) // Add title, back and close buttons to panel [backButton, titleLabel, closeButton].forEach { panel.addSubview($0) } // Add tagStackView to the panel tagStackView = UIStackView() tagStackView.axis = .vertical tagStackView.spacing = 16 panel.addSubview(tagStackView) // Layout constraints overlay.translatesAutoresizingMaskIntoConstraints = false panel.translatesAutoresizingMaskIntoConstraints = false titleLabel.translatesAutoresizingMaskIntoConstraints = false closeButton.translatesAutoresizingMaskIntoConstraints = false backButton.translatesAutoresizingMaskIntoConstraints = false tagStackView.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ overlay.topAnchor.constraint(equalTo: topAnchor), overlay.leadingAnchor.constraint(equalTo: leadingAnchor), overlay.trailingAnchor.constraint(equalTo: trailingAnchor), overlay.bottomAnchor.constraint(equalTo: bottomAnchor), panel.centerXAnchor.constraint(equalTo: centerXAnchor), panel.centerYAnchor.constraint(equalTo: centerYAnchor), panel.widthAnchor.constraint(equalTo: widthAnchor, multiplier: 1), backButton.leadingAnchor.constraint(equalTo: panel.leadingAnchor, constant: 12), backButton.topAnchor.constraint(equalTo: panel.topAnchor, constant: 12), backButton.widthAnchor.constraint(equalToConstant: 24), backButton.heightAnchor.constraint(equalToConstant: 24), titleLabel.topAnchor.constraint(equalTo: panel.topAnchor, constant: 12), titleLabel.centerXAnchor.constraint(equalTo: panel.centerXAnchor), closeButton.trailingAnchor.constraint(equalTo: panel.trailingAnchor, constant: -12), closeButton.topAnchor.constraint(equalTo: panel.topAnchor, constant: 12), closeButton.widthAnchor.constraint(equalToConstant: 24), closeButton.heightAnchor.constraint(equalToConstant: 24), tagStackView.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 16), tagStackView.leadingAnchor.constraint(equalTo: panel.leadingAnchor, constant: 16), tagStackView.trailingAnchor.constraint(equalTo: panel.trailingAnchor, constant: -16), tagStackView.bottomAnchor.constraint(equalTo: panel.bottomAnchor, constant: -16) ]) buildTagSection() } private func buildTagSection() { let categories: [(String, [String])] = [ ("日常事项", ["吃饭", "喝水", "喂奶", "尿便", "铲屎"]), ("健康事项", ["驱虫", "喂药", "疫苗", "看病", "体检"]), ("清洁事项", ["洗澡", "梳毛", "剪指甲", "洗耳朵", "挤肛门腺"]), ("打扫事项", ["洗笼子","洗食盆","洗水盆","洗玩具","换耗材"]) ] for (category, items) in categories { let sectionView = createTagSection(title: category, items: items) tagStackView.addArrangedSubview(sectionView) } } private func createTagSection(title: String, items: [String]) -> UIView { let sectionView = UIView() let sectionTitle = UILabel() sectionTitle.text = title sectionTitle.font = .systemFont(ofSize: 13, weight: .semibold) sectionTitle.textColor = UIColor(hex: "#000000") sectionView.addSubview(sectionTitle) let tagsStackView = UIStackView() tagsStackView.axis = .horizontal tagsStackView.spacing = 12 tagsStackView.distribution = .fillEqually sectionView.addSubview(tagsStackView) sectionTitle.translatesAutoresizingMaskIntoConstraints = false tagsStackView.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ sectionTitle.topAnchor.constraint(equalTo: sectionView.topAnchor), sectionTitle.leadingAnchor.constraint(equalTo: sectionView.leadingAnchor), sectionTitle.trailingAnchor.constraint(equalTo: sectionView.trailingAnchor), sectionTitle.heightAnchor.constraint(equalToConstant: 20), tagsStackView.topAnchor.constraint(equalTo: sectionTitle.bottomAnchor, constant: 8), tagsStackView.leadingAnchor.constraint(equalTo: sectionView.leadingAnchor), tagsStackView.trailingAnchor.constraint(equalTo: sectionView.trailingAnchor), tagsStackView.bottomAnchor.constraint(equalTo: sectionView.bottomAnchor) ]) for tag in items { let tagButton = createTagButton(title: tag) tagsStackView.addArrangedSubview(tagButton) } return sectionView } private func createTagButton(title: String) -> UIView { let holder = UIView() // Create the image view for the tag icon (peihead) let imageView = UIImageView(image: UIImage(named: "peihead")) imageView.contentMode = .scaleAspectFit imageView.translatesAutoresizingMaskIntoConstraints = false imageView.widthAnchor.constraint(equalToConstant: 40).isActive = true imageView.heightAnchor.constraint(equalToConstant: 40).isActive = true // Create the label for the tag title let label = UILabel() label.text = title label.font = .systemFont(ofSize: 12) label.textColor = UIColor(hex: "#6B6B6B") label.textAlignment = .center label.translatesAutoresizingMaskIntoConstraints = false // Stack the image and label vertically let stackView = UIStackView(arrangedSubviews: [imageView, label]) stackView.axis = .vertical stackView.alignment = .center stackView.spacing = 6 stackView.translatesAutoresizingMaskIntoConstraints = false holder.addSubview(stackView) NSLayoutConstraint.activate([ stackView.topAnchor.constraint(equalTo: holder.topAnchor), stackView.bottomAnchor.constraint(equalTo: holder.bottomAnchor), stackView.leadingAnchor.constraint(equalTo: holder.leadingAnchor), stackView.trailingAnchor.constraint(equalTo: holder.trailingAnchor) ]) // Full-size invisible button to capture taps let tap = UIButton(type: .system) tap.backgroundColor = .clear tap.accessibilityLabel = title tap.addTarget(self, action: #selector(tagButtonTapped(_:)), for: .touchUpInside) holder.addSubview(tap) tap.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ tap.topAnchor.constraint(equalTo: holder.topAnchor), tap.bottomAnchor.constraint(equalTo: holder.bottomAnchor), tap.leadingAnchor.constraint(equalTo: holder.leadingAnchor), tap.trailingAnchor.constraint(equalTo: holder.trailingAnchor) ]) return holder } @objc private func tagButtonTapped(_ sender: UIButton) { guard let tag = sender.accessibilityLabel else { return } onTagSelected?(tag) // Handle the tag selection here print("Selected tag: \(tag)") hide() } func show() { overlay.isHidden = false panel.isHidden = false UIView.animate(withDuration: 0.2) { self.overlay.alpha = 1 self.panel.alpha = 1 } } func hide() { UIView.animate(withDuration: 0.2, animations: { self.overlay.alpha = 0 self.panel.alpha = 0 }) { _ in self.overlay.isHidden = true self.panel.isHidden = true self.isHidden = true } } @objc private func closeTagPicker() { hide() } @objc private func backButtonTapped() { // Handle the back button logic here print("Back button tapped") } }