角色模块标签

This commit is contained in:
mh 2025-10-17 14:13:23 +08:00
parent 9fb598f906
commit a3b1677409
9 changed files with 420 additions and 11 deletions

View File

@ -121,19 +121,14 @@ class CLTopHeaderView: UIView {
// MARK: Action
@objc func searchImgViewClicked() {
print("111111")
// UIWindow.getTopViewController()?.navigationController?.pushViewController(TestEntrancesController(), animated: true)
subject.send(.search)
}
@objc func calendarImgViewClicked() {
print("2222")
subject.send(.check)
}
@objc func discordImgViewClicked() {
print("333")
subject.send(.discord)
}

View File

@ -188,6 +188,61 @@ class EPChipFilterButton: EPChipButton {
}
}
class EPRoleTagsFilterButton: EPChipButton {
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = UIColor(hex: "#BAC5D2") // EPSystemToken.color(.surfaceElementNormal)
layer.borderWidth = 0
addSubview(textLabel)
textLabel.snp.makeConstraints { make in
make.edges.equalTo(self).inset(paddingInsets).priority(.high)
make.height.equalTo(chipButtonHeight)
}
}
override func setupTheme() {
super.setupTheme()
layer.borderColor = UIColor(hex: "#0065FF").cgColor // EPSystemToken.color(.primaryVariantNormal).cgColor
}
override var paddingInsets: UIEdgeInsets {
UIEdgeInsets(top: 0, left: 16, bottom: 0, right: 16)
}
override var intrinsicContentSize: CGSize{
return CGSize(width: textLabel.size.width + 32, height: chipButtonHeight)
}
override var isHighlighted: Bool {
didSet {
backgroundColor = isSelected
? (isHighlighted ? UIColor(hex: "#BAC5D2") : UIColor(hex: "#0065FF"))
: (isHighlighted ? UIColor(hex: "#0065FF") : UIColor(hex: "#BAC5D2"))
}
}
override var isSelected: Bool {
didSet {
backgroundColor = isSelected
? UIColor(hex: "#0065FF")
: UIColor(hex: "#BAC5D2")
layer.borderWidth = isSelected ? 1 : 0
}
}
override var isEnabled: Bool {
didSet {
textLabel.textColor = isEnabled
? UIColor.white
: UIColor(hex: "#E5F1FF")
backgroundColor = isEnabled
? UIColor.c.csen
: UIColor.c.csed
}
}
}
class EPChipCenterIconButton: EPChipButton {
override init(frame: CGRect) {
super.init(frame: frame)

View File

@ -45,7 +45,7 @@ class HorizontalScrollTagsView: UIView {
private var stackView: UIStackView!
///
private var tagButtons: [EPChipFilterButton] = []
private var tagButtons: [EPRoleTagsFilterButton] = []
///
private var tags: [String] = []
@ -163,7 +163,7 @@ class HorizontalScrollTagsView: UIView {
//
for (index, tag) in tags.enumerated() {
let button = EPChipFilterButton()
let button = EPRoleTagsFilterButton()
button.text = tag
button.tag = index
button.addTarget(self, action: #selector(tagButtonTapped(_:)), for: .touchUpInside)
@ -173,7 +173,7 @@ class HorizontalScrollTagsView: UIView {
}
}
@objc private func tagButtonTapped(_ sender: EPChipFilterButton) {
@objc private func tagButtonTapped(_ sender: EPRoleTagsFilterButton) {
let index = sender.tag
//
@ -184,7 +184,6 @@ class HorizontalScrollTagsView: UIView {
selectedIndices.insert(index)
sender.isSelected = true
}
//
notifySelectionChanged()
}

View File

@ -0,0 +1,13 @@
//
// CLRoleTagsModel.swift
// Visual_Novel_iOS
//
// Created by mh on 2025/10/17.
//
import Foundation
struct CLRoleTagsModel: Codable {
var name: String = ""
var isSelected: Bool = false
}

View File

@ -129,7 +129,7 @@ class CLRoleCollectionCell: UICollectionViewCell {
contentView.addSubview(remindLab)
coverImgView.snp.makeConstraints { make in
make.width.equalTo(cellWidth)
make.width.equalTo(cellWidth).priority(999)
make.height.equalTo(coverImgView.snp.width).multipliedBy(4.0 / 3.0)
make.top.left.right.equalToSuperview()
}

View File

@ -0,0 +1,112 @@
//
// CLRoleTagsView.swift
// Visual_Novel_iOS
//
// Created by mh on 2025/10/16.
//
import UIKit
class CLRoleTagsView: UIView {
// let tags = ["#", "#", "#", "#", "#this is good", "#", "#", "#a", "#a"]
var tagModels: [CLRoleTagsModel] = [
CLRoleTagsModel(name: "#浪漫浪漫浪漫浪漫浪漫浪漫浪漫浪漫浪漫漫浪漫浪漫浪漫漫浪漫浪漫浪漫漫浪漫浪漫浪漫", isSelected: false),
CLRoleTagsModel(name: "#温柔", isSelected: false),
CLRoleTagsModel(name: "#多愁善感", isSelected: false),
CLRoleTagsModel(name: "#this is good", isSelected: false),
CLRoleTagsModel(name: "#沙瓦迪", isSelected: false),
CLRoleTagsModel(name: "#科技哈", isSelected: false),
CLRoleTagsModel(name: "#等好a", isSelected: false),
CLRoleTagsModel(name: "#a", isSelected: false),
CLRoleTagsModel(name: "#浪漫", isSelected: false),
]
lazy var collectionView: AutoHeightCollectionView = {
let layout = TagFlowLayout()
layout.interItemSpacing = 10 //
layout.lineSpacing = 8
layout.maxLineWidth = UIScreen.width - 20.0
layout.delegate = self
let collectionView = AutoHeightCollectionView(frame: .zero, collectionViewLayout: layout)
collectionView.delegate = self
collectionView.dataSource = self
collectionView.backgroundColor = .clear
collectionView.setContentHuggingPriority(.required, for: .vertical)
collectionView.showsVerticalScrollIndicator = false
collectionView.showsHorizontalScrollIndicator = false
collectionView.register(RoleTagCollectionCell.self, forCellWithReuseIdentifier: "RoleTagCollectionCell")
return collectionView
}()
override init(frame: CGRect) {
super.init(frame: frame)
setupSubviews()
// setupDatas()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// MARK: Subviews
func setupSubviews() {
addSubview(collectionView)
collectionView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
}
// MARK: data
private func setupDatas() {
}
}
extension CLRoleTagsView: UICollectionViewDataSource, UICollectionViewDelegate, TagFlowLayoutDelegate {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
tagModels.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell: RoleTagCollectionCell = collectionView.dequeueReusableCell(withReuseIdentifier: "RoleTagCollectionCell", for: indexPath) as! RoleTagCollectionCell
cell.setupData(model: tagModels[indexPath.item])
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print("点击了标签:\(tagModels[indexPath.item].name)")
tagModels[indexPath.item].isSelected.toggle()
// collectionView.reloadItems(at: [indexPath])
collectionView.reloadData()
}
// size
func collectionView(_ collectionView: UICollectionView,
layout: TagFlowLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize {
let text = tagModels[indexPath.item].name
let font = UIFont.boldSystemFont(ofSize: 12)
let w = text.size(withAttributes: [.font: font]).width + 20 // 10 pt padding
return CGSize(width: min(w, layout.maxItemWidth), height: 23)
}
}
final class AutoHeightCollectionView: UICollectionView {
override var contentSize: CGSize {
didSet { invalidateIntrinsicContentSize() }
}
override var intrinsicContentSize: CGSize {
CGSize(width: UIView.noIntrinsicMetric, height: contentSize.height)
}
}

View File

@ -0,0 +1,64 @@
//
// RoleTagCollectionCell.swift
// Visual_Novel_iOS
//
// Created by mh on 2025/10/16.
//
import UIKit
class RoleTagCollectionCell: UICollectionViewCell {
lazy var containerView: UIView = {
let view = UIView()
view.backgroundColor = UIColor(hex: "#BAC5D2")
view.cornerRadius = 11.5
return view
}()
lazy var titleLab: UILabel = {
let lab = UILabel()
lab.font = UIFont.boldSystemFont(ofSize: 12)
lab.textColor = UIColor(hex: "#E5F1FF")
lab.textAlignment = .center
return lab
}()
override init(frame: CGRect) {
super.init(frame: frame)
self.contentView.clipsToBounds = true
setupViews()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setupViews() {
contentView.addSubview(containerView)
containerView.addSubview(titleLab)
containerView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
titleLab.snp.makeConstraints { make in
make.centerY.equalToSuperview()
make.left.right.equalToSuperview().inset(7)
}
}
func setupData(model: CLRoleTagsModel) {
titleLab.text = model.name
if model.isSelected {
containerView.backgroundColor = UIColor(hex: "#0065FF")
titleLab.textColor = .white
} else {
containerView.backgroundColor = UIColor(hex: "#BAC5D2")
titleLab.textColor = UIColor(hex: "#E5F1FF")
}
}
}

View File

@ -15,6 +15,10 @@ class RolesRootPageView: CLContainer {
let itemWidth: CGFloat = (UIScreen.width - 30.0) / 2.0
var jumpPublisher: AnyPublisher<JumpTarget, Never> { topView.jumpPublisher }
// private lazy var pagingView = JXPagingListRefreshView(delegate: self)
// lazy var headerView:
let data: [String] = [
"Once a prodigy, Lin Feng had his cultivation shattered and was cast out Once a prodigy, Lin Feng had his cultivation shattered and was cast",
"Once a prodigy, Lin Feng had his cultivation",
@ -46,6 +50,11 @@ class RolesRootPageView: CLContainer {
return view
}()
lazy var tagsView: CLRoleTagsView = {
let tagsView = CLRoleTagsView()
return tagsView
}()
lazy var collectionView: UICollectionView = {
let layout = CLWaterfallLayout()
layout.columnCount = 2
@ -65,6 +74,7 @@ class RolesRootPageView: CLContainer {
super.init(frame: frame)
setupViews()
setupDatas()
}
required init?(coder: NSCoder) {
@ -73,6 +83,8 @@ class RolesRootPageView: CLContainer {
private func setupViews() {
addSubview(self.topView)
// addSubview(tagsChooseView)
addSubview(tagsView)
addSubview(collectionView)
topView.snp.makeConstraints { make in
@ -80,11 +92,20 @@ class RolesRootPageView: CLContainer {
make.height.equalTo(UIDevice().navHeight)
}
tagsView.snp.makeConstraints { make in
make.right.left.equalToSuperview()
make.top.equalTo(topView.snp.bottom).offset(0)
}
collectionView.snp.makeConstraints { make in
make.bottom.left.right.equalToSuperview()
make.top.equalTo(topView.snp.bottom).offset(20)
make.top.equalTo(tagsView.snp.bottom).offset(0)
}
}
private func setupDatas() {
}
}
extension RolesRootPageView: UICollectionViewDelegate, UICollectionViewDataSource, WaterfallLayoutDelegate {
@ -100,6 +121,10 @@ extension RolesRootPageView: UICollectionViewDelegate, UICollectionViewDataSourc
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
}
func collectionView(_ collectionView: UICollectionView,
layout: CLWaterfallLayout,
heightForItemAt indexPath: IndexPath) -> CGFloat {
@ -131,3 +156,69 @@ extension RolesRootPageView: UICollectionViewDelegate, UICollectionViewDataSourc
return coverH + 10.0 + textH + 5.0 + remindH
}
}
//extension RolesRootPageView: JXPagingViewDelegate {
// func tableHeaderViewHeight(in _: JXPagingView) -> Int {
// return 100
// }
//
// func tableHeaderView(in _: JXPagingView) -> UIView {
// return headerView
// }
//
// func heightForPinSectionHeader(in _: JXPagingView) -> Int {
// return headerPinHeadHeight
// }
//
// func viewForPinSectionHeader(in _: JXPagingView) -> UIView {
// return pinHeaderView
// }
//
// func numberOfLists(in _: JXPagingView) -> Int {
// return controllers.count
// }
//
// func pagingView(_: JXPagingView, initListAtIndex index: Int) -> JXPagingViewListViewDelegate {
// let vc = controllers[index]
// return vc
// }
//
// func segmentedView(_ segmentedView: JXSegmentedView, didSelectedItemAt index: Int) {
// if segmentedView == pinHeaderView.segmentedView {
// refreshSubTagsSegmentView()
// }
//// else if segmentedView == pinHeaderView.subSegementedView {
//// let selectTag = tagsNodes[index]
//// if let currentVc = controllers[pinHeaderView.segmentedView.selectedIndex] as? DiscoverRolesGridController {
//// currentVc.tryLoad(code: selectTag.code!)
//// }
//// }
// }
//
// func mainTableViewDidScroll(_ scrollView: UIScrollView) {
// NaviAlphaHandle.changeNaviViewsAlpha(scrollView: scrollView, alphaViews: [bgBdView, navigationView?.bgView], oppositeViews: [])
// }
//}
//extension DiscoverRootPageView: JXPagingMainTableViewGestureDelegate {
// func mainTableViewGestureRecognizer(
// _ gestureRecognizer: UIGestureRecognizer,
// shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
// // UICollectionView
// if let panGesture = otherGestureRecognizer as? UIPanGestureRecognizer,
// let otherView = otherGestureRecognizer.view,
// otherView is UICollectionView {
// let velocity = panGesture.velocity(in: otherView)
// //
// if abs(velocity.x) > abs(velocity.y) {
// return false
// }
// }
// // segmentedView
//// if otherGestureRecognizer == segmentedView.collectionView.panGestureRecognizer {
//// return false
//// }
// return gestureRecognizer.isKind(of: UIPanGestureRecognizer.self)
// && otherGestureRecognizer.isKind(of: UIPanGestureRecognizer.self)
// }
//}

View File

@ -0,0 +1,80 @@
//
// TagFlowLayout.swift
// Visual_Novel_iOS
//
// Created by mh on 2025/10/16.
//
import UIKit
final class TagFlowLayout: UICollectionViewLayout {
// MARK: -
var maxLineWidth: CGFloat = UIScreen.width - 20.0
var maxItemWidth: CGFloat = (UIScreen.width - 50.0) / 2.0
var interItemSpacing: CGFloat = 8
var lineSpacing: CGFloat = 6
var sectionInset: UIEdgeInsets = .init(top: 12, left: 20, bottom: 12, right: 10)
var delegate: TagFlowLayoutDelegate? = nil
// MARK: -
private var cache: [UICollectionViewLayoutAttributes] = []
private var contentHeight: CGFloat = 0
override var collectionViewContentSize: CGSize {
CGSize(width: maxLineWidth, height: contentHeight)
}
override func prepare() {
super.prepare()
guard cache.isEmpty, let cv = collectionView else { return }
contentHeight = sectionInset.top
var x: CGFloat = sectionInset.left
var y: CGFloat = sectionInset.top
var lineHeight: CGFloat = 0
for idx in 0..<cv.numberOfItems(inSection: 0) {
let indexPath = IndexPath(item: idx, section: 0)
// size delegate
let size = delegate?.collectionView(cv, layout: self, sizeForItemAt: indexPath) ??
CGSize(width: 60, height: 32)
//
if x + size.width + sectionInset.right > maxLineWidth && idx > 0 {
x = sectionInset.left
y += lineHeight + lineSpacing
lineHeight = 0
}
// frame
let attr = UICollectionViewLayoutAttributes(forCellWith: indexPath)
attr.frame = CGRect(origin: CGPoint(x: x, y: y), size: size)
cache.append(attr)
//
x += size.width + interItemSpacing
lineHeight = max(lineHeight, size.height)
}
contentHeight = y + lineHeight + sectionInset.bottom
}
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
cache.filter { $0.frame.intersects(rect) }
}
override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
cache[safe: indexPath.item]
}
override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
newBounds.width != maxLineWidth
}
}
// MARK: - delegate size
protocol TagFlowLayoutDelegate: AnyObject {
func collectionView(_ collectionView: UICollectionView,
layout: TagFlowLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize
}