| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207 |
- //
- // LNMultiSelectionPanel.swift
- // Gami
- //
- // Created by OneeChan on 2026/1/20.
- //
- import Foundation
- import UIKit
- import SnapKit
- class LNMultiSelectionPanel: LNPopupView {
- private var minCount: Int = 0
- private var maxCount: Int = 0
-
- private let titleLabel = UILabel()
- private let descLabel = UILabel()
- private let stackView = LNMultiLineStackView()
- private let confirmButton = UIButton()
-
- private var itemViews: [LNMultiSelectPanelItemView] = []
- private var curSelection: [Int] {
- var indexs: [Int] = []
- for (index, itemView) in itemViews.enumerated() {
- if itemView.isSelected {
- indexs.append(index)
- }
- }
- return indexs
- }
-
- var handler: (([Int]) -> Void)?
-
- override init(frame: CGRect) {
- super.init(frame: frame)
-
- setupViews()
- }
-
- func setTitles(_ title: String, desc: String? = nil) {
- titleLabel.text = title
- descLabel.text = desc
- descLabel.isHidden = desc?.isEmpty != false
- }
-
- func update(_ items: [String], curSelected: [String]) {
- var views: [LNMultiSelectPanelItemView] = []
- for item in items {
- let itemView = LNMultiSelectPanelItemView()
- itemView.titleLabel.text = item
- itemView.isSelected = curSelected.contains(item)
- itemView.onTap { [weak self, weak itemView] in
- guard let self, let itemView else { return }
- itemView.isSelected.toggle()
- if maxCount > 0, curSelection.count >= maxCount {
- itemViews.forEach {
- $0.isEnable = $0.isSelected
- }
- } else {
- itemViews.forEach {
- $0.isEnable = true
- }
- }
- updateConfirm()
- }
-
- views.append(itemView)
- }
-
- itemViews = views
- stackView.update(views)
- updateConfirm()
- }
-
- func setLimie(min: Int, max: Int) {
- minCount = min
- maxCount = max
- }
-
- required init?(coder: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
- }
- extension LNMultiSelectionPanel {
- private func updateConfirm() {
- let isEmpty = if minCount > 0 {
- curSelection.count < minCount
- } else {
- curSelection.isEmpty
- }
- if isEmpty == confirmButton.isEnabled {
- confirmButton.isEnabled = !isEmpty
- confirmButton.setBackgroundImage(isEmpty ? nil : .primary_8, for: .normal)
- }
- }
-
- private func setupViews() {
- let headerView = buildHeader()
- container.addSubview(headerView)
- headerView.snp.makeConstraints { make in
- make.horizontalEdges.equalToSuperview()
- make.top.equalToSuperview()
- make.height.equalTo(56)
- }
-
- let selection = buildSelection()
- container.addSubview(selection)
- selection.snp.makeConstraints { make in
- make.horizontalEdges.equalToSuperview().inset(21)
- make.top.equalTo(headerView.snp.bottom).offset(16)
- }
-
- confirmButton.setTitle(.init(key: "A00223"), for: .normal)
- confirmButton.setTitleColor(.text_1, for: .normal)
- confirmButton.titleLabel?.font = .heading_h3
- confirmButton.layer.cornerRadius = 23.5
- confirmButton.clipsToBounds = true
- confirmButton.isEnabled = false
- confirmButton.backgroundColor = .fill_4
- confirmButton.addAction(UIAction(handler: { [weak self] _ in
- guard let self else { return }
- dismiss()
- handler?(curSelection)
- }), for: .touchUpInside)
- container.addSubview(confirmButton)
- confirmButton.snp.makeConstraints { make in
- make.horizontalEdges.equalToSuperview().inset(16)
- make.top.equalTo(selection.snp.bottom).offset(24)
- make.bottom.equalToSuperview().offset(commonBottomInset)
- make.height.equalTo(47)
- }
- }
-
- private func buildHeader() -> UIView {
- let container = UIView()
-
- let stackView = UIStackView()
- stackView.axis = .vertical
- stackView.spacing = 3
- container.addSubview(stackView)
- stackView.snp.makeConstraints { make in
- make.center.equalToSuperview()
- }
-
- titleLabel.font = .heading_h3
- titleLabel.textColor = .text_5
- titleLabel.textAlignment = .center
- stackView.addArrangedSubview(titleLabel)
-
- descLabel.font = .body_s
- descLabel.textColor = .text_3
- descLabel.textAlignment = .center
- stackView.addArrangedSubview(descLabel)
-
- return container
- }
-
- private func buildSelection() -> UIView {
- stackView.columns = 3
- stackView.itemSpacing = 16
- stackView.spacing = 20
-
- return stackView
- }
- }
- private class LNMultiSelectPanelItemView: UIView {
- let titleLabel = UILabel()
-
- var isSelected: Bool = false {
- didSet {
- backgroundColor = isSelected ? .fill_5 : .fill_1
- titleLabel.font = isSelected ? .heading_h5 : .body_s
- titleLabel.textColor = isSelected ? .text_6 : .text_4
- }
- }
- var isEnable: Bool = true {
- didSet {
- isUserInteractionEnabled = isEnable
- alpha = isEnable ? 1.0 : 0.5
- }
- }
-
- override init(frame: CGRect) {
- super.init(frame: frame)
-
- layer.cornerRadius = 13
- snp.makeConstraints { make in
- make.height.equalTo(26)
- }
-
- titleLabel.textAlignment = .center
- addSubview(titleLabel)
- titleLabel.snp.makeConstraints { make in
- make.centerY.equalToSuperview()
- make.horizontalEdges.equalToSuperview().inset(7)
- }
-
- isSelected = false
- }
-
- required init?(coder: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
- }
|