parent
bbbab43c2e
commit
c74e0d9041
@ -0,0 +1,54 @@
|
||||
//
|
||||
// Mine.swift
|
||||
// IndieMusic
|
||||
//
|
||||
// Created by WenLei on 2023/11/23.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import RxDataSources
|
||||
|
||||
struct Mine: Codable {
|
||||
let title: String
|
||||
let detail: String
|
||||
}
|
||||
|
||||
struct MineSection {
|
||||
var items: [Mine]
|
||||
|
||||
}
|
||||
|
||||
extension MineSection: SectionModelType {
|
||||
typealias Item = Mine
|
||||
|
||||
init(original: MineSection, items: [Item]) {
|
||||
self = original
|
||||
self.items = items
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
struct MineSingle {
|
||||
let cover: String
|
||||
let title: String
|
||||
let detail: String
|
||||
}
|
||||
|
||||
|
||||
struct MineSingleSection {
|
||||
var items: [MineSingle]
|
||||
|
||||
}
|
||||
|
||||
extension MineSingleSection: SectionModelType {
|
||||
typealias Item = MineSingle
|
||||
|
||||
init(original: MineSingleSection, items: [Item]) {
|
||||
self = original
|
||||
self.items = items
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
//
|
||||
// MusicStyle.swift
|
||||
// IndieMusic
|
||||
//
|
||||
// Created by WenLei on 2024/1/2.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import RxDataSources
|
||||
|
||||
struct MusicStyle: Codable {
|
||||
let title: String
|
||||
let subTitle: String
|
||||
let backgroundImage: String
|
||||
}
|
||||
|
||||
|
||||
struct MusicStyleSection {
|
||||
var items: [MusicStyle]
|
||||
|
||||
}
|
||||
|
||||
extension MusicStyleSection: SectionModelType {
|
||||
typealias Item = MusicStyle
|
||||
|
||||
init(original: MusicStyleSection, items: [Item]) {
|
||||
self = original
|
||||
self.items = items
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
//
|
||||
// PersonInfo.swift
|
||||
// IndieMusic
|
||||
//
|
||||
// Created by WenLei on 2024/1/1.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
struct PersonInfo {
|
||||
let avator: String
|
||||
let name: String
|
||||
let slogn: String
|
||||
let day: String
|
||||
let sex: String
|
||||
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
//
|
||||
// Search.swift
|
||||
// IndieMusic
|
||||
//
|
||||
// Created by WenLei on 2024/1/2.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import RxDataSources
|
||||
|
||||
enum SearchType {
|
||||
case single
|
||||
case journal
|
||||
}
|
||||
|
||||
extension SearchType {
|
||||
var description: String {
|
||||
switch self {
|
||||
case .single:
|
||||
return "单曲"
|
||||
case .journal:
|
||||
return "期刊"
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Search: Codable {
|
||||
let title: String
|
||||
let subTitle: String
|
||||
let backgroundImage: String
|
||||
}
|
||||
|
||||
|
||||
struct SearchSection {
|
||||
var items: [Search]
|
||||
|
||||
}
|
||||
|
||||
extension SearchSection: SectionModelType {
|
||||
typealias Item = Search
|
||||
|
||||
init(original: SearchSection, items: [Item]) {
|
||||
self = original
|
||||
self.items = items
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
//
|
||||
// Setting.swift
|
||||
// IndieMusic
|
||||
//
|
||||
// Created by WenLei on 2024/1/1.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import RxDataSources
|
||||
|
||||
struct Setting: Codable {
|
||||
let title: String
|
||||
let detail: String
|
||||
let arrowIcon: String
|
||||
|
||||
}
|
||||
|
||||
enum SettingType {
|
||||
case editInfo(Setting)
|
||||
case account(Setting)
|
||||
case privacy(Setting)
|
||||
|
||||
case timing(Setting)
|
||||
case cache(Setting)
|
||||
case permission(Setting)
|
||||
|
||||
case feedback(Setting)
|
||||
case about(Setting)
|
||||
case contributors(Setting)
|
||||
case version(Setting)
|
||||
|
||||
case setting(Setting)
|
||||
}
|
||||
|
||||
|
||||
struct SettingSection {
|
||||
var items: [SettingType]
|
||||
|
||||
}
|
||||
|
||||
extension SettingSection: SectionModelType {
|
||||
typealias Item = SettingType
|
||||
|
||||
init(original: SettingSection, items: [Item]) {
|
||||
self = original
|
||||
self.items = items
|
||||
}
|
||||
}
|
@ -0,0 +1,224 @@
|
||||
//
|
||||
// CommentViewCell.swift
|
||||
// IndieMusic
|
||||
//
|
||||
// Created by WenLei on 2023/11/27.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class CommentHeaderView: UIView {
|
||||
var titleLabel: UILabel = {
|
||||
let titleLabel = UILabel.init()
|
||||
|
||||
return titleLabel
|
||||
}()
|
||||
|
||||
var segmentControl: SegmentControl = {
|
||||
let segmentControl = SegmentControl.init()
|
||||
segmentControl.items = ["热门", "最新"]
|
||||
|
||||
return segmentControl
|
||||
}()
|
||||
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
makeUI()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
|
||||
func makeUI() {
|
||||
|
||||
addSubview(titleLabel)
|
||||
addSubview(segmentControl)
|
||||
|
||||
}
|
||||
|
||||
override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
|
||||
|
||||
titleLabel.snp.makeConstraints { make in
|
||||
make.left.equalTo(self).offset(18)
|
||||
make.centerY.equalTo(self)
|
||||
}
|
||||
|
||||
segmentControl.snp.makeConstraints { make in
|
||||
make.right.equalTo(self).offset(0)
|
||||
make.centerY.equalTo(self)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
class CommentViewCell: UITableViewCell {
|
||||
var avatarView: UIImageView = {
|
||||
let avatarView = UIImageView.init()
|
||||
|
||||
return avatarView
|
||||
}()
|
||||
|
||||
|
||||
var nameLabel: UILabel = {
|
||||
let nameLabel = UILabel.init()
|
||||
|
||||
return nameLabel
|
||||
}()
|
||||
|
||||
var dateLabel: UILabel = {
|
||||
let dateLabel = UILabel.init()
|
||||
|
||||
return dateLabel
|
||||
}()
|
||||
|
||||
var likeButton: UIButton = {
|
||||
let likeButton = UIButton.init()
|
||||
|
||||
return likeButton
|
||||
}()
|
||||
|
||||
|
||||
var commentLabel: UILabel = {
|
||||
let commentLabel = UILabel.init()
|
||||
|
||||
return commentLabel
|
||||
}()
|
||||
|
||||
|
||||
var subCommentView: UIView = {
|
||||
let subCommentView = UIView.init()
|
||||
|
||||
return subCommentView
|
||||
}()
|
||||
|
||||
|
||||
var subAvatarView: UIImageView = {
|
||||
let subAvatarView = UIImageView.init()
|
||||
|
||||
return subAvatarView
|
||||
}()
|
||||
|
||||
var subCommentLabel: UILabel = {
|
||||
let subCommentLabel = UILabel.init()
|
||||
|
||||
return subCommentLabel
|
||||
}()
|
||||
|
||||
var moreButton: UIButton = {
|
||||
let moreButton = UIButton.init()
|
||||
|
||||
return moreButton
|
||||
}()
|
||||
|
||||
|
||||
|
||||
|
||||
override func awakeFromNib() {
|
||||
super.awakeFromNib()
|
||||
// Initialization code
|
||||
}
|
||||
|
||||
override func setSelected(_ selected: Bool, animated: Bool) {
|
||||
super.setSelected(selected, animated: animated)
|
||||
|
||||
// Configure the view for the selected state
|
||||
}
|
||||
|
||||
|
||||
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
||||
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
||||
|
||||
makeUI()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
func makeUI() {
|
||||
|
||||
contentView.addSubview(avatarView)
|
||||
contentView.addSubview(nameLabel)
|
||||
contentView.addSubview(dateLabel)
|
||||
contentView.addSubview(likeButton)
|
||||
contentView.addSubview(commentLabel)
|
||||
|
||||
contentView.addSubview(subCommentView)
|
||||
subCommentView.addSubview(subAvatarView)
|
||||
subCommentView.addSubview(subCommentLabel)
|
||||
subCommentView.addSubview(moreButton)
|
||||
}
|
||||
|
||||
|
||||
override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
|
||||
|
||||
avatarView.snp.makeConstraints { make in
|
||||
make.left.equalTo(contentView).offset(18)
|
||||
make.top.equalTo(contentView).offset(12)
|
||||
make.size.equalTo(CGSize.init(width: 40, height: 40))
|
||||
}
|
||||
|
||||
moreButton.snp.makeConstraints { make in
|
||||
make.right.equalTo(contentView).offset(18)
|
||||
make.centerY.equalTo(avatarView)
|
||||
}
|
||||
|
||||
|
||||
nameLabel.snp.makeConstraints { make in
|
||||
make.top.equalTo(avatarView)
|
||||
make.left.equalTo(avatarView.snp.right).offset(14)
|
||||
make.right.equalTo(moreButton.snp.left).offset(-10)
|
||||
}
|
||||
|
||||
dateLabel.snp.makeConstraints { make in
|
||||
make.left.equalTo(avatarView.snp.right).offset(14)
|
||||
make.top.equalTo(nameLabel.snp.bottom).offset(2)
|
||||
}
|
||||
|
||||
commentLabel.snp.makeConstraints { make in
|
||||
make.left.equalTo(avatarView.snp.right).offset(14)
|
||||
make.right.equalTo(contentView).offset(-18)
|
||||
make.top.equalTo(dateLabel.snp.bottom).offset(10)
|
||||
}
|
||||
|
||||
subCommentView.snp.makeConstraints { make in
|
||||
make.left.equalTo(avatarView.snp.right).offset(14)
|
||||
make.right.equalTo(contentView).offset(-18)
|
||||
make.top.equalTo(commentLabel.snp.bottom).offset(15)
|
||||
make.bottom.equalTo(contentView).offset(-12)
|
||||
}
|
||||
|
||||
subAvatarView.snp.makeConstraints { make in
|
||||
make.left.equalTo(subCommentView)
|
||||
make.top.equalTo(subCommentView)
|
||||
make.size.equalTo(CGSize.init(width: 20, height: 20))
|
||||
}
|
||||
|
||||
subCommentLabel.snp.makeConstraints { make in
|
||||
make.left.equalTo(subAvatarView.snp.right).offset(5)
|
||||
make.right.equalTo(subCommentView)
|
||||
make.top.equalTo(subCommentView)
|
||||
}
|
||||
|
||||
moreButton.snp.makeConstraints { make in
|
||||
make.top.equalTo(subCommentLabel.snp.bottom).offset(12)
|
||||
make.bottom.equalTo(subCommentView)
|
||||
make.left.equalTo(subCommentView)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,53 @@
|
||||
//
|
||||
// CommentViewController.swift
|
||||
// IndieMusic
|
||||
//
|
||||
// Created by WenLei on 2023/11/27.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import RxSwift
|
||||
import RxCocoa
|
||||
import RxDataSources
|
||||
|
||||
class CommentViewController: ViewController {
|
||||
var tableView: UITableView = {
|
||||
let tableView = UITableView.init()
|
||||
|
||||
|
||||
return tableView
|
||||
}()
|
||||
|
||||
|
||||
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
override func makeUI() {
|
||||
super.makeUI()
|
||||
|
||||
view.addSubview(tableView)
|
||||
}
|
||||
|
||||
override func bindViewModel() {
|
||||
super.bindViewModel()
|
||||
|
||||
|
||||
}
|
||||
|
||||
override func viewDidLayoutSubviews() {
|
||||
super.viewDidLayoutSubviews()
|
||||
|
||||
|
||||
tableView.snp.makeConstraints { make in
|
||||
make.edges.equalTo(view)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
//
|
||||
// MineSingleController.swift
|
||||
// IndieMusic
|
||||
//
|
||||
// Created by WenLei on 2023/11/23.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import RxSwift
|
||||
import RxCocoa
|
||||
import RxDataSources
|
||||
|
||||
class MineSingleController: TableViewController {
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
// Do any additional setup after loading the view.
|
||||
}
|
||||
|
||||
|
||||
override func makeUI() {
|
||||
super.makeUI()
|
||||
|
||||
|
||||
}
|
||||
|
||||
override func bindViewModel() {
|
||||
super.bindViewModel()
|
||||
|
||||
guard let viewModel = viewModel as? MineSingleViewModel else { return }
|
||||
|
||||
let input = MineSingleViewModel.Input.init(viewWillAppear: rx.viewWillAppear,
|
||||
selection: tableView.rx.itemSelected.asDriver())
|
||||
let output = viewModel.transform(input: input)
|
||||
|
||||
let dataSource = MineSingleController.dataSource()
|
||||
|
||||
output.items.bind(to: tableView.rx.items(dataSource: dataSource)).disposed(by: rx.disposeBag)
|
||||
|
||||
|
||||
output.itemSelected.subscribe { sectionItem in
|
||||
|
||||
|
||||
}.disposed(by: rx.disposeBag)
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
extension MineSingleController {
|
||||
static func dataSource() -> RxTableViewSectionedReloadDataSource<MineSingleSection> {
|
||||
return RxTableViewSectionedReloadDataSource<MineSingleSection>(
|
||||
configureCell: { dataSource, tableView, indexPath, item in
|
||||
let cell: SongViewCell = tableView.dequeueReusableCell(withIdentifier: "SongViewCell", for: indexPath) as! SongViewCell
|
||||
|
||||
// cell.titleLabel.text = "123"
|
||||
// cell.detailLabel.text = "321"
|
||||
|
||||
return cell
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
//
|
||||
// MineSingleViewModel.swift
|
||||
// IndieMusic
|
||||
//
|
||||
// Created by WenLei on 2023/11/23.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import RxSwift
|
||||
import RxCocoa
|
||||
import RxDataSources
|
||||
|
||||
class MineSingleViewModel: ViewModel, ViewModelType {
|
||||
|
||||
struct Input {
|
||||
let viewWillAppear: ControlEvent<Bool>
|
||||
let selection: Driver<IndexPath>
|
||||
|
||||
}
|
||||
|
||||
struct Output {
|
||||
let items: BehaviorRelay<[MineSingleSection]>
|
||||
let selection: Driver<IndexPath>
|
||||
let itemSelected: PublishSubject<MineSingle>
|
||||
|
||||
}
|
||||
|
||||
let itemSelected = PublishSubject<MineSingle>()
|
||||
let items = BehaviorRelay<[MineSingleSection]>.init(value: [])
|
||||
|
||||
func transform(input: Input) -> Output {
|
||||
|
||||
input.viewWillAppear.subscribe { (_) in
|
||||
|
||||
}.disposed(by: rx.disposeBag)
|
||||
|
||||
let mine = MineSingle.init(cover: "", title: "", detail: "")
|
||||
|
||||
items.accept([MineSingleSection.init(items: [mine, mine, mine])])
|
||||
|
||||
|
||||
input.selection.drive { indexPath in
|
||||
guard let sectionItem = self.items.value.first?.items[indexPath.row] else { return }
|
||||
self.itemSelected.onNext(sectionItem)
|
||||
}.disposed(by: rx.disposeBag)
|
||||
|
||||
|
||||
|
||||
return Output.init(items: items,
|
||||
selection: input.selection,
|
||||
itemSelected: itemSelected)
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,355 @@
|
||||
//
|
||||
// MineView.swift
|
||||
// IndieMusic
|
||||
//
|
||||
// Created by WenLei on 2023/11/23.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class MineHeaderView: UIView {
|
||||
lazy var iconView: UIImageView = {
|
||||
let iconView = UIImageView.init()
|
||||
iconView.layer.cornerRadius = 32
|
||||
|
||||
iconView.backgroundColor = .red
|
||||
|
||||
return iconView
|
||||
}()
|
||||
|
||||
lazy var nameButton: UIButton = {
|
||||
let nameButton = UIButton.init()
|
||||
nameButton.titleLabel?.font = UIFont.systemFont(ofSize: 20, weight: .medium)
|
||||
nameButton.setTitle("立即登录", for: .normal)
|
||||
|
||||
return nameButton
|
||||
}()
|
||||
|
||||
lazy var tipsLabel: UILabel = {
|
||||
let tipsLabel = UILabel.init()
|
||||
tipsLabel.font = UIFont.systemFont(ofSize: 12)
|
||||
tipsLabel.text = "独立 不独于世"
|
||||
tipsLabel.textColor = .init(hex: 0x000000, alpha: 0.6)
|
||||
|
||||
return tipsLabel
|
||||
}()
|
||||
|
||||
|
||||
var mineMenuView: MineMenuView = {
|
||||
let mineMenuView = MineMenuView.init()
|
||||
|
||||
return mineMenuView
|
||||
}()
|
||||
|
||||
var lineView: UIView = {
|
||||
let lineView = UIView.init()
|
||||
lineView.backgroundColor = .separator()
|
||||
|
||||
return lineView
|
||||
}()
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
makeUI()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
func makeUI() {
|
||||
backgroundColor = .white
|
||||
|
||||
addSubview(iconView)
|
||||
addSubview(nameButton)
|
||||
addSubview(tipsLabel)
|
||||
addSubview(mineMenuView)
|
||||
addSubview(lineView)
|
||||
|
||||
}
|
||||
|
||||
override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
|
||||
iconView.snp.makeConstraints { make in
|
||||
make.left.equalTo(self).offset(18)
|
||||
make.top.equalTo(self).offset(11)
|
||||
make.size.equalTo(CGSize.init(width: 64, height: 64))
|
||||
}
|
||||
|
||||
nameButton.snp.makeConstraints { make in
|
||||
make.left.equalTo(iconView.snp.right).offset(18)
|
||||
make.top.equalTo(iconView).offset(4)
|
||||
}
|
||||
|
||||
tipsLabel.snp.makeConstraints { make in
|
||||
make.left.equalTo(iconView.snp.right).offset(18)
|
||||
make.top.equalTo(nameButton.snp.bottom).offset(6)
|
||||
make.right.equalTo(self).offset(-18)
|
||||
}
|
||||
|
||||
|
||||
mineMenuView.snp.makeConstraints { make in
|
||||
make.left.equalTo(self)
|
||||
make.right.equalTo(self)
|
||||
make.top.equalTo(iconView.snp.bottom).offset(16)
|
||||
make.height.equalTo(74)
|
||||
}
|
||||
|
||||
lineView.snp.makeConstraints { make in
|
||||
make.left.equalTo(self).offset(18)
|
||||
make.right.equalTo(self).offset(-18)
|
||||
make.height.equalTo(1)
|
||||
make.top.equalTo(mineMenuView.snp.bottom).offset(18)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
class MineMenuView: UIView {
|
||||
lazy var followingView: MineMenuSubView = {
|
||||
let followingView = MineMenuSubView.init()
|
||||
followingView.titleLabel.text = "关注"
|
||||
followingView.detailLabel.text = "123"
|
||||
|
||||
|
||||
return followingView
|
||||
}()
|
||||
|
||||
lazy var followersView: MineMenuSubView = {
|
||||
let followersView = MineMenuSubView.init()
|
||||
followersView.titleLabel.text = "粉丝"
|
||||
followersView.detailLabel.text = "123"
|
||||
|
||||
|
||||
return followersView
|
||||
}()
|
||||
|
||||
lazy var likeView: MineMenuSubView = {
|
||||
let likeView = MineMenuSubView.init()
|
||||
likeView.titleLabel.text = "获赞"
|
||||
likeView.detailLabel.text = "123"
|
||||
|
||||
|
||||
return likeView
|
||||
}()
|
||||
|
||||
lazy var commentView: MineMenuSubView = {
|
||||
let commentView = MineMenuSubView.init()
|
||||
commentView.titleLabel.text = "评论"
|
||||
commentView.detailLabel.text = "123"
|
||||
|
||||
|
||||
return commentView
|
||||
}()
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
makeUI()
|
||||
|
||||
backgroundColor = .white
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
func makeUI() {
|
||||
addSubview(followingView)
|
||||
addSubview(followersView)
|
||||
addSubview(likeView)
|
||||
addSubview(commentView)
|
||||
|
||||
}
|
||||
|
||||
override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
|
||||
let width = self.bounds.width / 4
|
||||
|
||||
followingView.snp.remakeConstraints { make in
|
||||
make.left.equalTo(self)
|
||||
make.top.equalTo(self)
|
||||
make.bottom.equalTo(self)
|
||||
make.width.equalTo(width)
|
||||
}
|
||||
|
||||
followersView.snp.remakeConstraints { make in
|
||||
make.left.equalTo(followingView.snp.right)
|
||||
make.top.equalTo(self)
|
||||
make.bottom.equalTo(self)
|
||||
make.width.equalTo(width)
|
||||
}
|
||||
|
||||
likeView.snp.remakeConstraints { make in
|
||||
make.left.equalTo(followersView.snp.right)
|
||||
make.top.equalTo(self)
|
||||
make.bottom.equalTo(self)
|
||||
make.width.equalTo(width)
|
||||
}
|
||||
|
||||
commentView.snp.remakeConstraints { make in
|
||||
make.left.equalTo(likeView.snp.right)
|
||||
make.top.equalTo(self)
|
||||
make.bottom.equalTo(self)
|
||||
make.width.equalTo(width)
|
||||
make.right.equalTo(self)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
class MineMenuSubView: UIView {
|
||||
lazy var titleLabel: UILabel = {
|
||||
let titleLabel = UILabel.init()
|
||||
titleLabel.font = UIFont.systemFont(ofSize: 12)
|
||||
titleLabel.textAlignment = .center
|
||||
titleLabel.textColor = .init(hex: 0x000000, alpha: 0.6)
|
||||
|
||||
return titleLabel
|
||||
}()
|
||||
|
||||
lazy var detailLabel: UILabel = {
|
||||
let detailLabel = UILabel.init()
|
||||
detailLabel.font = UIFont.systemFont(ofSize: 20, weight: .medium)
|
||||
detailLabel.textAlignment = .center
|
||||
|
||||
return detailLabel
|
||||
}()
|
||||
|
||||
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
makeUI()
|
||||
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
func makeUI() {
|
||||
addSubview(detailLabel)
|
||||
addSubview(titleLabel)
|
||||
}
|
||||
|
||||
override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
|
||||
detailLabel.snp.makeConstraints { make in
|
||||
make.top.equalTo(self).offset(14)
|
||||
make.left.equalTo(self)
|
||||
make.right.equalTo(self)
|
||||
}
|
||||
|
||||
titleLabel.snp.makeConstraints { make in
|
||||
make.top.equalTo(detailLabel.snp.bottom).offset(3)
|
||||
make.left.equalTo(self)
|
||||
make.right.equalTo(self)
|
||||
make.bottom.equalTo(self).offset(-16)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class MineViewCell: UITableViewCell {
|
||||
lazy var coverView: UIImageView = {
|
||||
let coverView = UIImageView.init()
|
||||
coverView.layer.cornerRadius = 3
|
||||
coverView.layer.masksToBounds = true
|
||||
|
||||
coverView.backgroundColor = .red
|
||||
return coverView
|
||||
}()
|
||||
|
||||
lazy var titleLabel: UILabel = {
|
||||
let titleLabel = UILabel.init()
|
||||
titleLabel.font = UIFont.systemFont(ofSize: 15, weight: .medium)
|
||||
|
||||
|
||||
return titleLabel
|
||||
}()
|
||||
|
||||
lazy var detailLabel: UILabel = {
|
||||
let detailLabel = UILabel.init()
|
||||
detailLabel.font = UIFont.systemFont(ofSize: 12)
|
||||
detailLabel.textColor = .init(hex: 0x000000, alpha: 0.6)
|
||||
|
||||
return detailLabel
|
||||
}()
|
||||
|
||||
lazy var playButton: UIButton = {
|
||||
let playButton = UIButton.init()
|
||||
playButton.setImage(UIImage.init(named: "mine_play_btn"), for: .normal)
|
||||
playButton.setImage(UIImage.init(named: ""), for: .selected)
|
||||
playButton.setContentHuggingPriority(.required, for: .horizontal)
|
||||
playButton.setContentCompressionResistancePriority(.required, for: .horizontal)
|
||||
return playButton
|
||||
}()
|
||||
|
||||
|
||||
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
||||
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
||||
|
||||
makeUI()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
func makeUI () {
|
||||
contentView.addSubview(coverView)
|
||||
contentView.addSubview(titleLabel)
|
||||
contentView.addSubview(detailLabel)
|
||||
contentView.addSubview(playButton)
|
||||
|
||||
|
||||
coverView.snp.makeConstraints { make in
|
||||
make.left.equalTo(contentView).offset(18)
|
||||
make.top.equalTo(contentView).offset(18)
|
||||
make.bottom.equalTo(contentView).offset(-18)
|
||||
make.size.equalTo(CGSize.init(width: 64, height: 64))
|
||||
}
|
||||
|
||||
playButton.snp.makeConstraints { make in
|
||||
make.right.equalTo(contentView).offset(-18)
|
||||
make.centerY.equalTo(contentView)
|
||||
}
|
||||
|
||||
titleLabel.snp.makeConstraints { make in
|
||||
make.left.equalTo(coverView.snp.right).offset(15)
|
||||
make.top.equalTo(coverView).offset(10)
|
||||
make.right.equalTo(playButton.snp.left).offset(-10).priority(.low)
|
||||
}
|
||||
|
||||
detailLabel.snp.makeConstraints { make in
|
||||
make.left.equalTo(coverView.snp.right).offset(15)
|
||||
make.top.equalTo(titleLabel.snp.bottom).offset(10)
|
||||
make.right.equalTo(playButton.snp.left).offset(-6).priority(.low)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
override var frame:CGRect{
|
||||
didSet {
|
||||
let inset: CGFloat = 18.0
|
||||
|
||||
var newFrame = frame
|
||||
newFrame.origin.x += inset
|
||||
newFrame.size.width -= 2*inset
|
||||
|
||||
|
||||
super.frame = newFrame
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,320 @@
|
||||
//
|
||||
// MusicStyleViewController.swift
|
||||
// IndieMusic
|
||||
//
|
||||
// Created by WenLei on 2024/1/2.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import RxSwift
|
||||
import RxCocoa
|
||||
import RxDataSources
|
||||
|
||||
class MusicStyleViewController: ViewController {
|
||||
let collectionView: UICollectionView = {
|
||||
let collectionView = UICollectionView.init()
|
||||
|
||||
return collectionView
|
||||
}()
|
||||
|
||||
lazy var headerView: MusicStyleHeaderView = {
|
||||
let headerView = MusicStyleHeaderView.init()
|
||||
|
||||
headerView.backgroundColor = .red
|
||||
return headerView
|
||||
}()
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
// Do any additional setup after loading the view.
|
||||
}
|
||||
|
||||
override func makeUI() {
|
||||
super.makeUI()
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
override func bindViewModel() {
|
||||
super.bindViewModel()
|
||||
|
||||
}
|
||||
|
||||
|
||||
override func viewDidLayoutSubviews() {
|
||||
super.viewDidLayoutSubviews()
|
||||
|
||||
|
||||
}
|
||||
|
||||
func updateText(text: String) {
|
||||
|
||||
updateHeader()
|
||||
}
|
||||
|
||||
func updateHeader() {
|
||||
collectionView.collectionViewLayout.invalidateLayout()
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
extension MusicStyleViewController: UICollectionViewDelegateFlowLayout {
|
||||
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
|
||||
// 根据 section 或其他条件计算 header 的高度
|
||||
let width = collectionView.bounds.width
|
||||
headerView.frame = CGRect(x: 0, y: 0, width: width, height: 1000)
|
||||
headerView.layoutIfNeeded()
|
||||
let size = headerView.systemLayoutSizeFitting(CGSize(width: width, height: UIView.layoutFittingCompressedSize.height),
|
||||
withHorizontalFittingPriority: .required,
|
||||
verticalFittingPriority: .fittingSizeLevel)
|
||||
|
||||
return CGSize(width: collectionView.bounds.width, height: size.height)
|
||||
}
|
||||
|
||||
static func dataSource() -> RxCollectionViewSectionedReloadDataSource<MusicStyleSection> {
|
||||
return RxCollectionViewSectionedReloadDataSource<MusicStyleSection>(
|
||||
configureCell: { dataSource, collectionView, indexPath, item in
|
||||
// 配置和返回 cell
|
||||
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MusicStyleCellView", for: indexPath)
|
||||
// 配置 cell
|
||||
return cell
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
class MusicStyleHeaderView: UIView {
|
||||
let titleImageView: UIImageView = {
|
||||
let titleImageView = UIImageView.init()
|
||||
|
||||
return titleImageView
|
||||
}()
|
||||
|
||||
|
||||
let containerView: UIView = {
|
||||
let containerView = UIView.init()
|
||||
containerView.layer.cornerRadius = 8
|
||||
containerView.layer.masksToBounds = true
|
||||
containerView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
|
||||
|
||||
return containerView
|
||||
}()
|
||||
|
||||
|
||||
let styleLabel: UILabel = {
|
||||
let styleLabel = UILabel.init()
|
||||
styleLabel.font = UIFont.systemFont(ofSize: 24, weight: .medium)
|
||||
styleLabel.textColor = .init(hex: 0x000000, alpha: 1)
|
||||
|
||||
return styleLabel
|
||||
}()
|
||||
|
||||
|
||||
let subStyleLabel: UILabel = {
|
||||
let subStyleLabel = UILabel.init()
|
||||
subStyleLabel.font = UIFont.systemFont(ofSize: 14)
|
||||
subStyleLabel.textColor = .init(hex: 0x000000, alpha: 0.6)
|
||||
|
||||
return subStyleLabel
|
||||
}()
|
||||
|
||||
let contentLabel: UILabel = {
|
||||
let contentLabel = UILabel.init()
|
||||
contentLabel.font = UIFont.systemFont(ofSize: 15)
|
||||
contentLabel.textColor = .init(hex: 0x000000, alpha: 0.6)
|
||||
|
||||
return contentLabel
|
||||
}()
|
||||
|
||||
|
||||
var dropButton: UIButton = {
|
||||
let dropButton = UIButton.init()
|
||||
dropButton.setTitle("展开", for: .normal)
|
||||
dropButton.setTitle("收起", for: .selected)
|
||||
dropButton.setTitleColor(.init(hex: 0x000000, alpha: 0.6), for: .normal)
|
||||
|
||||
dropButton.setImage(UIImage.init(named: "journal_drop_up"), for: .normal)
|
||||
dropButton.setImage(UIImage.init(named: "journal_drop_up"), for: .selected)
|
||||
|
||||
return dropButton
|
||||
}()
|
||||
|
||||
|
||||
|
||||
var gradientLayer: CAGradientLayer = {
|
||||
let gradientLayer = CAGradientLayer.init()
|
||||
gradientLayer.colors = [UIColor.init(hex: 0xFFFFFF, alpha: 0).cgColor,
|
||||
UIColor.init(hex: 0xFFFFFF, alpha: 0.8).cgColor]
|
||||
gradientLayer.locations = [0.0, 0.9]
|
||||
|
||||
gradientLayer.startPoint = CGPoint.init(x: 0 , y: 0)
|
||||
gradientLayer.endPoint = CGPoint.init(x: 0, y: 1)
|
||||
|
||||
return gradientLayer
|
||||
}()
|
||||
|
||||
|
||||
var isExpand = false {
|
||||
didSet {
|
||||
|
||||
switch isExpand {
|
||||
case true:
|
||||
dropButton.isSelected = true
|
||||
contentLabel.numberOfLines = 0
|
||||
// contentLabel.lineBreakMode = .byClipping
|
||||
|
||||
gradientLayer.isHidden = true
|
||||
|
||||
case false:
|
||||
dropButton.isSelected = false
|
||||
contentLabel.numberOfLines = 4
|
||||
// contentLabel.lineBreakMode = .byClipping
|
||||
|
||||
gradientLayer.isHidden = false
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
makeUI()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
func makeUI() {
|
||||
|
||||
addSubview(titleImageView)
|
||||
addSubview(containerView)
|
||||
containerView.addSubview(styleLabel)
|
||||
containerView.addSubview(subStyleLabel)
|
||||
containerView.addSubview(contentLabel)
|
||||
|
||||
}
|
||||
|
||||
override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
|
||||
|
||||
titleImageView.snp.makeConstraints { make in
|
||||
make.left.equalTo(self)
|
||||
make.right.equalTo(self)
|
||||
make.top.equalTo(self)
|
||||
make.height.equalTo(294)
|
||||
}
|
||||
|
||||
containerView.snp.makeConstraints { make in
|
||||
make.left.equalTo(self)
|
||||
make.right.equalTo(self)
|
||||
make.top.equalTo(self).offset(BaseDimensions.topHeight + 59)
|
||||
make.bottom.equalTo(self)
|
||||
}
|
||||
|
||||
styleLabel.snp.makeConstraints { make in
|
||||
make.left.equalTo(containerView).offset(18)
|
||||
make.top.equalTo(containerView).offset(24)
|
||||
}
|
||||
|
||||
subStyleLabel.snp.makeConstraints { make in
|
||||
make.left.equalTo(styleLabel.snp.right).offset(11)
|
||||
make.centerY.equalTo(styleLabel)
|
||||
}
|
||||
|
||||
contentLabel.snp.makeConstraints { make in
|
||||
make.left.equalTo(containerView).offset(18)
|
||||
make.right.equalTo(containerView).offset(-18)
|
||||
make.top.equalTo(styleLabel.snp.bottom).offset(15)
|
||||
}
|
||||
|
||||
dropButton.snp.remakeConstraints { make in
|
||||
make.left.equalTo(containerView).offset(18)
|
||||
make.top.equalTo(contentLabel.snp.bottom).offset(16)
|
||||
make.bottom.equalTo(containerView.snp.bottom).offset(-35)
|
||||
}
|
||||
|
||||
|
||||
gradientLayer.frame = self.contentLabel.bounds
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class MusicStyleCellView: UICollectionViewCell {
|
||||
let titleImageView: UIImageView = {
|
||||
let titleImageView = UIImageView.init()
|
||||
titleImageView.layer.cornerRadius = 8
|
||||
titleImageView.layer.masksToBounds = true
|
||||
|
||||
|
||||
return titleImageView
|
||||
}()
|
||||
|
||||
let volLabel: UILabel = {
|
||||
let volLabel = UILabel.init()
|
||||
volLabel.font = UIFont.systemFont(ofSize: 12)
|
||||
volLabel.textColor = .init(hex: 0x000000, alpha: 0.4)
|
||||
|
||||
return volLabel
|
||||
}()
|
||||
|
||||
let titleLabel: UILabel = {
|
||||
let titleLabel = UILabel.init()
|
||||
titleLabel.font = UIFont.systemFont(ofSize: 14, weight: .medium)
|
||||
|
||||
return titleLabel
|
||||
}()
|
||||
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
makeUI()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
func makeUI() {
|
||||
contentView.addSubview(titleImageView)
|
||||
contentView.addSubview(volLabel)
|
||||
contentView.addSubview(titleLabel)
|
||||
|
||||
|
||||
|
||||
titleImageView.snp.makeConstraints { make in
|
||||
make.left.equalTo(contentView)
|
||||
make.right.equalTo(contentView)
|
||||
make.top.equalTo(contentView)
|
||||
make.height.equalTo(100)
|
||||
}
|
||||
|
||||
volLabel.snp.makeConstraints { make in
|
||||
make.left.equalTo(contentView)
|
||||
make.top.equalTo(titleImageView.snp.bottom).offset(9)
|
||||
make.right.equalTo(contentView)
|
||||
}
|
||||
|
||||
titleLabel.snp.makeConstraints { make in
|
||||
make.left.equalTo(contentView)
|
||||
make.right.equalTo(contentView)
|
||||
make.top.equalTo(volLabel.snp.bottom).offset(2)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,288 @@
|
||||
//
|
||||
// SearchResultsController.swift
|
||||
// IndieMusic
|
||||
//
|
||||
// Created by WenLei on 2024/1/2.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import RxSwift
|
||||
import RxCocoa
|
||||
import RxDataSources
|
||||
|
||||
class SearchResultsController: ViewController {
|
||||
|
||||
let searchTopBar: SearchTopBar = {
|
||||
let searchTopBar = SearchTopBar.init()
|
||||
|
||||
return searchTopBar
|
||||
}()
|
||||
|
||||
let searchNoDataView: SearchNoDataView = {
|
||||
let searchNoDataView = SearchNoDataView.init()
|
||||
|
||||
return searchNoDataView
|
||||
}()
|
||||
|
||||
let searchResultsView: SearchResultsView = {
|
||||
let searchResultsView = SearchResultsView.init()
|
||||
|
||||
return searchResultsView
|
||||
}()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
// Do any additional setup after loading the view.
|
||||
}
|
||||
|
||||
override func makeUI() {
|
||||
super.makeUI()
|
||||
|
||||
view.addSubview(searchTopBar)
|
||||
view.addSubview(searchNoDataView)
|
||||
view.addSubview(searchResultsView)
|
||||
|
||||
}
|
||||
|
||||
|
||||
override func bindViewModel() {
|
||||
super.bindViewModel()
|
||||
|
||||
}
|
||||
|
||||
|
||||
override func viewDidLayoutSubviews() {
|
||||
super.viewDidLayoutSubviews()
|
||||
|
||||
|
||||
searchTopBar.snp.makeConstraints { make in
|
||||
make.left.equalTo(view)
|
||||
make.right.equalTo(view)
|
||||
make.top.equalTo(view).offset(BaseDimensions.statusBarHeight + 15)
|
||||
make.height.equalTo(40)
|
||||
}
|
||||
|
||||
searchNoDataView.snp.makeConstraints { make in
|
||||
make.centerX.equalTo(view)
|
||||
make.top.equalTo(searchTopBar.snp.bottom).offset(45)
|
||||
}
|
||||
|
||||
searchResultsView.snp.makeConstraints { make in
|
||||
make.left.equalTo(view)
|
||||
make.right.equalTo(view)
|
||||
make.top.equalTo(searchTopBar.snp.bottom).offset(24)
|
||||
make.bottom.equalTo(view)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
class SearchTopBar: UIView {
|
||||
let searchControl: SearchControl = {
|
||||
let searchControl = SearchControl.init()
|
||||
|
||||
return searchControl
|
||||
}()
|
||||
|
||||
let cancelButton: UIButton = {
|
||||
let cancelButton = UIButton.init()
|
||||
cancelButton.titleLabel?.font = UIFont.systemFont(ofSize: 17, weight: .medium)
|
||||
cancelButton.setTitle("取消", for: .normal)
|
||||
|
||||
return cancelButton
|
||||
}()
|
||||
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
makeUI()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
func makeUI() {
|
||||
addSubview(searchControl)
|
||||
addSubview(cancelButton)
|
||||
}
|
||||
|
||||
override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
|
||||
cancelButton.snp.makeConstraints { make in
|
||||
make.right.equalTo(self).offset(-18)
|
||||
make.centerY.equalTo(self)
|
||||
}
|
||||
|
||||
searchControl.snp.makeConstraints { make in
|
||||
make.left.equalTo(self).offset(18)
|
||||
make.centerY.equalTo(self)
|
||||
make.right.equalTo(cancelButton.snp.left).offset(-12)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class SearchNoDataView: UIView {
|
||||
let titleLabel: UILabel = {
|
||||
let titleLabel = UILabel.init()
|
||||
titleLabel.font = UIFont.systemFont(ofSize: 15)
|
||||
titleLabel.textColor = .init(hex: 0x000000, alpha: 0.6)
|
||||
titleLabel.text = "暂无搜索内容"
|
||||
|
||||
return titleLabel
|
||||
}()
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
makeUI()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
func makeUI() {
|
||||
addSubview(titleLabel)
|
||||
}
|
||||
|
||||
override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
|
||||
titleLabel.snp.makeConstraints { make in
|
||||
make.center.equalTo(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class SearchResultsView: UIView {
|
||||
lazy var segmentControl: SegmentControl = {
|
||||
let segmentControl = SegmentControl.init()
|
||||
segmentControl.items = ["单曲", "期刊"]
|
||||
segmentControl.font = UIFont.systemFont(ofSize: 15)
|
||||
segmentControl.selectedFont = UIFont.systemFont(ofSize: 15)
|
||||
|
||||
|
||||
return segmentControl
|
||||
}()
|
||||
|
||||
|
||||
let tableView: UITableView = {
|
||||
let tableView = UITableView.init()
|
||||
|
||||
return tableView
|
||||
}()
|
||||
|
||||
let collectionView: UICollectionView = {
|
||||
let collectionView = UICollectionView.init()
|
||||
collectionView.isHidden = true
|
||||
|
||||
return collectionView
|
||||
}()
|
||||
|
||||
|
||||
|
||||
var currentSearchType: SearchType = .single {
|
||||
didSet {
|
||||
switch currentSearchType {
|
||||
case .single:
|
||||
collectionView.isHidden = true
|
||||
tableView.isHidden = false
|
||||
case .journal:
|
||||
collectionView.isHidden = false
|
||||
tableView.isHidden = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
makeUI()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
func makeUI() {
|
||||
addSubview(segmentControl)
|
||||
addSubview(tableView)
|
||||
addSubview(collectionView)
|
||||
|
||||
}
|
||||
|
||||
override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
|
||||
segmentControl.snp.makeConstraints { make in
|
||||
make.left.equalTo(self).offset(18)
|
||||
make.top.equalTo(self).offset(0)
|
||||
}
|
||||
|
||||
tableView.snp.makeConstraints { make in
|
||||
make.left.equalTo(self)
|
||||
make.right.equalTo(self)
|
||||
make.top.equalTo(segmentControl.snp.bottom).offset(24)
|
||||
make.bottom.equalTo(self)
|
||||
}
|
||||
|
||||
collectionView.snp.makeConstraints { make in
|
||||
make.left.equalTo(self)
|
||||
make.right.equalTo(self)
|
||||
make.top.equalTo(segmentControl.snp.bottom).offset(24)
|
||||
make.bottom.equalTo(self)
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
extension SearchResultsView {
|
||||
|
||||
static func dataSource() -> RxCollectionViewSectionedReloadDataSource<MusicStyleSection> {
|
||||
return RxCollectionViewSectionedReloadDataSource<MusicStyleSection>(
|
||||
configureCell: { dataSource, collectionView, indexPath, item in
|
||||
// 配置和返回 cell
|
||||
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MusicStyleCellView", for: indexPath)
|
||||
// 配置 cell
|
||||
return cell
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extension SearchResultsView {
|
||||
//TODO
|
||||
static func dataSource() -> RxTableViewSectionedReloadDataSource<JournalSection> {
|
||||
return RxTableViewSectionedReloadDataSource<JournalSection>(
|
||||
configureCell: { dataSource, tableView, indexPath, item in
|
||||
let cell: SongViewCell = tableView.dequeueReusableCell(withIdentifier: "SongViewCell", for: indexPath) as! SongViewCell
|
||||
|
||||
cell.audio = item
|
||||
|
||||
return cell
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
@ -0,0 +1,163 @@
|
||||
//
|
||||
// AboutViewController.swift
|
||||
// IndieMusic
|
||||
//
|
||||
// Created by WenLei on 2024/1/2.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import RxSwift
|
||||
import RxCocoa
|
||||
import RxDataSources
|
||||
|
||||
class AboutViewController: TableViewController {
|
||||
let headerView: EditInfoHeaderView = {
|
||||
let headerView = EditInfoHeaderView.init(frame: CGRect.init(x: 0, y: 0, width: BaseDimensions.screenWidth, height: 191))
|
||||
|
||||
return headerView
|
||||
}()
|
||||
|
||||
|
||||
let abloutFooterView: AbloutFooterView = {
|
||||
let abloutFooterView = AbloutFooterView.init()
|
||||
|
||||
return abloutFooterView
|
||||
}()
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
|
||||
}
|
||||
|
||||
override func makeUI() {
|
||||
super.makeUI()
|
||||
view.backgroundColor = .blue
|
||||
|
||||
tableView.register(MineViewCell.self, forCellReuseIdentifier: "SettingViewCell")
|
||||
tableView.tableHeaderView = headerView
|
||||
|
||||
|
||||
view.addSubview(abloutFooterView)
|
||||
}
|
||||
|
||||
|
||||
|
||||
override func bindViewModel() {
|
||||
super.bindViewModel()
|
||||
|
||||
guard let viewModel = viewModel as? MineViewModel else { return }
|
||||
|
||||
let input = MineViewModel.Input.init(viewWillAppear: rx.viewWillAppear,
|
||||
selection: tableView.rx.itemSelected.asDriver())
|
||||
let output = viewModel.transform(input: input)
|
||||
|
||||
let dataSource = MineViewController.dataSource()
|
||||
|
||||
output.items.bind(to: tableView.rx.items(dataSource: dataSource)).disposed(by: rx.disposeBag)
|
||||
|
||||
|
||||
output.itemSelected.subscribe { sectionItem in
|
||||
|
||||
|
||||
}.disposed(by: rx.disposeBag)
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
override func viewDidLayoutSubviews() {
|
||||
super.viewDidLayoutSubviews()
|
||||
|
||||
abloutFooterView.snp.makeConstraints { make in
|
||||
make.bottom.equalTo(view).offset(-BaseDimensions.bottomHeight)
|
||||
make.left.equalTo(view)
|
||||
make.right.equalTo(view)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
extension AboutViewController {
|
||||
static func dataSource() -> RxTableViewSectionedReloadDataSource<MineSection> {
|
||||
return RxTableViewSectionedReloadDataSource<MineSection>(
|
||||
configureCell: { dataSource, tableView, indexPath, item in
|
||||
let cell: MineViewCell = tableView.dequeueReusableCell(withIdentifier: "SettingViewCell", for: indexPath) as! MineViewCell
|
||||
|
||||
cell.titleLabel.text = "123"
|
||||
cell.detailLabel.text = "321"
|
||||
|
||||
return cell
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
class AbloutFooterView: UIView, UITextViewDelegate {
|
||||
let textView: UITextView = {
|
||||
let textView = UITextView.init()
|
||||
textView.addAttributed(attributedes: [("服务条款 ", [NSAttributedString.Key.foregroundColor: UIColor.primary(), NSAttributedString.Key.link: URL.init(string: Configs.App.aggrementUrl) ?? ""]),
|
||||
(" 版权声明 ", [NSAttributedString.Key.foregroundColor: UIColor.primary(), NSAttributedString.Key.link: URL.init(string: Configs.App.aggrementUrl) ?? ""]),
|
||||
(" 许可协议", [NSAttributedString.Key.foregroundColor: UIColor.primary(), NSAttributedString.Key.link: URL.init(string: Configs.App.aggrementUrl) ?? ""])
|
||||
])
|
||||
|
||||
return textView
|
||||
}()
|
||||
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
makeUI()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
func makeUI() {
|
||||
|
||||
addSubview(textView)
|
||||
}
|
||||
|
||||
override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
|
||||
textView.snp.makeConstraints { make in
|
||||
make.edges.equalTo(self).offset(18)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {
|
||||
|
||||
switch URL.scheme {
|
||||
case Configs.App.aggrementUrl:
|
||||
return false
|
||||
// case Configs.App.aggrementUrl:
|
||||
// break
|
||||
// case Configs.App.aggrementUrl:
|
||||
// break
|
||||
|
||||
default:
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@available(iOS 17.0, *)
|
||||
func textView(_ textView: UITextView, menuConfigurationFor textItem: UITextItem, defaultMenu: UIMenu) -> UITextItem.MenuConfiguration? {
|
||||
if case .link(let url) = textItem.content {
|
||||
print("menu \(url)")
|
||||
return nil
|
||||
}
|
||||
|
||||
return .init(menu: defaultMenu)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,19 @@
|
||||
//
|
||||
// AccountViewController.swift
|
||||
// IndieMusic
|
||||
//
|
||||
// Created by WenLei on 2024/1/1.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class AccountViewController: TableViewController {
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
// Do any additional setup after loading the view.
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
//
|
||||
// AccountViewModel.swift
|
||||
// IndieMusic
|
||||
//
|
||||
// Created by WenLei on 2024/1/1.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import RxSwift
|
||||
import RxCocoa
|
||||
import RxDataSources
|
||||
|
||||
class AccountViewModel: ViewModel, ViewModelType {
|
||||
|
||||
struct Input {
|
||||
let viewWillAppear: ControlEvent<Bool>
|
||||
let selection: Driver<IndexPath>
|
||||
|
||||
}
|
||||
|
||||
struct Output {
|
||||
let items: BehaviorRelay<[SettingSection]>
|
||||
let selection: Driver<IndexPath>
|
||||
let itemSelected: PublishSubject<Setting>
|
||||
|
||||
}
|
||||
|
||||
let itemSelected = PublishSubject<Setting>()
|
||||
let items = BehaviorRelay<[SettingSection]>.init(value: [])
|
||||
|
||||
func transform(input: Input) -> Output {
|
||||
|
||||
input.viewWillAppear.subscribe { (_) in
|
||||
|
||||
}.disposed(by: rx.disposeBag)
|
||||
|
||||
let phone = Setting.init(title: "手机号", detail: "去绑定", arrowIcon: "setting_arrow")
|
||||
let wechatBinding = Setting.init(title: "绑定微信", detail: "", arrowIcon: "setting_arrow")
|
||||
let privacy = Setting.init(title: "注销账户", detail: "", arrowIcon: "setting_arrow")
|
||||
|
||||
|
||||
//TODO
|
||||
items.accept([SettingSection.init(items: [.setting(phone), .setting(wechatBinding), .setting(privacy)])])
|
||||
|
||||
|
||||
input.selection.drive { indexPath in
|
||||
guard let sectionItem = self.items.value.first?.items[indexPath.row] else { return }
|
||||
|
||||
|
||||
switch sectionItem {
|
||||
case .about(let setting):
|
||||
|
||||
// case .account(let setting):
|
||||
// case .privacy(let setting):
|
||||
// case .timing(let setting):
|
||||
// case .cache(let setting):
|
||||
// case .permission(let setting):
|
||||
// case .feedback(let setting):
|
||||
// case .about(let setting):
|
||||
// case .contributors(let setting):
|
||||
// case .version(let setting):
|
||||
|
||||
self.itemSelected.onNext(setting)
|
||||
|
||||
default: break
|
||||
|
||||
}
|
||||
|
||||
}.disposed(by: rx.disposeBag)
|
||||
|
||||
|
||||
|
||||
return Output.init(items: items,
|
||||
selection: input.selection,
|
||||
itemSelected: itemSelected)
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,176 @@
|
||||
//
|
||||
// CacheViewController.swift
|
||||
// IndieMusic
|
||||
//
|
||||
// Created by WenLei on 2024/1/2.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class CacheViewController: TableViewController {
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
// Do any additional setup after loading the view.
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
class CacheViewCell: UITableViewCell {
|
||||
let titleLabel: UILabel = {
|
||||
let titleLabel = UILabel.init()
|
||||
titleLabel.font = UIFont.systemFont(ofSize: 12)
|
||||
titleLabel.textColor = .init(hex: 0x000000)
|
||||
|
||||
return titleLabel
|
||||
}()
|
||||
|
||||
let detaileLabel: UILabel = {
|
||||
let detaileLabel = UILabel.init()
|
||||
detaileLabel.font = .systemFont(ofSize: 18)
|
||||
|
||||
return detaileLabel
|
||||
}()
|
||||
|
||||
|
||||
let actionButton: UIButton = {
|
||||
let actionButton = UIButton.init()
|
||||
|
||||
return actionButton
|
||||
}()
|
||||
|
||||
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
||||
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
||||
|
||||
makeUI()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
func makeUI() {
|
||||
|
||||
contentView.addSubview(titleLabel)
|
||||
contentView.addSubview(detaileLabel)
|
||||
contentView.addSubview(actionButton)
|
||||
|
||||
|
||||
|
||||
actionButton.snp.makeConstraints { make in
|
||||
make.right.equalTo(contentView).offset(-18)
|
||||
make.centerY.equalTo(contentView)
|
||||
}
|
||||
|
||||
titleLabel.snp.makeConstraints { make in
|
||||
make.left.equalTo(contentView).offset(18)
|
||||
make.top.equalTo(contentView).offset(18)
|
||||
}
|
||||
|
||||
detaileLabel.snp.makeConstraints { make in
|
||||
make.left.equalTo(titleLabel)
|
||||
make.top.equalTo(titleLabel.snp.bottom).offset(1)
|
||||
make.right.equalTo(actionButton.snp.left).offset(-18)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
class CacheHeaderView: UIView {
|
||||
|
||||
private var progressLayer = CAShapeLayer()
|
||||
private var trackLayer = CAShapeLayer()
|
||||
|
||||
|
||||
let titleLabel: UILabel = {
|
||||
let titleLabel = UILabel.init()
|
||||
|
||||
return titleLabel
|
||||
}()
|
||||
|
||||
let contentLabel: UILabel = {
|
||||
let contentLabel = UILabel.init()
|
||||
|
||||
return contentLabel
|
||||
}()
|
||||
|
||||
let tipsLabel: UILabel = {
|
||||
let tipsLabel = UILabel.init()
|
||||
|
||||
return tipsLabel
|
||||
}()
|
||||
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
createCircularPath()
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
super.init(coder: aDecoder)
|
||||
createCircularPath()
|
||||
}
|
||||
|
||||
|
||||
func makeUI() {
|
||||
addSubview(titleLabel)
|
||||
addSubview(contentLabel)
|
||||
addSubview(tipsLabel)
|
||||
|
||||
}
|
||||
|
||||
|
||||
override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
|
||||
|
||||
titleLabel.snp.makeConstraints { make in
|
||||
make.centerX.equalTo(self)
|
||||
make.top.equalTo(self).offset(52)
|
||||
}
|
||||
|
||||
contentLabel.snp.makeConstraints { make in
|
||||
make.centerX.equalTo(self)
|
||||
make.left.equalTo(self).offset(10)
|
||||
make.right.equalTo(self).offset(-10)
|
||||
make.top.equalTo(titleLabel.snp.bottom).offset(8)
|
||||
}
|
||||
|
||||
tipsLabel.snp.makeConstraints { make in
|
||||
make.centerX.equalTo(self)
|
||||
make.top.equalTo(contentLabel.snp.bottom).offset(3)
|
||||
}
|
||||
}
|
||||
|
||||
private func createCircularPath() {
|
||||
self.backgroundColor = .clear
|
||||
self.layer.cornerRadius = self.frame.size.width / 2
|
||||
|
||||
let circlePath = UIBezierPath(arcCenter: CGPoint(x: frame.size.width / 2, y: frame.size.height / 2), radius: (frame.size.width - 1.5) / 2, startAngle: CGFloat(-0.5 * .pi), endAngle: CGFloat(1.5 * .pi), clockwise: false)
|
||||
|
||||
trackLayer.path = circlePath.cgPath
|
||||
trackLayer.fillColor = UIColor.clear.cgColor
|
||||
trackLayer.strokeColor = UIColor.lightGray.cgColor
|
||||
trackLayer.lineWidth = 5.0
|
||||
trackLayer.strokeEnd = 1.0
|
||||
layer.addSublayer(trackLayer)
|
||||
|
||||
progressLayer.path = circlePath.cgPath
|
||||
progressLayer.fillColor = UIColor.clear.cgColor
|
||||
progressLayer.strokeColor = UIColor.red.cgColor
|
||||
progressLayer.lineWidth = 5.0
|
||||
progressLayer.strokeEnd = 0.0
|
||||
layer.addSublayer(progressLayer)
|
||||
}
|
||||
|
||||
func setProgress(to progressConstant: CGFloat) {
|
||||
progressLayer.strokeEnd = progressConstant
|
||||
}
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
//
|
||||
// EditInfoView.swift
|
||||
// IndieMusic
|
||||
//
|
||||
// Created by WenLei on 2024/1/1.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class EditInfoHeaderView: UIView {
|
||||
let avatorView: UIImageView = {
|
||||
let avatorView = UIImageView.init()
|
||||
avatorView.layer.cornerRadius = 45
|
||||
avatorView.layer.masksToBounds = true
|
||||
|
||||
return avatorView
|
||||
}()
|
||||
|
||||
let tipsLabel: UILabel = {
|
||||
let tipsLabel = UILabel.init()
|
||||
tipsLabel.font = UIFont.systemFont(ofSize: 15)
|
||||
tipsLabel.text = "点击更换头像"
|
||||
tipsLabel.textColor = .tertiaryText()
|
||||
|
||||
return tipsLabel
|
||||
}()
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
makeUI()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
func makeUI() {
|
||||
addSubview(avatorView)
|
||||
addSubview(tipsLabel)
|
||||
|
||||
}
|
||||
|
||||
override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
|
||||
avatorView.snp.makeConstraints { make in
|
||||
make.centerX.equalTo(self)
|
||||
make.top.equalTo(self).offset(31)
|
||||
make.size.equalTo(CGSize.init(width: 90, height: 90))
|
||||
}
|
||||
|
||||
tipsLabel.snp.makeConstraints { make in
|
||||
make.centerX.equalTo(self)
|
||||
make.top.equalTo(avatorView.snp.bottom).offset(15)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
//
|
||||
// EditInfoViewController.swift
|
||||
// IndieMusic
|
||||
//
|
||||
// Created by WenLei on 2024/1/1.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import RxSwift
|
||||
import RxCocoa
|
||||
import RxDataSources
|
||||
|
||||
class EditInfoViewController: TableViewController {
|
||||
let headerView: EditInfoHeaderView = {
|
||||
let headerView = EditInfoHeaderView.init(frame: CGRect.init(x: 0, y: 0, width: BaseDimensions.screenWidth, height: 191))
|
||||
|
||||
return headerView
|
||||
}()
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
|
||||
}
|
||||
|
||||
override func makeUI() {
|
||||
super.makeUI()
|
||||
view.backgroundColor = .blue
|
||||
|
||||
tableView.register(MineViewCell.self, forCellReuseIdentifier: "SettingViewCell")
|
||||
tableView.tableHeaderView = headerView
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
override func bindViewModel() {
|
||||
super.bindViewModel()
|
||||
|
||||
guard let viewModel = viewModel as? MineViewModel else { return }
|
||||
|
||||
let input = MineViewModel.Input.init(viewWillAppear: rx.viewWillAppear,
|
||||
selection: tableView.rx.itemSelected.asDriver())
|
||||
let output = viewModel.transform(input: input)
|
||||
|
||||
let dataSource = MineViewController.dataSource()
|
||||
|
||||
output.items.bind(to: tableView.rx.items(dataSource: dataSource)).disposed(by: rx.disposeBag)
|
||||
|
||||
|
||||
output.itemSelected.subscribe { sectionItem in
|
||||
|
||||
|
||||
}.disposed(by: rx.disposeBag)
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
extension EditInfoViewController {
|
||||
static func dataSource() -> RxTableViewSectionedReloadDataSource<MineSection> {
|
||||
return RxTableViewSectionedReloadDataSource<MineSection>(
|
||||
configureCell: { dataSource, tableView, indexPath, item in
|
||||
let cell: MineViewCell = tableView.dequeueReusableCell(withIdentifier: "SettingViewCell", for: indexPath) as! MineViewCell
|
||||
|
||||
cell.titleLabel.text = "123"
|
||||
cell.detailLabel.text = "321"
|
||||
|
||||
return cell
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,79 @@
|
||||
//
|
||||
// EditInfoViewModel.swift
|
||||
// IndieMusic
|
||||
//
|
||||
// Created by WenLei on 2024/1/1.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
import RxSwift
|
||||
import RxCocoa
|
||||
import RxDataSources
|
||||
|
||||
class EditInfoViewModel: ViewModel, ViewModelType {
|
||||
|
||||
struct Input {
|
||||
let viewWillAppear: ControlEvent<Bool>
|
||||
let selection: Driver<IndexPath>
|
||||
|
||||
}
|
||||
|
||||
struct Output {
|
||||
let items: BehaviorRelay<[SettingSection]>
|
||||
let selection: Driver<IndexPath>
|
||||
let itemSelected: PublishSubject<Setting>
|
||||
|
||||
}
|
||||
|
||||
let itemSelected = PublishSubject<Setting>()
|
||||
let items = BehaviorRelay<[SettingSection]>.init(value: [])
|
||||
|
||||
func transform(input: Input) -> Output {
|
||||
|
||||
input.viewWillAppear.subscribe { (_) in
|
||||
|
||||
}.disposed(by: rx.disposeBag)
|
||||
|
||||
let name = Setting.init(title: "用户名", detail: "", arrowIcon: "")
|
||||
let slogn = Setting.init(title: "签名", detail: "", arrowIcon: "")
|
||||
let birthDay = Setting.init(title: "生日", detail: "", arrowIcon: "")
|
||||
let sex = Setting.init(title: "性别", detail: "", arrowIcon: "")
|
||||
|
||||
|
||||
items.accept([SettingSection.init(items: [.setting(name), .setting(slogn), .setting(birthDay), .setting(sex)])])
|
||||
|
||||
|
||||
input.selection.drive { indexPath in
|
||||
guard let sectionItem = self.items.value.first?.items[indexPath.row] else { return }
|
||||
|
||||
switch sectionItem {
|
||||
case .about(let setting):
|
||||
|
||||
// case .account(let setting):
|
||||
// case .privacy(let setting):
|
||||
// case .timing(let setting):
|
||||
// case .cache(let setting):
|
||||
// case .permission(let setting):
|
||||
// case .feedback(let setting):
|
||||
// case .about(let setting):
|
||||
// case .contributors(let setting):
|
||||
// case .version(let setting):
|
||||
|
||||
self.itemSelected.onNext(setting)
|
||||
|
||||
default: break
|
||||
|
||||
}
|
||||
|
||||
}.disposed(by: rx.disposeBag)
|
||||
|
||||
|
||||
|
||||
return Output.init(items: items,
|
||||
selection: input.selection,
|
||||
itemSelected: itemSelected)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,80 @@
|
||||
//
|
||||
// EditNameController.swift
|
||||
// IndieMusic
|
||||
//
|
||||
// Created by WenLei on 2024/1/1.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class EditNameController: ViewController {
|
||||
let editNameTextField: EditNameTextField = {
|
||||
let editNameTextField = EditNameTextField.init(frame: CGRect.init(x: 0, y: 0, width: BaseDimensions.screenWidth, height: 52))
|
||||
return editNameTextField
|
||||
}()
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
// Do any additional setup after loading the view.
|
||||
}
|
||||
|
||||
override func makeUI() {
|
||||
super.makeUI()
|
||||
|
||||
view.addSubview(editNameTextField)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
class EditNameTextField: UIView {
|
||||
let textFieldView: UITextField = {
|
||||
let textFieldView = UITextField.init()
|
||||
|
||||
return textFieldView
|
||||
}()
|
||||
|
||||
let countTipsLabel: UILabel = {
|
||||
let countTipsLabel = UILabel.init()
|
||||
countTipsLabel.font = UIFont.systemFont(ofSize: 15)
|
||||
|
||||
|
||||
|
||||
return countTipsLabel
|
||||
}()
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
makeUI()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
func makeUI() {
|
||||
addSubview(textFieldView)
|
||||
addSubview(countTipsLabel)
|
||||
|
||||
}
|
||||
|
||||
override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
|
||||
countTipsLabel.snp.makeConstraints { make in
|
||||
make.right.equalTo(self).offset(-18)
|
||||
make.centerY.equalTo(self)
|
||||
}
|
||||
|
||||
|
||||
textFieldView.snp.makeConstraints { make in
|
||||
make.left.equalTo(self).offset(18)
|
||||
make.right.equalTo(countTipsLabel.snp.left).offset(-18)
|
||||
make.centerY.equalTo(self)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,329 @@
|
||||
//
|
||||
// FeedbackViewController.swift
|
||||
// IndieMusic
|
||||
//
|
||||
// Created by WenLei on 2024/1/1.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class FeedbackViewController: ViewController {
|
||||
let feedbackTypeView: FeedbackTypeView = {
|
||||
let feedbackTypeView = FeedbackTypeView.init()
|
||||
|
||||
return feedbackTypeView
|
||||
}()
|
||||
|
||||
let feedbackDetailView: FeedbackDetailView = {
|
||||
let feedbackDetailView = FeedbackDetailView.init()
|
||||
|
||||
return feedbackDetailView
|
||||
}()
|
||||
|
||||
let feedbackContactView: FeedbackContactView = {
|
||||
let feedbackContactView = FeedbackContactView.init()
|
||||
|
||||
return feedbackContactView
|
||||
}()
|
||||
|
||||
|
||||
let confirmButton: UIButton = {
|
||||
let confirmButton = UIButton.init()
|
||||
confirmButton.setTitle("提交", for: .normal)
|
||||
confirmButton.titleLabel?.font = UIFont.systemFont(ofSize: 15)
|
||||
confirmButton.backgroundColor = .init(hex: 0x000000)
|
||||
return confirmButton
|
||||
}()
|
||||
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
// Do any additional setup after loading the view.
|
||||
}
|
||||
|
||||
|
||||
override func makeUI() {
|
||||
super.makeUI()
|
||||
|
||||
view.addSubview(feedbackTypeView)
|
||||
view.addSubview(feedbackDetailView)
|
||||
view.addSubview(feedbackContactView)
|
||||
view.addSubview(confirmButton)
|
||||
|
||||
}
|
||||
|
||||
|
||||
override func viewDidLayoutSubviews() {
|
||||
super.viewDidLayoutSubviews()
|
||||
|
||||
feedbackTypeView.snp.makeConstraints { make in
|
||||
make.left.equalTo(view)
|
||||
make.right.equalTo(view)
|
||||
make.top.equalTo(view)
|
||||
}
|
||||
|
||||
feedbackDetailView.snp.makeConstraints { make in
|
||||
make.left.equalTo(view)
|
||||
make.right.equalTo(view)
|
||||
make.top.equalTo(feedbackTypeView.snp.bottom)
|
||||
}
|
||||
|
||||
feedbackContactView.snp.makeConstraints { make in
|
||||
make.left.equalTo(view)
|
||||
make.right.equalTo(view)
|
||||
make.top.equalTo(feedbackDetailView.snp.bottom)
|
||||
|
||||
}
|
||||
|
||||
confirmButton.snp.makeConstraints { make in
|
||||
make.left.equalTo(view)
|
||||
make.right.equalTo(view)
|
||||
make.top.equalTo(feedbackContactView.snp.bottom).offset(30)
|
||||
make.height.equalTo(44)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
class FeedbackTypeView: UIView {
|
||||
let titleLabel: UILabel = {
|
||||
let titleLabel = UILabel.init()
|
||||
|
||||
return titleLabel
|
||||
}()
|
||||
|
||||
let feedbackTypeControl: FeedbackTypeControl = {
|
||||
let feedbackTypeControl = FeedbackTypeControl.init()
|
||||
|
||||
return feedbackTypeControl
|
||||
}()
|
||||
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
makeUI()
|
||||
}
|
||||
|
||||
func makeUI() {
|
||||
addSubview(titleLabel)
|
||||
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class FeedbackTypeControl: UIControl {
|
||||
let titleLabel: UILabel = {
|
||||
let titleLabel = UILabel.init()
|
||||
titleLabel.font = UIFont.systemFont(ofSize: 15)
|
||||
|
||||
return titleLabel
|
||||
}()
|
||||
|
||||
let detailLabel: UILabel = {
|
||||
let detailLabel = UILabel.init()
|
||||
detailLabel.font = .systemFont(ofSize: 15)
|
||||
|
||||
return detailLabel
|
||||
}()
|
||||
|
||||
let arrowView: UIImageView = {
|
||||
let arrowView = UIImageView .init()
|
||||
arrowView.image = UIImage.init(named: "")
|
||||
|
||||
return arrowView
|
||||
}()
|
||||
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
makeUI()
|
||||
}
|
||||
|
||||
func makeUI() {
|
||||
addSubview(titleLabel)
|
||||
addSubview(detailLabel)
|
||||
addSubview(arrowView)
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
arrowView.snp.makeConstraints { make in
|
||||
make.right.equalTo(self)
|
||||
make.centerY.equalTo(self)
|
||||
}
|
||||
|
||||
detailLabel.snp.makeConstraints { make in
|
||||
make.right.equalTo(arrowView.snp.left).offset(-18)
|
||||
make.centerY.equalTo(self)
|
||||
}
|
||||
|
||||
titleLabel.snp.makeConstraints { make in
|
||||
make.left.equalTo(self).offset(18)
|
||||
make.top.equalTo(self).offset(12)
|
||||
make.width.equalTo(100)
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class FeedbackDetailView: UIView {
|
||||
let titleLabel: UILabel = {
|
||||
let titleLabel = UILabel.init()
|
||||
titleLabel.font = UIFont.systemFont(ofSize: 15)
|
||||
|
||||
return titleLabel
|
||||
}()
|
||||
|
||||
let feedbackDetailSubView: FeedbackDetailSubView = {
|
||||
let feedbackDetailSubView = FeedbackDetailSubView.init()
|
||||
|
||||
return feedbackDetailSubView
|
||||
}()
|
||||
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
makeUI()
|
||||
}
|
||||
|
||||
func makeUI() {
|
||||
addSubview(titleLabel)
|
||||
addSubview(feedbackDetailSubView)
|
||||
|
||||
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class FeedbackDetailSubView: UIView {
|
||||
let textView: UITextView = {
|
||||
let textView = UITextView.init()
|
||||
|
||||
return textView
|
||||
}()
|
||||
|
||||
let countLabel: UILabel = {
|
||||
let countLabel = UILabel.init()
|
||||
countLabel.font = UIFont.systemFont(ofSize: 14)
|
||||
|
||||
return countLabel
|
||||
}()
|
||||
|
||||
// TODO:相册
|
||||
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
makeUI()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
func makeUI() {
|
||||
addSubview(textView)
|
||||
addSubview(countLabel)
|
||||
|
||||
}
|
||||
|
||||
override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
|
||||
textView.snp.makeConstraints { make in
|
||||
make.left.equalTo(self)
|
||||
make.right.equalTo(self)
|
||||
make.top.equalTo(self)
|
||||
}
|
||||
|
||||
countLabel.snp.makeConstraints { make in
|
||||
make.right.equalTo(self).offset(-12)
|
||||
make.top.equalTo(textView.snp.bottom).offset(20)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
class FeedbackContactView: UIView {
|
||||
let titleLabel: UILabel = {
|
||||
let titleLabel = UILabel.init()
|
||||
titleLabel.font = UIFont.systemFont(ofSize: 15)
|
||||
|
||||
return titleLabel
|
||||
}()
|
||||
|
||||
let textFieldView: UITextField = {
|
||||
let textFieldView = UITextField.init()
|
||||
textFieldView.font = UIFont.systemFont(ofSize: 15)
|
||||
textFieldView.placeholder = "手机/邮箱"
|
||||
|
||||
return textFieldView
|
||||
}()
|
||||
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
makeUI()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
func makeUI() {
|
||||
addSubview(titleLabel)
|
||||
addSubview(textFieldView)
|
||||
|
||||
}
|
||||
|
||||
override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
|
||||
titleLabel.snp.makeConstraints { make in
|
||||
make.left.equalTo(self).offset(18)
|
||||
make.top.equalTo(self).offset(12)
|
||||
}
|
||||
|
||||
textFieldView.snp.makeConstraints { make in
|
||||
make.left.equalTo(self).offset(18)
|
||||
make.right.equalTo(self).offset(-18)
|
||||
make.top.equalTo(titleLabel.snp.bottom).offset(9)
|
||||
make.height.equalTo(45)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
//
|
||||
// PrivacyViewController.swift
|
||||
// IndieMusic
|
||||
//
|
||||
// Created by WenLei on 2024/1/2.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class PrivacyViewController: TableViewController {
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
}
|
||||
|
||||
|
||||
override func makeUI() {
|
||||
super.makeUI()
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,111 @@
|
||||
//
|
||||
// SettingView.swift
|
||||
// IndieMusic
|
||||
//
|
||||
// Created by WenLei on 2024/1/1.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class SettingViewCell: UITableViewCell {
|
||||
let titleLabel: UILabel = {
|
||||
let titleLabel = UILabel.init()
|
||||
titleLabel.font = .systemFont(ofSize: 15)
|
||||
|
||||
return titleLabel
|
||||
}()
|
||||
|
||||
let detailLabel: UILabel = {
|
||||
let detailLabel = UILabel.init()
|
||||
detailLabel.font = UIFont.systemFont(ofSize: 15)
|
||||
detailLabel.textColor = .secondaryText()
|
||||
|
||||
return detailLabel
|
||||
}()
|
||||
|
||||
let arrowView: UIImageView = {
|
||||
let arrowView = UIImageView.init()
|
||||
arrowView.image = UIImage.init(named: "setting_arrow")
|
||||
|
||||
return arrowView
|
||||
}()
|
||||
|
||||
let switchButton: UISwitch = {
|
||||
let switchButton = UISwitch.init()
|
||||
switchButton.isHidden = true
|
||||
|
||||
return switchButton
|
||||
}()
|
||||
|
||||
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
||||
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
||||
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
|
||||
func makeUI() {
|
||||
contentView.addSubview(titleLabel)
|
||||
contentView.addSubview(detailLabel)
|
||||
contentView.addSubview(arrowView)
|
||||
|
||||
contentView.addSubview(switchButton)
|
||||
|
||||
|
||||
|
||||
arrowView.snp.makeConstraints { make in
|
||||
make.right.equalTo(contentView).offset(-18)
|
||||
make.centerY.equalTo(contentView)
|
||||
}
|
||||
|
||||
detailLabel.snp.makeConstraints { make in
|
||||
make.right.equalTo(arrowView.snp.left).offset(2)
|
||||
make.centerY.equalTo(contentView)
|
||||
}
|
||||
|
||||
titleLabel.snp.makeConstraints { make in
|
||||
make.left.equalTo(contentView).offset(18)
|
||||
make.centerY.equalTo(contentView)
|
||||
make.right.equalTo(detailLabel.snp.left).offset(-18)
|
||||
}
|
||||
|
||||
switchButton.snp.makeConstraints { make in
|
||||
make.right.equalTo(arrowView.snp.left).offset(2)
|
||||
make.centerY.equalTo(contentView)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
class SettingViewFooterView: UIView {
|
||||
let logoutButton: UIButton = {
|
||||
let logoutButton = UIButton.init()
|
||||
logoutButton.titleLabel?.font = UIFont.systemFont(ofSize: 15)
|
||||
logoutButton.setTitle("退出登录", for: .normal)
|
||||
|
||||
return logoutButton
|
||||
}()
|
||||
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
addSubview(logoutButton)
|
||||
|
||||
logoutButton.snp.makeConstraints { make in
|
||||
make.edges.equalTo(self)
|
||||
}
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
//
|
||||
// SettingViewController.swift
|
||||
// IndieMusic
|
||||
//
|
||||
// Created by WenLei on 2024/1/1.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import RxSwift
|
||||
import RxCocoa
|
||||
import RxDataSources
|
||||
|
||||
class SettingViewController: TableViewController {
|
||||
let footerView: SettingViewFooterView = {
|
||||
let footerView = SettingViewFooterView.init(frame: CGRect.init(x: 0, y: 0, width: BaseDimensions.screenWidth, height: 52))
|
||||
|
||||
return footerView
|
||||
}()
|
||||
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
|
||||
}
|
||||
|
||||
override func makeUI() {
|
||||
super.makeUI()
|
||||
view.backgroundColor = .blue
|
||||
|
||||
tableView.register(MineViewCell.self, forCellReuseIdentifier: "SettingViewCell")
|
||||
tableView.tableFooterView = footerView
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
override func bindViewModel() {
|
||||
super.bindViewModel()
|
||||
|
||||
guard let viewModel = viewModel as? MineViewModel else { return }
|
||||
|
||||
let input = MineViewModel.Input.init(viewWillAppear: rx.viewWillAppear,
|
||||
selection: tableView.rx.itemSelected.asDriver())
|
||||
let output = viewModel.transform(input: input)
|
||||
|
||||
let dataSource = MineViewController.dataSource()
|
||||
|
||||
output.items.bind(to: tableView.rx.items(dataSource: dataSource)).disposed(by: rx.disposeBag)
|
||||
|
||||
|
||||
output.itemSelected.subscribe { sectionItem in
|
||||
|
||||
|
||||
}.disposed(by: rx.disposeBag)
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
extension SettingViewController {
|
||||
static func dataSource() -> RxTableViewSectionedReloadDataSource<MineSection> {
|
||||
return RxTableViewSectionedReloadDataSource<MineSection>(
|
||||
configureCell: { dataSource, tableView, indexPath, item in
|
||||
let cell: MineViewCell = tableView.dequeueReusableCell(withIdentifier: "SettingViewCell", for: indexPath) as! MineViewCell
|
||||
|
||||
cell.titleLabel.text = "123"
|
||||
cell.detailLabel.text = "321"
|
||||
|
||||
return cell
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,89 @@
|
||||
//
|
||||
// SettingViewMdel.swift
|
||||
// IndieMusic
|
||||
//
|
||||
// Created by WenLei on 2024/1/1.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import RxSwift
|
||||
import RxCocoa
|
||||
import RxDataSources
|
||||
|
||||
|
||||
class SettingViewMdel: ViewModel, ViewModelType {
|
||||
|
||||
struct Input {
|
||||
let viewWillAppear: ControlEvent<Bool>
|
||||
let selection: Driver<IndexPath>
|
||||
|
||||
}
|
||||
|
||||
struct Output {
|
||||
let items: BehaviorRelay<[SettingSection]>
|
||||
let selection: Driver<IndexPath>
|
||||
let itemSelected: PublishSubject<Setting>
|
||||
|
||||
}
|
||||
|
||||
let itemSelected = PublishSubject<Setting>()
|
||||
let items = BehaviorRelay<[SettingSection]>.init(value: [])
|
||||
|
||||
func transform(input: Input) -> Output {
|
||||
|
||||
input.viewWillAppear.subscribe { (_) in
|
||||
|
||||
}.disposed(by: rx.disposeBag)
|
||||
|
||||
let editInfo = Setting.init(title: "编辑资料", detail: "", arrowIcon: "setting_arrow")
|
||||
let account = Setting.init(title: "账户与安全", detail: "", arrowIcon: "setting_arrow")
|
||||
let privacy = Setting.init(title: "消息和隐私设置", detail: "", arrowIcon: "setting_arrow")
|
||||
|
||||
|
||||
let timing = Setting.init(title: "定时关闭", detail: "", arrowIcon: "setting_arrow")
|
||||
let cache = Setting.init(title: "清理缓存", detail: "", arrowIcon: "setting_arrow")
|
||||
let permission = Setting.init(title: "个人信息与权限", detail: "", arrowIcon: "setting_arrow")
|
||||
|
||||
|
||||
let feedback = Setting.init(title: "意见反馈", detail: "", arrowIcon: "setting_arrow")
|
||||
let about = Setting.init(title: "关于雀乐", detail: "", arrowIcon: "setting_arrow")
|
||||
let contributors = Setting.init(title: "贡献者名单", detail: "", arrowIcon: "setting_arrow")
|
||||
let version = Setting.init(title: "检查版本", detail: "", arrowIcon: "setting_arrow")
|
||||
|
||||
|
||||
items.accept([SettingSection.init(items: [.editInfo(editInfo), .account(account), .privacy(privacy)])])
|
||||
|
||||
|
||||
input.selection.drive { indexPath in
|
||||
guard let sectionItem = self.items.value.first?.items[indexPath.row] else { return }
|
||||
|
||||
|
||||
switch sectionItem {
|
||||
case .about(let setting):
|
||||
|
||||
// case .account(let setting):
|
||||
// case .privacy(let setting):
|
||||
// case .timing(let setting):
|
||||
// case .cache(let setting):
|
||||
// case .permission(let setting):
|
||||
// case .feedback(let setting):
|
||||
// case .about(let setting):
|
||||
// case .contributors(let setting):
|
||||
// case .version(let setting):
|
||||
|
||||
self.itemSelected.onNext(setting)
|
||||
|
||||
default: break
|
||||
|
||||
}
|
||||
|
||||
}.disposed(by: rx.disposeBag)
|
||||
|
||||
|
||||
|
||||
return Output.init(items: items,
|
||||
selection: input.selection,
|
||||
itemSelected: itemSelected)
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,114 @@
|
||||
//
|
||||
// ThanksViewController.swift
|
||||
// IndieMusic
|
||||
//
|
||||
// Created by WenLei on 2024/1/1.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class ThanksViewController: ViewController {
|
||||
let headerView: ThanksHeaderView = {
|
||||
let headerView = ThanksHeaderView.init()
|
||||
|
||||
return headerView
|
||||
}()
|
||||
|
||||
let collectionView: UICollectionView = {
|
||||
let collectionView = UICollectionView.init()
|
||||
|
||||
return collectionView
|
||||
}()
|
||||
|
||||
let confirmButton: UIButton = {
|
||||
let confirmButton = UIButton.init()
|
||||
confirmButton.setTitle("成为贡献者", for: .normal)
|
||||
confirmButton.titleLabel?.font = UIFont.systemFont(ofSize: 15)
|
||||
confirmButton.backgroundColor = .init(hex: 0xAD3030)
|
||||
|
||||
return confirmButton
|
||||
}()
|
||||
|
||||
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
// Do any additional setup after loading the view.
|
||||
}
|
||||
|
||||
|
||||
override func makeUI() {
|
||||
super.makeUI()
|
||||
|
||||
view.addSubview(collectionView)
|
||||
view.addSubview(confirmButton)
|
||||
|
||||
}
|
||||
|
||||
|
||||
override func viewDidLayoutSubviews() {
|
||||
super.viewDidLayoutSubviews()
|
||||
|
||||
collectionView.snp.makeConstraints { make in
|
||||
make.edges.equalTo(view)
|
||||
}
|
||||
|
||||
confirmButton.snp.makeConstraints { make in
|
||||
make.centerX.equalTo(view)
|
||||
make.bottom.equalTo(view).offset(-BaseDimensions.bottomHeight - 10)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class ThanksHeaderView: UIView {
|
||||
let titleImageView: UIImageView = {
|
||||
let titleImageView = UIImageView.init(image: UIImage.init(named: ""))
|
||||
|
||||
return titleImageView
|
||||
}()
|
||||
|
||||
let titleLabel: UILabel = {
|
||||
let titleLabel = UILabel.init()
|
||||
titleLabel.text = "这些年里,我们依旧在那些得到与失去中彳亍前行,虽然各有各的人生困苦,却不及此刻重逢的欢愉。值得欣慰的是,总有人正年轻、总有人在歌唱、总有人怀揣梦想、总有人奔赴向前、总有那些音乐陪伴着我们。感谢所有曾经在黑夜中给予我们孤独的灵魂以安抚的声音,在内心荒漠的世界里。"
|
||||
|
||||
return titleLabel
|
||||
}()
|
||||
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
func makeUI() {
|
||||
addSubview(titleImageView)
|
||||
addSubview(titleLabel)
|
||||
|
||||
}
|
||||
|
||||
override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
|
||||
titleImageView.snp.makeConstraints { make in
|
||||
make.left.equalTo(self)
|
||||
make.right.equalTo(self)
|
||||
make.top.equalTo(self)
|
||||
make.height.equalTo(100)//TODO
|
||||
}
|
||||
|
||||
titleLabel.snp.makeConstraints { make in
|
||||
make.left.equalTo(self).offset(25)
|
||||
make.right.equalTo(self).offset(-25)
|
||||
make.top.equalTo(titleImageView.snp.bottom).offset(10)//TODO
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,89 @@
|
||||
//
|
||||
// TimingViewController.swift
|
||||
// IndieMusic
|
||||
//
|
||||
// Created by WenLei on 2024/1/1.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class TimingViewController: ViewController {
|
||||
let titleLabel: UILabel = {
|
||||
let titleLabel = UILabel.init()
|
||||
titleLabel.font = UIFont.systemFont(ofSize: 15)
|
||||
|
||||
return titleLabel
|
||||
}()
|
||||
|
||||
let switchControl: UIControl = {
|
||||
let switchControl = UIControl.init()
|
||||
|
||||
return switchControl
|
||||
}()
|
||||
|
||||
|
||||
let collectionView: UICollectionView = {
|
||||
let collectionView = UICollectionView.init()
|
||||
|
||||
return collectionView
|
||||
}()
|
||||
|
||||
let button: UIButton = {
|
||||
let button = UIButton.init()
|
||||
button.setTitle("自定义", for: .normal)
|
||||
button.titleLabel?.font = UIFont.systemFont(ofSize: 15)
|
||||
|
||||
return button
|
||||
}()
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
// Do any additional setup after loading the view.
|
||||
}
|
||||
|
||||
|
||||
override func makeUI() {
|
||||
super.makeUI()
|
||||
|
||||
view.addSubview(titleLabel)
|
||||
view.addSubview(switchControl)
|
||||
view.addSubview(collectionView)
|
||||
view.addSubview(button)
|
||||
|
||||
}
|
||||
|
||||
|
||||
override func bindViewModel() {
|
||||
super.bindViewModel()
|
||||
|
||||
|
||||
}
|
||||
|
||||
override func viewDidLayoutSubviews() {
|
||||
super.viewDidLayoutSubviews()
|
||||
|
||||
switchControl.snp.makeConstraints { make in
|
||||
make.right.equalTo(view).offset(-18)
|
||||
make.top.equalTo(view).offset(19)
|
||||
}
|
||||
|
||||
titleLabel.snp.makeConstraints { make in
|
||||
make.left.equalTo(view).offset(18)
|
||||
make.top.equalTo(view).offset(24)
|
||||
}
|
||||
|
||||
collectionView.snp.makeConstraints { make in
|
||||
make.left.equalTo(view)
|
||||
make.right.equalTo(view)
|
||||
make.top.equalTo(view).offset(80)
|
||||
}
|
||||
|
||||
button.snp.makeConstraints { make in
|
||||
make.centerX.equalTo(view)
|
||||
make.top.equalTo(collectionView.snp.bottom).offset(30)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
Before Width: | Height: | Size: 477 B |
@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "mine_play_btn.svg",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 556 B |
@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "nav_back_btn.svg",
|
||||
"filename" : "search_icon.svg",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
After Width: | Height: | Size: 668 B |
@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "setting_arrow.svg",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 395 B |
Loading…
Reference in new issue