// // LNUserRelationViewController.swift // Lanu // // Created by OneeChan on 2025/12/19. // import Foundation import UIKit import SnapKit extension UIView { func pushToRelationList(uid: String, tabType: LNUserRelationTabType = .follow) { let vc = LNUserRelationViewController() navigationController?.pushViewController(vc, animated: true) vc.locatedTo(tabType) } } enum LNUserRelationTabType: CaseIterable { case follow case fans } class LNUserRelationViewController: LNViewController { private var curTabType: LNUserRelationTabType = .follow { didSet { locatedTabTo(curTabType, animated: true) } } private let tabIndicator = UIImageView() private let followLabel = UILabel() private let fansLabel = UILabel() private let scrollView = UIScrollView() private let followList = LNUserRelationListView(curType: .follow) private let fansList = LNUserRelationListView(curType: .fans) override func viewDidLoad() { super.viewDidLoad() setupViews() let tabType = curTabType curTabType = tabType } func locatedTo(_ tab: LNUserRelationTabType) { view.layoutIfNeeded() curTabType = tab } } extension LNUserRelationViewController: LNUserRelationListViewDelegate { func onUserRelationListViewTotalChanged(view: LNUserRelationListView, total: Int) { switch view.curType { case .fans: fansLabel.text = .init(key: "A00234", total) case .follow: followLabel.text = .init(key: "A00238", total) } } } extension LNUserRelationViewController: UIScrollViewDelegate { func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { let page = Int(scrollView.contentOffset.x / scrollView.bounds.width) let tab = LNUserRelationTabType.allCases[page] locatedTabTo(tab, animated: true) } } extension LNUserRelationViewController { private func scrollTo(_ tab: LNUserRelationTabType, animated: Bool) { let page = LNUserRelationTabType.allCases.firstIndex(of: tab) ?? 0 let offsetX = scrollView.bounds.width * CGFloat(page) scrollView.setContentOffset(.init(x: offsetX, y: 0), animated: animated) } private func locatedTabTo(_ tab: LNUserRelationTabType, animated: Bool) { let targetTab: UIView? switch tab { case .follow: targetTab = followLabel.superview followLabel.textColor = .text_5 fansLabel.textColor = .text_2 case .fans: targetTab = fansLabel.superview followLabel.textColor = .text_2 fansLabel.textColor = .text_5 } guard let targetTab else { return } tabIndicator.snp.remakeConstraints { make in make.center.equalTo(targetTab) make.height.equalTo(16) } scrollTo(tab, animated: animated) if animated { UIView.animate(withDuration: 0.25) { [weak self] in guard let self else { return } followLabel.superview?.superview?.layoutIfNeeded() } } } private func setupViews() { setupNavBar() scrollView.delegate = self scrollView.isPagingEnabled = true scrollView.showsVerticalScrollIndicator = false scrollView.showsHorizontalScrollIndicator = false view.addSubview(scrollView) scrollView.snp.makeConstraints { make in make.horizontalEdges.equalToSuperview() make.bottom.equalToSuperview() make.top.equalToSuperview() } followList.delegate = self scrollView.addSubview(followList) followList.snp.makeConstraints { make in make.verticalEdges.equalToSuperview() make.leading.equalToSuperview() make.width.height.equalToSuperview() } fansList.delegate = self scrollView.addSubview(fansList) fansList.snp.makeConstraints { make in make.verticalEdges.equalToSuperview() make.trailing.equalToSuperview() make.leading.equalTo(followList.snp.trailing) make.width.height.equalToSuperview() } } private func setupNavBar() { let stackView = UIStackView() stackView.axis = .horizontal stackView.spacing = 0 stackView.distribution = .fillEqually setTitleView(stackView) stackView.snp.makeConstraints { make in make.width.equalTo(view.bounds.width).priority(.medium) make.height.equalTo(44) } tabIndicator.image = .icHomeTabSelected tabIndicator.contentMode = .scaleAspectFit stackView.addSubview(tabIndicator) let followButton = UIButton() followButton.addAction(UIAction(handler: { [weak self] _ in guard let self else { return } curTabType = .follow }), for: .touchUpInside) stackView.addArrangedSubview(followButton) followLabel.font = .heading_h3 followLabel.textColor = .text_5 followLabel.text = .init(key: "A00238", 0) followButton.addSubview(followLabel) followLabel.snp.makeConstraints { make in make.center.equalToSuperview() } let fansButton = UIButton() fansButton.addAction(UIAction(handler: { [weak self] _ in guard let self else { return } curTabType = .fans }), for: .touchUpInside) stackView.addArrangedSubview(fansButton) fansLabel.font = .heading_h3 fansLabel.textColor = .text_5 fansLabel.text = .init(key: "A00234", 0) fansButton.addSubview(fansLabel) fansLabel.snp.makeConstraints { make in make.center.equalToSuperview() } } }