| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340 |
- //
- // SettingsPopupView.swift
- // RoderickRalph
- //
- // Created by Neoa on 2025/8/19.
- //
- import Foundation
- import UIKit
- // 在文件顶部 import 之后、class 之前加:
- protocol SettingsPopupViewDelegate: AnyObject {
- func settingsPopupViewDidClose(_ view: SettingsPopupView)
- }
- class SettingsPopupView: UIView {
- weak var delegate: SettingsPopupViewDelegate?
-
- // MARK: - UI Components
- private let backgroundView: UIView = {
- let view = UIView()
- view.backgroundColor = UIColor.black.withAlphaComponent(0.5) // Semi-transparent gray background
- view.translatesAutoresizingMaskIntoConstraints = false
- return view
- }()
-
- private let settingButton: UIButton = {
- let button = UIButton(type: .system)
- button.setBackgroundImage(UIImage(named: "pqan333"), for: .normal)
- button.setTitle("设置", for: .normal)
- button.setTitleColor(.white, for: .normal)
- button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 18)
- button.translatesAutoresizingMaskIntoConstraints = false
- return button
- }()
-
-
- private let iconBGView: UIImageView = {
- let iv = UIImageView()
- iv.image = UIImage(named: "pqan336")
- iv.contentMode = .scaleAspectFit
- iv.translatesAutoresizingMaskIntoConstraints = false
- return iv
- }()
- private let iconImageView: UIImageView = {
- let iv = UIImageView()
- iv.image = UIImage(named: "catlogos")
- iv.contentMode = .scaleAspectFit
- iv.layer.cornerRadius = 24
- iv.clipsToBounds = true
- iv.translatesAutoresizingMaskIntoConstraints = false
- return iv
- }()
- private let nikNmeLeftLabel: UILabel = {
- let label = UILabel()
- label.text = "昵 称"
- label.font = UIFont.systemFont(ofSize: 12)
- label.textColor = .white
- label.translatesAutoresizingMaskIntoConstraints = false
- return label
- }()
-
- private let nikNmeRightLabel: UILabel = {
- let label = UILabel()
- label.text = "XXXX"
- label.backgroundColor = .white
- label.font = UIFont.systemFont(ofSize: 12)
- label.textColor = UIColor(hexString:"#E28814")
- label.layer.cornerRadius = 4
- label.clipsToBounds = true
- label.textAlignment = .center
- label.translatesAutoresizingMaskIntoConstraints = false
- return label
- }()
- private let roleIDLeftLabel: UILabel = {
- let label = UILabel()
- label.text = "角色ID"
- label.font = UIFont.systemFont(ofSize: 12)
- label.textColor = .white
- label.translatesAutoresizingMaskIntoConstraints = false
- return label
- }()
-
- private let roleIDRightLabel: UILabel = {
- let label = UILabel()
- label.text = "XXXX"
- label.backgroundColor = .white
- label.font = UIFont.systemFont(ofSize: 12)
- label.textColor = UIColor(hexString:"#E28814")
- label.layer.cornerRadius = 4
- label.clipsToBounds = true
- label.textAlignment = .center
- label.translatesAutoresizingMaskIntoConstraints = false
- return label
- }()
-
- private let closeButton: UIButton = {
- let button = UIButton(type: .custom)
- button.setImage(UIImage(named: "pqan334"), for: .normal)
- button.addTarget(self, action: #selector(closePopup), for: .touchUpInside)
- button.translatesAutoresizingMaskIntoConstraints = false
- return button
- }()
- private let musicLeftLabel: UILabel = {
- let label = UILabel()
- label.text = "音乐"
- label.font = UIFont.systemFont(ofSize: 12)
- label.textColor = .white
- label.translatesAutoresizingMaskIntoConstraints = false
- return label
- }()
- private let musicSwitch: UISwitch = {
- let switchControl = UISwitch()
- switchControl.isOn = false
- switchControl.translatesAutoresizingMaskIntoConstraints = false
- return switchControl
- }()
-
- private let soundLeftLabel: UILabel = {
- let label = UILabel()
- label.text = "音效"
- label.font = UIFont.systemFont(ofSize: 12)
- label.textColor = .white
- label.translatesAutoresizingMaskIntoConstraints = false
- return label
- }()
- private let soundSwitch: UISwitch = {
- let switchControl = UISwitch()
- switchControl.isOn = false
- switchControl.translatesAutoresizingMaskIntoConstraints = false
- return switchControl
- }()
- private let registrationTimeLabel: UILabel = {
- let label = UILabel()
- label.text = "注册时间: 2025-05-26 17:58:48"
- label.font = UIFont.systemFont(ofSize: 10)
- label.textColor = .white
- label.translatesAutoresizingMaskIntoConstraints = false
- return label
- }()
-
- private let softwareNameLabel: UILabel = {
- let label = UILabel()
- label.text = "青柠檬记账"
- label.font = UIFont.systemFont(ofSize: 10)
- label.textColor = .white
- label.translatesAutoresizingMaskIntoConstraints = false
- return label
- }()
- private let popupBackgroundImageView: UIImageView = {
- let imageView = UIImageView()
- imageView.image = UIImage(named: "pqan335") // Background image for the pop-up
- imageView.contentMode = .scaleToFill
- imageView.translatesAutoresizingMaskIntoConstraints = false
- return imageView
- }()
- // MARK: - Initialization
- init() {
- super.init(frame: .zero)
- setupUI()
- setupConstraints()
- }
- required init?(coder: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
- // MARK: - UI Setup
- private func setupUI() {
-
- addSubview(backgroundView)
- backgroundView.isUserInteractionEnabled = true // 允许事件穿透
- addSubview(popupBackgroundImageView)
-
- addSubview(settingButton)
- addSubview(iconBGView)
- addSubview(iconImageView)
- addSubview(nikNmeLeftLabel)
- addSubview(nikNmeRightLabel)
- addSubview(roleIDLeftLabel)
- addSubview(roleIDRightLabel)
- addSubview(musicLeftLabel)
- addSubview(soundLeftLabel)
- addSubview(musicSwitch)
- addSubview(soundSwitch)
- addSubview(closeButton)
- addSubview(registrationTimeLabel)
- addSubview(softwareNameLabel)
- // Prefill from saved user info (if available)
- let nickname = UserDefaults.standard.string(forKey: "nickname") ?? "XXXX"
- let roleID = UserDefaults.standard.string(forKey: "roleID") ?? "XXXX"
- let regTime = UserDefaults.standard.string(forKey: "registryTimeStr") ?? "--"
- nikNmeRightLabel.text = nickname
- roleIDRightLabel.text = roleID
- registrationTimeLabel.text = "注册时间: \(regTime)"
- // 显示已选择的渠道名(如果有),否则使用默认占位
- if let savedChannel = UserDefaults.standard.string(forKey: "selectedChannelName"), !savedChannel.isEmpty {
- softwareNameLabel.text = savedChannel
- }
- let head = UserDefaults.standard.string(forKey: "headImgURL")
- setIcon(with: head)
- // 最后添加背景视图(确保它在最底层)
-
- // 添加背景点击手势
- let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleBackgroundTap))
- backgroundView.addGestureRecognizer(tapGesture)
- }
- private func setupConstraints() {
- NSLayoutConstraint.activate([
- // Background (Gray) for the outer area
- backgroundView.topAnchor.constraint(equalTo: topAnchor),
- backgroundView.bottomAnchor.constraint(equalTo: bottomAnchor),
- backgroundView.leadingAnchor.constraint(equalTo: leadingAnchor),
- backgroundView.trailingAnchor.constraint(equalTo: trailingAnchor),
-
- // Popup background image
- popupBackgroundImageView.centerXAnchor.constraint(equalTo: centerXAnchor),
- popupBackgroundImageView.centerYAnchor.constraint(equalTo: centerYAnchor),
- popupBackgroundImageView.widthAnchor.constraint(equalToConstant: 333),
- popupBackgroundImageView.heightAnchor.constraint(equalToConstant: 215),
-
- // Close Button
- closeButton.topAnchor.constraint(equalTo: popupBackgroundImageView.topAnchor, constant: -12),
- closeButton.trailingAnchor.constraint(equalTo: popupBackgroundImageView.trailingAnchor, constant: 12),
- closeButton.widthAnchor.constraint(equalToConstant: 24),
- closeButton.heightAnchor.constraint(equalToConstant: 24),
- settingButton.topAnchor.constraint(equalTo: popupBackgroundImageView.topAnchor, constant: 10),
- settingButton.centerXAnchor.constraint(equalTo: popupBackgroundImageView.centerXAnchor, constant: 0),
- settingButton.widthAnchor.constraint(equalToConstant: 132),
- settingButton.heightAnchor.constraint(equalToConstant: 37),
- iconBGView.topAnchor.constraint(equalTo: settingButton.bottomAnchor, constant: 5),
- iconBGView.leadingAnchor.constraint(equalTo: popupBackgroundImageView.leadingAnchor, constant: 33),
- iconBGView.widthAnchor.constraint(equalToConstant: 58),
- iconBGView.heightAnchor.constraint(equalToConstant: 58),
- iconImageView.centerXAnchor.constraint(equalTo: iconBGView.centerXAnchor),
- iconImageView.centerYAnchor.constraint(equalTo: iconBGView.centerYAnchor),
- iconImageView.widthAnchor.constraint(equalToConstant: 48),
- iconImageView.heightAnchor.constraint(equalToConstant: 48),
-
- nikNmeRightLabel.trailingAnchor.constraint(equalTo: popupBackgroundImageView.trailingAnchor,constant: -35),
- nikNmeRightLabel.topAnchor.constraint(equalTo: settingButton.bottomAnchor,constant: 14),
- nikNmeRightLabel.widthAnchor.constraint(equalToConstant: 130),
- nikNmeRightLabel.heightAnchor.constraint(equalToConstant: 24),
- nikNmeLeftLabel.trailingAnchor.constraint(equalTo: nikNmeRightLabel.leadingAnchor,constant: -12),
- nikNmeLeftLabel.centerYAnchor.constraint(equalTo: nikNmeRightLabel.centerYAnchor,constant: 0),
- roleIDRightLabel.trailingAnchor.constraint(equalTo: nikNmeRightLabel.trailingAnchor,constant: 0),
- roleIDRightLabel.topAnchor.constraint(equalTo: nikNmeRightLabel.bottomAnchor,constant: 3),
- roleIDRightLabel.widthAnchor.constraint(equalToConstant: 130),
- roleIDRightLabel.heightAnchor.constraint(equalToConstant: 24),
-
- roleIDLeftLabel.trailingAnchor.constraint(equalTo: roleIDRightLabel.leadingAnchor,constant: -12),
- roleIDLeftLabel.centerYAnchor.constraint(equalTo: roleIDRightLabel.centerYAnchor,constant: 0),
- musicLeftLabel.leadingAnchor.constraint(equalTo: iconBGView.leadingAnchor,constant: 0),
- musicLeftLabel.topAnchor.constraint(equalTo: iconBGView.bottomAnchor,constant: 24),
- // Music Switch
- musicSwitch.centerYAnchor.constraint(equalTo: musicLeftLabel.centerYAnchor, constant: 0),
- musicSwitch.leadingAnchor.constraint(equalTo: musicLeftLabel.trailingAnchor, constant: 10),
-
- // Sound Switch
- soundSwitch.centerYAnchor.constraint(equalTo: musicSwitch.centerYAnchor),
- soundSwitch.trailingAnchor.constraint(equalTo: popupBackgroundImageView.trailingAnchor, constant: -28),
-
- soundLeftLabel.centerYAnchor.constraint(equalTo: musicLeftLabel.centerYAnchor,constant: 0),
- soundLeftLabel.trailingAnchor.constraint(equalTo: soundSwitch.trailingAnchor,constant: -60),
-
- // Registration Time Label
- registrationTimeLabel.leadingAnchor.constraint(equalTo: musicLeftLabel.leadingAnchor, constant: 0),
- registrationTimeLabel.topAnchor.constraint(equalTo: musicLeftLabel.bottomAnchor,constant: 22),
-
- softwareNameLabel.centerYAnchor.constraint(equalTo: registrationTimeLabel.centerYAnchor, constant: 0),
- softwareNameLabel.trailingAnchor.constraint(equalTo: soundSwitch.trailingAnchor,constant: 0),
- ])
- }
- // MARK: - Actions
- @objc private func closePopup() {
- delegate?.settingsPopupViewDidClose(self)
- removeFromSuperview()
- }
-
- @objc private func handleBackgroundTap() {
- closePopup()
- }
- // MARK: - Avatar Loading
- private static let imageCache = NSCache<NSURL, UIImage>()
- private func setIcon(with urlString: String?) {
- guard let s = urlString, !s.isEmpty, let url = URL(string: s) else {
- iconImageView.image = UIImage(named: "catlogos")
- return
- }
- if let cached = SettingsPopupView.imageCache.object(forKey: url as NSURL) {
- iconImageView.image = cached
- return
- }
- URLSession.shared.dataTask(with: url) { data, _, _ in
- guard let data = data, let img = UIImage(data: data) else { return }
- SettingsPopupView.imageCache.setObject(img, forKey: url as NSURL)
- DispatchQueue.main.async { [weak self] in
- self?.iconImageView.image = img
- }
- }.resume()
- }
- }
|