IOS 24 实现歌单详情(UITableView)列表
歌单详情完整效果
歌单详情歌单列表效果
歌单详情列表页整体效果稍微有点复杂,我们进行分部实现,先实现歌单详情里面的歌单列表,使用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 TangramKit
class SongItemCell: BaseTableViewCell {
override func initViews() {
super.initViews()
container.tg_space = 0
container.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_SMALL
container.addSubview(rightContainer)
//标题
rightContainer.addSubview(self.titleView)
//信息容器
let infoContainer = TGLinearLayout(.horz)
infoContainer.tg_width.equal(.fill)
infoContainer.tg_height.equal(.wrap)
infoContainer.tg_space = PADDING_SMALL
rightContainer.addSubview(infoContainer)
infoContainer.addSubview(self.downloadedView)
infoContainer.addSubview(self.infoView)
//更多按钮
let moreButton = ViewFactoryUtil.button(image:R.image.moreVerticalDot()!.withTintColor())
moreButton.tintColor = .black80
moreButton.tg_width.equal(50)
moreButton.tg_height.equal(50)
container.addSubview(moreButton)
}
func bind(_ data:Song) {
titleView.text = data.title
infoView.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 = 1
result.font = UIFont.systemFont(ofSize: TEXT_LARGE)
result.textColor = .black80
return result
}()
lazy var titleView: UILabel = {
let r = UILabel()
r.tg_width.equal(.fill)
r.tg_height.equal(.wrap)
r.numberOfLines = 1
r.font = UIFont.systemFont(ofSize: TEXT_LARGE)
r.textColor = .colorOnSurface
return r
}()
lazy var downloadedView: UIImageView = {
let r = UIImageView()
r.tg_width.equal(.wrap)
r.tg_height.equal(.wrap)
r.tg_visibility = .gone
r.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 = 1
r.font = UIFont.systemFont(ofSize: TEXT_MEDDLE)
r.textColor = .black80
return r
}()
}
//
// BaseTableViewCell.swift
// 通用TableViewCell
//
// Created by jin on 2024/8/27.
//
import UIKit
//提供类似Android中更高层级布局框架
import TangramKit
class 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 = .clear
contentView.backgroundColor = .clear
//去掉默认的选中颜色
selectionStyle = .none
//根容器
container = TGLinearLayout(getContainerOrientation())
container.tg_width.equal(.fill)
container.tg_height.equal(.wrap)
container.tg_space = PADDING_MEDDLE
contentView.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 HandyJSON
class 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? = nil
override 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 in
self?.show(data.data!)
}.disposed(by: rx.disposeBag)
}
func show(_ data: Sheet) {
self.data = data
datum = 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! Song
let cell = tableView.dequeueReusableCell(withIdentifier: Constant.CELL, for: indexPath) as! SongItemCell
cell.bind(data)
cell.indexView.text = "\(indexPath.row + 1)"
return cell
}
}
至此,实现了歌单详情里面的歌单列表。