import UIKit
import SnapKit
// MARK: - DeviceListNewViewController
class DeviceListNewViewController: SurveillanceCommonTableController {
// MARK: - 属性
private lazy var headerView: DeviceListHeaderView = {
let view = DeviceListHeaderView()
view.onBackTap = { [weak self] in
self?.onBackTapped()
}
view.onLocationTap = { [weak self] in
self?.onLocationTapped()
}
view.onSearchTap = { [weak self] in
self?.onSearchTapped()
}
return view
}()
private lazy var multiScreenButton: UIButton = {
let btn = UIButton(type: .custom)
btn.setTitle("asdsad", for: .normal)
btn.setTitleColor(.blue, for: .normal)
btn.titleLabel?.font = UIFont.systemFont(ofSize: 20)
btn.contentEdgeInsets = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8)
btn.addTarget(self, action: #selector(onMultiScreenTapped), for: .touchUpInside)
return btn
}()
// MARK: - 生命周期
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.contentInsetAdjustmentBehavior = .never
reloadData()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.setNavigationBarHidden(true, animated: false)
}
// MARK: - 设置子视图
override func tpbSetupSubviews() {
super.tpbSetupSubviews()
view.addSubview(headerView)
}
// MARK: - 布局约束
override func tpbMakeConstraint() {
// 不调用 super
// super.tpbMakeConstraint()
headerView.snp.makeConstraints { make in
make.top.equalTo(view.safeAreaLayoutGuide.snp.top)
make.leading.trailing.equalToSuperview()
make.height.equalTo(50)
}
tableView.snp.remakeConstraints { make in
make.top.equalTo(headerView.snp.bottom).offset(10)
make.leading.trailing.equalToSuperview()
make.bottom.equalTo(self.view.safeAreaLayoutGuide.snp.bottom)
}
}
// MARK: - 创建 Multi-Screen 行
private func createMultiScreenRowView() -> UIView {
let container = TPBBaseView()
container.backgroundColor = .tpbCard
container.layer.cornerRadius = 3
container.clipsToBounds = true
container.addSubview(multiScreenButton)
multiScreenButton.snp.makeConstraints { make in
make.trailing.equalTo(container).offset(-16)
make.centerY.equalTo(container)
make.size.equalTo(CGSize(width: 44, height: 44))
}
return container
}
private func createDeviceCountView() -> UIView {
let view = UIView()
view.backgroundColor = .tpbCard
let label = UILabel()
label.text = "设备总数:32 台"
label.font = UIFont.systemFont(ofSize: 16, weight: .regular)
label.textColor = .tpbTextPrimary
view.addSubview(label)
label.snp.makeConstraints { make in
make.centerY.equalTo(view)
make.leading.equalTo(view).offset(16)
}
return view
}
private func createStorageUsageView() -> UIView {
let view = UIView()
view.backgroundColor = .tpbCard
let label = UILabel()
label.text = "已用存储:1.2 TB / 5 TB"
label.font = UIFont.systemFont(ofSize: 16, weight: .regular)
label.textColor = .tpbTextPrimary
view.addSubview(label)
label.snp.makeConstraints { make in
make.centerY.equalTo(view)
make.leading.equalTo(view).offset(16)
}
return view
}
// MARK: - 刷新设备列表区域(核心:嵌套 UICollectionView)
private func refreshDeviceListSection() {
let itemCount = 10
let itemHeight: CGFloat = 130
let lineSpacing: CGFloat = 10
// 动态计算总高度
let totalHeight = itemHeight * CGFloat(itemCount) + lineSpacing * max(0, CGFloat(itemCount - 1))
let containerView = UIView()
containerView.backgroundColor = .tpbCard
let paddedView = UIView()
paddedView.backgroundColor = .tpbCard
paddedView.layer.cornerRadius = 3
paddedView.clipsToBounds = true
let deviceListView = DeviceListView(itemCount: itemCount) // 可选:传参控制数量
containerView.addSubview(paddedView)
paddedView.addSubview(deviceListView)
paddedView.snp.makeConstraints { make in
make.edges.equalTo(containerView).inset(UIEdgeInsets(top: 0, left: 16, bottom: 0, right: 16))
}
deviceListView.snp.makeConstraints { make in
make.edges.equalTo(paddedView)
make.height.equalTo(totalHeight)
}
let cellModel = TPBBaseTableCellModel.customContent(with: containerView)
cellModel.height = TPBTableElementHeight.customHeight(totalHeight)
let section = TPBTableSectionModel()
section.cellModelArray = [cellModel]
if sectionArray.count > 1 {
sectionArray[1] = section
} else {
sectionArray.append(section)
}
}
// MARK: - 重新加载数据
private func reloadData() {
var tempSectionArray = [TPBTableSectionModel]()
// Section 0: 统计信息 + Multi-Screen 按钮
let section0 = TPBTableSectionModel()
var cellModels = [TPBBaseTableCellModel]()
let deviceCountView = createDeviceCountView()
let deviceCountCellModel = TPBBaseTableCellModel.customContent(with: deviceCountView)
deviceCountCellModel.height = TPBTableElementHeight.customHeight(60)
cellModels.append(deviceCountCellModel)
let storageView = createStorageUsageView()
let storageCellModel = TPBBaseTableCellModel.customContent(with: storageView)
storageCellModel.height = TPBTableElementHeight.customHeight(60)
cellModels.append(storageCellModel)
let devicesRowView = createMultiScreenRowView()
let devicesRowCellModel = TPBBaseTableCellModel.customContent(with: devicesRowView)
devicesRowCellModel.height = TPBTableElementHeight.customHeight(72)
cellModels.append(devicesRowCellModel)
section0.cellModelArray = cellModels
tempSectionArray.append(section0)
// 更新设备列表 Section
refreshDeviceListSection()
// 合并 sections
sectionArray = tempSectionArray + Array(sectionArray.dropFirst(max(0, sectionArray.count - 1)))
tableView.reloadData()
}
// MARK: - Action 回调
@objc private func onBackTapped() {
navigationController?.popViewController(animated: true)
}
@objc private func onLocationTapped() {
print("定位按钮点击")
}
@objc private func onSearchTapped() {
print("搜索按钮点击")
}
@objc private func onMultiScreenTapped() {
print("Multi-Screen 按钮被点击")
}
}
// MARK: - DeviceListCell
class DeviceListCell: UICollectionViewCell {
private let titleLabel = UILabel()
override init(frame: CGRect) {
super.init(frame: frame)
setupUI()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setupUI()
}
private func setupUI() {
// 背景和边框样式
backgroundColor = .tpbCard
layer.borderColor = UIColor(red: 0.0, green: 0.4, blue: 1.0, alpha: 1.0).cgColor
layer.borderWidth = 1
layer.cornerRadius = 3
clipsToBounds = true
// 标题配置
titleLabel.font = UIFont.systemFont(ofSize: 16, weight: .medium)
titleLabel.textColor = .tpbTextPrimary
titleLabel.textAlignment = .center
titleLabel.numberOfLines = 1
titleLabel.translatesAutoresizingMaskIntoConstraints = false
// 添加到 contentView
contentView.addSubview(titleLabel)
// 使用 SnapKit 设置约束
titleLabel.snp.makeConstraints { make in
make.centerX.centerY.equalTo(contentView)
make.leading.greaterThanOrEqualTo(contentView.snp.leading).offset(16)
make.trailing.lessThanOrEqualTo(contentView.snp.trailing).offset(-16)
make.height.equalTo(20) // 可选:确保文字垂直居中时高度稳定
}
}
func configure(with title: String) {
titleLabel.text = title
}
override func prepareForReuse() {
super.prepareForReuse()
titleLabel.text = nil
}
}
// MARK: - DeviceListView (包含 UICollectionView)
class DeviceListView: UIView {
private let collectionView: UICollectionView
private let itemCount: Int
init(itemCount: Int = 10) {
self.itemCount = itemCount
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .vertical
layout.minimumLineSpacing = 10
layout.minimumInteritemSpacing = 0
collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
super.init(frame: .zero)
setupUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func setupUI() {
collectionView.backgroundColor = .tpbCard
collectionView.showsVerticalScrollIndicator = false
collectionView.isScrollEnabled = false
collectionView.register(DeviceListCell.self, forCellWithReuseIdentifier: "DeviceListCell")
collectionView.dataSource = self
addSubview(collectionView)
collectionView.snp.makeConstraints { make in
make.edges.equalToSuperview()
// 不在这里写死 height,留给外部约束控制
}
}
override func layoutSubviews() {
super.layoutSubviews()
guard let layout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout else { return }
let width = bounds.width
layout.itemSize = CGSize(width: width, height: 130)
}
}
// MARK: - UICollectionViewDataSource
extension DeviceListView: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 10
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "DeviceListCell", for: indexPath) as! DeviceListCell
cell.configure(with: "设备\(indexPath.item + 1)")
return cell
}
}
// MARK: - DeviceListHeaderView
fileprivate class DeviceListHeaderView: TPBBaseView {
private lazy var backButton: UIButton = {
let button = UIButton(type: .custom)
button.setTitle("←", for: .normal)
button.setTitleColor(.blue, for: .normal)
button.contentEdgeInsets = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8)
return button
}()
private lazy var locationButton: UIButton = {
let button = UIButton(type: .custom)
button.setTitle("📍", for: .normal)
button.setTitleColor(.blue, for: .normal)
button.contentEdgeInsets = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8)
return button
}()
private lazy var titleLabel: UILabel = {
let label = UILabel()
label.text = "设备列表"
label.font = UIFont.systemFont(ofSize: 18, weight: .medium)
label.textColor = .tpbTextPrimary
label.textAlignment = .center
return label
}()
private lazy var searchButton: UIButton = {
let button = UIButton(type: .custom)
button.setTitle("🔍", for: .normal)
button.setTitleColor(.blue, for: .normal)
button.contentEdgeInsets = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8)
return button
}()
var onBackTap: (() -> Void)?
var onLocationTap: (() -> Void)?
var onSearchTap: (() -> Void)?
override func setupSubviews() {
super.setupSubviews()
backgroundColor = .tpbBackground
backButton.addTarget(self, action: #selector(onBackTapped), for: .touchUpInside)
locationButton.addTarget(self, action: #selector(onLocationTapped), for: .touchUpInside)
searchButton.addTarget(self, action: #selector(onSearchTapped), for: .touchUpInside)
addSubviews([
backButton,
locationButton,
titleLabel,
searchButton,
])
}
override func makeConstraint() {
backButton.snp.makeConstraints { make in
make.leading.equalToSuperview().offset(16)
make.centerY.equalToSuperview()
make.width.greaterThanOrEqualTo(30)
}
locationButton.snp.makeConstraints { make in
make.leading.equalTo(backButton.snp.trailing).offset(8)
make.centerY.equalTo(backButton)
make.size.equalTo(30)
}
titleLabel.snp.makeConstraints { make in
make.centerX.equalToSuperview()
make.centerY.equalTo(backButton)
}
searchButton.snp.makeConstraints { make in
make.trailing.equalToSuperview().offset(-16)
make.centerY.equalTo(backButton)
make.width.greaterThanOrEqualTo(30)
}
}
@objc private func onBackTapped() {
onBackTap?()
}
@objc private func onLocationTapped() {
onLocationTap?()
}
@objc private func onSearchTapped() {
onSearchTap?()
}
}这里面是在哪里设置的四个cell之间的布局约束呢?我现在想让设备数量、存储容量、多分屏按钮的三个cell之间留一点空隙 怎么设置
最新发布