// // LNHomeGameTabView.swift // Lanu // // Created by OneeChan on 2025/11/14. // import Foundation import UIKit import SnapKit protocol LNHomeGameTabViewDelegate: AnyObject { func homeGameTabView(view: LNHomeGameTabView, didSelect category: LNGameCategoryItemVO?) func homeGameTabViewClickMore(view: LNHomeGameTabView) } class LNHomeGameTabView: UIView { private(set) var curGame: LNGameCategoryItemVO? { didSet { guard oldValue?.code != curGame?.code else { return } tabItemViews.forEach { $0.setSelected(curGame?.code == $0.item?.code) } delegate?.homeGameTabView(view: self, didSelect: curGame) } } private let indicator = UIImageView() private let stackView = UIStackView() private var tabItemViews: [LNHomeGameTabItemView] = [] weak var delegate: LNHomeGameTabViewDelegate? override init(frame: CGRect) { super.init(frame: frame) setupViews() } func update(_ games: [LNGameCategoryItemVO]) { let itemViews = stackView.arrangedSubviews itemViews.forEach { stackView.removeArrangedSubview($0) $0.removeFromSuperview() } tabItemViews.removeAll() games.prefix(3).forEach { item in let itemView = LNHomeGameTabItemView() itemView.onTap { [weak self, weak itemView] in guard let self, let itemView else { return } let animated = self.curGame != nil if self.curGame?.code == item.code { self.curGame = nil self.indicator.isHidden = true } else { self.curGame = item self.indicator.isHidden = false } handleSelectAt(itemView, animated: animated) } itemView.update(item) stackView.addArrangedSubview(itemView) tabItemViews.append(itemView) } } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } } extension LNHomeGameTabView { private func handleSelectAt(_ itemView: LNHomeGameTabItemView, animated: Bool = true) { indicator.snp.remakeConstraints { make in make.horizontalEdges.equalTo(itemView) make.bottom.equalToSuperview() } if animated { UIView.animate(withDuration: 0.25) { [weak self] in guard let self else { return } self.layoutIfNeeded() } } } private func setupViews() { indicator.image = .icHomeGameTabSelected addSubview(indicator) let moreView = LNHomeGameTabItemView() moreView.toBeMoreTab() moreView.onTap { [weak self] in guard let self else { return } self.delegate?.homeGameTabViewClickMore(view: self) } addSubview(moreView) moreView.snp.makeConstraints { make in make.top.equalToSuperview() make.trailing.equalToSuperview() } stackView.axis = .horizontal stackView.distribution = .fillEqually addSubview(stackView) stackView.snp.makeConstraints { make in make.leading.equalToSuperview() make.top.equalToSuperview() make.trailing.equalTo(moreView.snp.leading).offset(-20) } } } #if DEBUG import SwiftUI struct LNHomeGameTabViewPreview: UIViewRepresentable { func makeUIView(context: Context) -> some UIView { let container = UIView() container.backgroundColor = .lightGray let view = LNHomeGameTabView() container.addSubview(view) view.snp.makeConstraints { make in make.leading.trailing.top.equalToSuperview() } return container } func updateUIView(_ uiView: UIViewType, context: Context) { } } #Preview(body: { LNHomeGameTabViewPreview() }) #endif