如何解决如何快速制作嵌套的可折叠 tableview?
我有一些设计,父母和他们的孩子都可以折叠。我已经使用表格视图实现了父级,但对于它的子级,我将如何实现其扩展单元格。我应该加载另一个自定义视图单元格还是应该更改当前单元格,我不知道。如果有人有任何想法,请帮我解决这个问题。
// Model Class
class WorkoutTemplate {
var folderName:String
var workoutType: [WorkoutType]
init(folderName: String,workoutType: [WorkoutType]) {
self.folderName = folderName
self.workoutType = workoutType
}
}
class WorkoutType {
var workoutCategoryName: String // Basic Full Body
var totalWorkouts : [Workout]
init(workoutCategoryName: String,totalWorkouts: [Workout] ) {
self.workoutCategoryName = workoutCategoryName
self.totalWorkouts = totalWorkouts
}
}
class Workout{
var workoutName: String
var reps:Int = 0
var sets:Int = 0
init(workoutName: String,reps: Int,sets: Int) {
self.workoutName = workoutName
self.reps = reps
self.sets = sets
}
}
// Controller class
import UIKit
class AddWorkoutViewController: UIViewController {
@IBOutlet weak var tableView: UITableView?
var data = [WorkoutTemplate]()
var sectionIsExpanded = [false,false,false]
private let headerIdentifier = "WorkoutTemplateHeaderCell"
private let cellIdentifier = "AddWorkoutCategoryCell"
override func viewDidLoad() {
super.viewDidLoad()
let workout = Workout(workoutName: "Squat",reps: 10,sets: 9)
let workout2 = Workout(workoutName: "Bench press",reps: 6,sets: 7)
let workout3 = Workout(workoutName: "Dunmbell lunge",reps: 12,sets: 78)
let workoutType = WorkoutType(workoutCategoryName: "Basic full body",totalWorkouts: [workout,workout2,workout3])
let workoutTemplate = WorkoutTemplate(folderName: "My Workout Template",workoutType: [workoutType,workoutType])
data.append(workoutTemplate)
data.append(workoutTemplate)
data.append(workoutTemplate)
tableView?.reloadData()
}
}
extension AddWorkoutViewController: UITableViewDataSource,UITableViewDelegate {
func numberOfSections(in tableView: UITableView) -> Int {
return data.count
}
func tableView(_ tableView: UITableView,numberOfRowsInSection section: Int) -> Int {
// First will always be header
let sectiondata = data[section]
return sectionIsExpanded[section] ? (sectiondata.workoutType.count + 1) : 1
}
func tableView(_ tableView: UITableView,cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 {
let headerCell = tableView.dequeueReusableCell(withIdentifier: headerIdentifier,for: indexPath) as! AddWorkoutTemplateHeaderTableViewCell
let sectionData = data[indexPath.section]
headerCell.headingLabel?.text = sectionData.folderName
if sectionIsExpanded[indexPath.section] {
headerCell.setExpanded()
} else {
headerCell.setCollapsed()
}
return headerCell
} else {
let catCell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier,for: indexPath) as! AddWorkoutCategoryTableViewCell
let sectionData = data[indexPath.section]
let rowData = sectionData.workoutType[(indexPath.row - 1)]
catCell.headingLabel?.text = rowData.workoutCategoryName
var subheadings = ""
for item in rowData.totalWorkouts {
subheadings = subheadings + item.workoutName + ","
}
catCell.mutiWorkoutLabel?.text = subheadings
return catCell
}
}
func tableView(_ tableView: UITableView,didSelectRowAt indexPath: IndexPath) {
// Expand/hide the section if tapped its header
if indexPath.row == 0 {
sectionIsExpanded[indexPath.section] = !sectionIsExpanded[indexPath.section]
tableView.reloadSections([indexPath.section],with: .automatic)
}
}
}
解决方法
因为您有“通用”元素——人字形图像、标题、{{1}} 和“开始锻炼”按钮,我建议使用单个单元格类而不是单独的类。
将“中心”元素放在垂直堆栈视图中:
当你想显示单元格“折叠”集时:
...
并显示单元格“扩展”:
collapsedView.isHidden = false
expandedView.isHidden = true
堆栈视图会自动删除隐藏视图占用的空间,但将其保留为视图层次结构的一部分,因此您不必添加/删除子视图和激活/停用约束。
这是一个示例布局:
以及它在运行时的表现:
,//
// AddWorkoutViewController.swift
//
// Created by developer on 6/1/21.
//
import UIKit
class AddWorkoutViewController: UIViewController,passIndexData {
@IBOutlet weak var tableView: UITableView?
var data = [WorkoutTemplate]()
var sectionIsExpanded = [false,false,false]
private let headerIdentifier = "WorkoutTemplateHeaderCell"
private let cellIdentifier = "AddWorkoutCategoryCell"
override func viewDidLoad() {
super.viewDidLoad()
let workout = Workout(workoutName: "Squat",reps: 10,sets: 9)
let workout2 = Workout(workoutName: "Bench press",reps: 6,sets: 7)
let workout3 = Workout(workoutName: "Dunmbell lunge",reps: 12,sets: 78)
let workoutType = WorkoutType(workoutCategoryName: "Basic full body",totalWorkouts: [workout,workout2,workout3])
let workoutType2 = WorkoutType(workoutCategoryName: "Basic full body",workout3])
let workoutTemplate = WorkoutTemplate(folderName: "My Workout Template",workoutType: [workoutType,workoutType2])
let workoutType3 = WorkoutType(workoutCategoryName: "Basic full body",workout3])
let workoutType4 = WorkoutType(workoutCategoryName: "Basic full body",workout3])
let workoutTemplate2 = WorkoutTemplate(folderName: "My Workout Template",workoutType: [workoutType3,workoutType4])
data.append(workoutTemplate)
data.append(workoutTemplate2)
//data.append(workoutTemplate)
tableView?.reloadData()
}
func stringToAtributedString(string:String,fontName: String,alpha: CGFloat = 1)-> NSMutableAttributedString {
if let safeFont = UIFont(name: fontName,size: 14) {
let color = UIColor(named: "textBlack")
color?.withAlphaComponent(alpha)
let attribute = [NSAttributedString.Key.font: safeFont,NSAttributedString.Key.foregroundColor: color]
let attributedString = NSMutableAttributedString(string: string,attributes: attribute)
return attributedString
}
return NSMutableAttributedString()
}
}
extension AddWorkoutViewController: UITableViewDataSource,UITableViewDelegate {
func numberOfSections(in tableView: UITableView) -> Int {
return data.count
}
func tableView(_ tableView: UITableView,heightForFooterInSection section: Int) -> CGFloat {
return 1.2 //.leastNormalMagnitude // 0 may not work
}
func tableView(_ tableView: UITableView,numberOfRowsInSection section: Int) -> Int {
// First will always be header
let sectiondata = data[section]
return sectionIsExpanded[section] ? (sectiondata.workoutType.count + 1) : 1
}
func tableView(_ tableView: UITableView,cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 {
// header cell
let headerCell = tableView.dequeueReusableCell(withIdentifier: headerIdentifier,for: indexPath) as! AddWorkoutTemplateHeaderTableViewCell
let sectionData = data[indexPath.section]
headerCell.headingLabel?.text = sectionData.folderName
if sectionIsExpanded[indexPath.section] {
headerCell.setExpanded()
} else {
headerCell.setCollapsed()
}
headerCell.selectionStyle = .none
return headerCell
} else {
// workout category cell
let catCell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier,for: indexPath) as! AddWorkoutCategoryTableViewCell
let sectionData = data[indexPath.section]
let rowData = sectionData.workoutType[(indexPath.row - 1)]
catCell.headingLabel?.text = rowData.workoutCategoryName
var subHeadings = ""
let workoutNames = UILabel()
workoutNames.numberOfLines = 0
workoutNames.alpha = 0.7
for item in rowData.totalWorkouts {
subHeadings = subHeadings + item.workoutName + ","
}
workoutNames.attributedText = stringToAtributedString(string: subHeadings,fontName: "Poppins-Regular")
if catCell.workoutSetContainer != nil {
for view in catCell.workoutSetContainer!.subviews.enumerated() {
view.element.removeFromSuperview()
}
}
print("section: \(indexPath.section) row: \(indexPath.row) rowCollapse: \(rowData.isExpanded)")
if rowData.isExpanded {
catCell.setCollapsed()
for item in rowData.totalWorkouts.enumerated() {
let workoutSetcell = tableView.dequeueReusableCell(withIdentifier: "WorkoutSetCell") as! AddworkoutWOrkoutSetTableViewCell
workoutSetcell.workoutNameLabel?.text = item.element.workoutName
//workoutSetcell.workoutSetLabel?.text = "\(item.element.reps)" + " " + "\(item.element.sets)"
let repsCount = stringToAtributedString(string: "\(item.element.reps)",fontName: "Poppins-Bold")
let repsString = stringToAtributedString(string: " reps",fontName: "Poppins-Regular",alpha: 0.7)
repsCount.append(repsString)
workoutSetcell.workoutSetLabel?.attributedText = repsCount
catCell.workoutSetContainer?.addArrangedSubview(workoutSetcell)
}
} else {
catCell.setExpanded()
catCell.workoutSetContainer?.addArrangedSubview(workoutNames)
}
catCell.cellDelegate = self
catCell.cellIndexPath = indexPath
catCell.selectionStyle = .none
return catCell
}
}
func tableView(_ tableView: UITableView,didSelectRowAt indexPath: IndexPath) {
// Expand/hide the section if tapped its header
if indexPath.row == 0 {
sectionIsExpanded[indexPath.section] = !sectionIsExpanded[indexPath.section]
tableView.reloadSections([indexPath.section],with: .automatic)
}
}
}
extension AddWorkoutViewController:expandCell {
func passIndexValues(indexPath: IndexPath?) {
if indexPath != nil {
let sectionData = data[indexPath!.section]
let rowData = sectionData.workoutType[indexPath!.row - 1]
rowData.isExpanded = !rowData.isExpanded
sectionData.workoutType[indexPath!.row - 1] = rowData
data[indexPath!.section] = sectionData
tableView?.reloadRows(at: [indexPath!],with: .automatic)
//tableView?.reloadData()
}
//print("index path \(indexPath?.section)")
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。