歌单详情完整效果
歌单详情歌单列表效果
歌单详情列表页整体效果稍微有点复杂,我们进行分部实现,先实现歌单详情里面的歌单列表,使用UITableView来实现。UITableView的使用在之前的文章中多次使用,想来也比较熟悉了。不熟悉的可以看之前文章:IOS 21 发现界面(UITableView)单曲列表(UITableView)实现
歌单列表UITableView实现
1、创建SheetDetailController,继承自BaseTitleController
class SheetDetailController: BaseTitleController {
}
2、重新initViews(),初始化 UITableView
class SheetDetailController: BaseTitleController {override func initViews() {super.initViews()// 初始化TableView结构initTableViewSafeArea()}}
歌单列表Cell实现
实现流程:
1.创建Cell,及在使用UITableView的Controller控制器上注册Cell;
2.获取data列表数据,并调用UITableView的reloadData(),将数据更新到列表;
3.将data的Item数据绑定UITableView的每一个Cell。
1)创建和注册Cell
从效果图上面可以看出,歌单列表Cell由一个水平方向布局包含左中右三部分来实现。
自定义SongItemCell,继承自BaseTableViewCell,默认就是一个水平方向的TGLinearLayout。
//
// SongItemCell.swift
// 音乐cell
//
// Created by jin on 2024/9/12.
//import UIKit
import TangramKitclass SongItemCell: BaseTableViewCell {override func initViews() {super.initViews()container.tg_space = 0container.backgroundColor = .colorLightWhite//右侧有边距container.tg_padding = UIEdgeInsets(top: PADDING_SMALL, left: 0, bottom: 0, right: PADDING_SMALL)container.tg_gravity = TGGravity.vert.center//左侧容器let leftContainer = TGRelativeLayout()leftContainer.tg_width.equal(50)leftContainer.tg_height.equal(50)container.addSubview(leftContainer)//索引leftContainer.addSubview(self.indexView)//右侧容器let rightContainer = TGLinearLayout(.vert)rightContainer.tg_width.equal(.fill)rightContainer.tg_height.equal(.wrap)rightContainer.tg_space = PADDING_SMALLcontainer.addSubview(rightContainer)//标题rightContainer.addSubview(self.titleView)//信息容器let infoContainer = TGLinearLayout(.horz)infoContainer.tg_width.equal(.fill)infoContainer.tg_height.equal(.wrap)infoContainer.tg_space = PADDING_SMALLrightContainer.addSubview(infoContainer)infoContainer.addSubview(self.downloadedView)infoContainer.addSubview(self.infoView)//更多按钮let moreButton = ViewFactoryUtil.button(image:R.image.moreVerticalDot()!.withTintColor())moreButton.tintColor = .black80moreButton.tg_width.equal(50)moreButton.tg_height.equal(50)container.addSubview(moreButton)}func bind(_ data:Song) {titleView.text = data.titleinfoView.text = "\(data.singer.nickname!) - 这是专辑"}lazy var indexView: UILabel = {let result = UILabel()result.tg_width.equal(.wrap)result.tg_height.equal(.wrap)result.tg_centerX.equal(0)result.tg_centerY.equal(0)result.numberOfLines = 1result.font = UIFont.systemFont(ofSize: TEXT_LARGE)result.textColor = .black80return result}()lazy var titleView: UILabel = {let r = UILabel()r.tg_width.equal(.fill)r.tg_height.equal(.wrap)r.numberOfLines = 1r.font = UIFont.systemFont(ofSize: TEXT_LARGE)r.textColor = .colorOnSurfacereturn r}()lazy var downloadedView: UIImageView = {let r = UIImageView()r.tg_width.equal(.wrap)r.tg_height.equal(.wrap)r.tg_visibility = .goner.image = R.image.downloaded()return r}()lazy var infoView: UILabel = {let r = UILabel()r.tg_width.equal(.fill)r.tg_height.equal(.wrap)r.numberOfLines = 1r.font = UIFont.systemFont(ofSize: TEXT_MEDDLE)r.textColor = .black80return r}()
}
//
// BaseTableViewCell.swift
// 通用TableViewCell
//
// Created by jin on 2024/8/27.
//import UIKit//提供类似Android中更高层级布局框架
import TangramKitclass BaseTableViewCell:UITableViewCell{//对于需要动态评估高度的UITableViewCell来说可以把布局视图暴露出来。用于高度评估和边界线处理。以及事件处理的设置。var container:TGBaseLayout!override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {super.init(style: style, reuseIdentifier: reuseIdentifier)innerInit()}required init?(coder: NSCoder) {super.init(coder: coder)innerInit()}func innerInit() {initViews()initDatum()initListeners()}/// 找控件func initViews() {//背景透明backgroundColor = .clearcontentView.backgroundColor = .clear//去掉默认的选中颜色selectionStyle = .none//根容器container = TGLinearLayout(getContainerOrientation())container.tg_width.equal(.fill)container.tg_height.equal(.wrap)container.tg_space = PADDING_MEDDLEcontentView.addSubview(container)}func initDatum() {}func initListeners() {}/// 获取根容器布局方向func getContainerOrientation() -> TGOrientation {return .horz}/// 使用TangramKit后,让item自动计算高度,要重写该方法/// - Parameters:/// - targetSize: <#targetSize description#>/// - horizontalFittingPriority: <#horizontalFittingPriority description#>/// - verticalFittingPriority: <#verticalFittingPriority description#>/// - Returns: <#description#>override func systemLayoutSizeFitting(_ targetSize: CGSize, withHorizontalFittingPriority horizontalFittingPriority: UILayoutPriority, verticalFittingPriority: UILayoutPriority) -> CGSize {return self.container.systemLayoutSizeFitting(targetSize)}
}
在SheetDetailController控制器,注册SongItemCell
class SheetDetailController: BaseTitleController {override func initViews() {super.initViews()// 初始化TableView结构initTableViewSafeArea()// 注册单曲tableView.register(SongItemCell.self, forCellReuseIdentifier: Constant.CELL)}}
2)获取data列表数据
定义列表数据模型Song
//
// Song.swift
// 单曲模型
//
// Created by jin on 2024/9/2.
//import Foundation//导入JSON解析框架
import HandyJSONclass Song : BaseCommon{/// 标题var title:String!/// 封面var icon:String?/// 音乐地址var uri:String!/// 点击数var clicksCount:Int = 0/// 评论数var commentsCount:Int = 0/// 创建该音乐的人var user:User!/// 歌手var singer:User!/// 歌词类型var style:Int = 0/*** 歌词内容*/var lyric:String? = niloverride func mapping(mapper: HelpingMapper) {super.mapping(mapper: mapper)mapper <<< self.clicksCount <-- "clicks_count"mapper <<< self.commentsCount <-- "comments_count"}
}
请求歌单详情接口获取歌单详情里的歌曲列表数据,更新tableView.reloadData()
class SheetDetailController: BaseTitleController {var id: String!var data: Sheet!override func initViews() {super.initViews()// 初始化TableView结构initTableViewSafeArea()title = R.string.localizable.sheet()// 注册单曲tableView.register(SongItemCell.self, forCellReuseIdentifier: Constant.CELL)}override func initDatum() {super.initDatum()loadData()}func loadData() {DefaultRepository.shared.sheetDetail(id).subscribeSuccess { [weak self] data inself?.show(data.data!)}.disposed(by: rx.disposeBag)}func show(_ data: Sheet) {self.data = datadatum = data.songs ?? []tableView.reloadData()}
}
3)Item数据绑定Cell
SheetDetailController控制器重写父类的扩展 cellForRowAt方法,创建对应的Cell,并将Item数据绑定到Cell。
extension SheetDetailController {override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {let data = datum[indexPath.row] as! Songlet cell = tableView.dequeueReusableCell(withIdentifier: Constant.CELL, for: indexPath) as! SongItemCellcell.bind(data)cell.indexView.text = "\(indexPath.row + 1)"return cell}
}
至此,实现了歌单详情里面的歌单列表。