| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167 |
- //
- // ChannelSelectPopView.swift
- // RoderickRalph
- //
- // Created by Neoa on 2025/9/2.
- //
- import Foundation
- import UIKit
- // MARK: - Channel Models & Popup
- struct Channel: Codable, Hashable {
- let id: String
- let name: String
- }
- protocol RoutePickerAgent: AnyObject {
- func routePicker(_ panel: RoutePickerView, didPick channel: Channel)
- }
- class RoutePickerView: UIView {
- weak var delegate: RoutePickerAgent?
- private let channels: [Channel]
- private let backdropView: UIView = {
- let v = UIView()
- v.backgroundColor = UIColor.black.withAlphaComponent(0.5)
- v.translatesAutoresizingMaskIntoConstraints = false
- return v
- }()
- private let cardImageView: UIImageView = {
- let imageView = UIImageView()
- imageView.image = UIImage(named: "res_ew6zkg25")
- imageView.contentMode = .scaleToFill
- imageView.translatesAutoresizingMaskIntoConstraints = false
- return imageView
- }()
- private let titleRibbon: UIButton = {
- let button = UIButton(type: .system)
- button.setBackgroundImage(UIImage(named: "res_x8brwne3"), for: .normal)
- button.setTitle("请选择渠道", for: .normal)
- button.setTitleColor(.white, for: .normal)
- button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 18)
- button.translatesAutoresizingMaskIntoConstraints = false
- button.isUserInteractionEnabled = false
- return button
- }()
- private let scroller: UIScrollView = {
- let sv = UIScrollView()
- sv.translatesAutoresizingMaskIntoConstraints = false
- return sv
- }()
- private let stacker: UIStackView = {
- let sv = UIStackView()
- sv.axis = .vertical
- sv.spacing = 10
- sv.alignment = .fill
- sv.distribution = .fill
- sv.translatesAutoresizingMaskIntoConstraints = false
- return sv
- }()
- private let dismissBtn: UIButton = {
- let button = UIButton(type: .custom)
- button.setImage(UIImage(named: "res_9mx2yiyi"), for: .normal)
- button.translatesAutoresizingMaskIntoConstraints = false
- return button
- }()
- init(channels: [Channel]) {
- self.channels = channels
- super.init(frame: .zero)
- buildUI()
- applyLayout()
- inflateChannels()
- }
- required init?(coder: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
- private func buildUI() {
- addSubview(backdropView)
- addSubview(cardImageView)
- addSubview(titleRibbon)
- addSubview(scroller)
- scroller.addSubview(stacker)
- addSubview(dismissBtn)
- dismissBtn.isHidden = true
-
- dismissBtn.addTarget(self, action: #selector(closePanel), for: .touchUpInside)
- // Tap to dismiss on the dim background
- let tapGesture = UITapGestureRecognizer(target: self, action: #selector(closePanel))
- backdropView.addGestureRecognizer(tapGesture)
- }
- private func applyLayout() {
- NSLayoutConstraint.activate([
- backdropView.topAnchor.constraint(equalTo: topAnchor),
- backdropView.bottomAnchor.constraint(equalTo: bottomAnchor),
- backdropView.leadingAnchor.constraint(equalTo: leadingAnchor),
- backdropView.trailingAnchor.constraint(equalTo: trailingAnchor),
- cardImageView.centerXAnchor.constraint(equalTo: centerXAnchor),
- cardImageView.centerYAnchor.constraint(equalTo: centerYAnchor),
- cardImageView.widthAnchor.constraint(equalToConstant: 333),
- cardImageView.heightAnchor.constraint(equalToConstant: 333),
- titleRibbon.topAnchor.constraint(equalTo: cardImageView.topAnchor, constant: 10),
- titleRibbon.centerXAnchor.constraint(equalTo: cardImageView.centerXAnchor),
- titleRibbon.widthAnchor.constraint(equalToConstant: 132),
- titleRibbon.heightAnchor.constraint(equalToConstant: 37),
- scroller.topAnchor.constraint(equalTo: titleRibbon.bottomAnchor, constant: 12),
- scroller.leadingAnchor.constraint(equalTo: cardImageView.leadingAnchor, constant: 20),
- scroller.trailingAnchor.constraint(equalTo: cardImageView.trailingAnchor, constant: -20),
- scroller.bottomAnchor.constraint(equalTo: cardImageView.bottomAnchor, constant: -20),
- stacker.topAnchor.constraint(equalTo: scroller.topAnchor),
- stacker.leadingAnchor.constraint(equalTo: scroller.leadingAnchor),
- stacker.trailingAnchor.constraint(equalTo: scroller.trailingAnchor),
- stacker.bottomAnchor.constraint(equalTo: scroller.bottomAnchor),
- stacker.widthAnchor.constraint(equalTo: scroller.widthAnchor),
- dismissBtn.topAnchor.constraint(equalTo: cardImageView.topAnchor, constant: -12),
- dismissBtn.trailingAnchor.constraint(equalTo: cardImageView.trailingAnchor, constant: 12),
- dismissBtn.widthAnchor.constraint(equalToConstant: 24),
- dismissBtn.heightAnchor.constraint(equalToConstant: 24)
- ])
- }
- private func makeChannelButton(title: String) -> UIButton {
- let button = UIButton(type: .system)
- button.setBackgroundImage(UIImage(named: "res_ux9fin4y"), for: .normal)
- button.setTitle(title, for: .normal)
- button.setTitleColor(.white, for: .normal)
- button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 16)
- button.contentHorizontalAlignment = .center
- button.heightAnchor.constraint(equalToConstant: 45).isActive = true
- return button
- }
- private func inflateChannels() {
- for (idx, channel) in channels.enumerated() {
- let button = makeChannelButton(title: channel.name)
- button.tag = idx
- button.addTarget(self, action: #selector(didTapChannel(_:)), for: .touchUpInside)
- stacker.addArrangedSubview(button)
- }
- }
- @objc private func didTapChannel(_ sender: UIButton) {
- let idx = sender.tag
- guard idx >= 0 && idx < channels.count else { return }
- let channel = channels[idx]
- delegate?.routePicker(self, didPick: channel)
- }
- @objc private func closePanel() {
- // removeFromSuperview()
- }
- }
|