foldable UI Table view cell
import UIKit
class CollapsableViewModel {
let label: String
let image: UIImage?
let children: [CollapsableViewModel]
var isCollapsed: Bool
var needsSeparator: Bool = true
init(label: String, image: UIImage? = nil, children: [CollapsableViewModel] = [], isCollapsed: Bool = true) {
self.label = label
self.image = image
self.children = children
self.isCollapsed = isCollapsed
for child in self.children {
child.needsSeparator = false
}
self.children.last?.needsSeparator = true
}
}
class CollapsableTableViewController: UITableViewController {
let data = [
CollapsableViewModel(label: "Account", image: nil, children: [
CollapsableViewModel(label: "Profile"),
CollapsableViewModel(label: "Activate account"),
CollapsableViewModel(label: "Change password")]),
CollapsableViewModel(label: "Group"),
CollapsableViewModel(label: "Events", image: nil, children: [
CollapsableViewModel(label: "Nearby"),
CollapsableViewModel(label: "Global"),
]),
CollapsableViewModel(label: "Deals"),
]
var displayedRows: [CollapsableViewModel] = []
override func viewDidLoad() {
super.viewDidLoad()
displayedRows = data
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return displayedRows.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CellIdentifier") ?? UITableViewCell()
let viewModel = displayedRows[indexPath.row]
cell.textLabel!.text = viewModel.label
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: false)
let viewModel = displayedRows[indexPath.row]
if viewModel.children.count > 0 {
let range = indexPath.row+1...indexPath.row+viewModel.children.count
let indexPaths = range.map { IndexPath(row: $0, section: indexPath.section) }
tableView.beginUpdates()
if viewModel.isCollapsed {
displayedRows.insert(contentsOf: viewModel.children, at: indexPath.row + 1)
tableView.insertRows(at: indexPaths, with: .automatic)
} else {
displayedRows.removeSubrange(range)
tableView.deleteRows(at: indexPaths, with: .automatic)
}
tableView.endUpdates()
}
viewModel.isCollapsed = !viewModel.isCollapsed
}
}
//
// RingtoneCell.swift
// Phone-Color-Screen
//
// Created by Kerim Deveci on 13.11.2019.
// Copyright © 2019 Kerim Deveci. All rights reserved.
//
import UIKit
class RingtoneCell: UITableViewCell {
@IBOutlet weak var ringtoneImageHolder: UIImageView!
@IBOutlet weak var toneText: UILabel!
let separator = UIView(frame: .zero)
func configure(withViewModel viewModel: CollapsableViewModel) {
if(viewModel.needsSeparator) {
separator.backgroundColor = .gray
contentView.addSubview(separator)
} else {
separator.removeFromSuperview()
}
}
override func layoutSubviews() {
super.layoutSubviews()
let separatorHeight = 1 / UIScreen.main.scale
separator.frame = CGRect(x: separatorInset.left,
y: contentView.bounds.height - separatorHeight,
width: contentView.bounds.width-separatorInset.left-separatorInset.right,
height: separatorHeight)
}
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
}
}
//
// RingtoneViewControllerTableViewController.swift
// Phone-Color-Screen
//
// Created by Kerim Deveci on 13.11.2019.
// Copyright © 2019 Kerim Deveci. All rights reserved.
//
import UIKit
class RingtoneViewControllerTableViewController: UITableViewController {
let data = [
CollapsableViewModel(label: "Account", image: nil, children: [
CollapsableViewModel(label: "Profile"),
CollapsableViewModel(label: "Activate account"),
CollapsableViewModel(label: "Change password")]),
CollapsableViewModel(label: "Group"),
CollapsableViewModel(label: "Events", image: nil, children: [
CollapsableViewModel(label: "Nearby"),
CollapsableViewModel(label: "Global"),
]),
CollapsableViewModel(label: "Deals"),
]
var displayedRows: [CollapsableViewModel] = []
let ringtones = ["ringtoine1" , "ringtoine2" , "ringtoine3"]
let separator = UIView(frame: .zero)
override func viewDidLoad() {
super.viewDidLoad()
displayedRows = data
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return displayedRows.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ringtoneCell", for: indexPath) as! RingtoneCell
let viewModel = displayedRows[indexPath.row]
cell.configure(withViewModel: displayedRows[indexPath.row])
cell.toneText.text = viewModel.label
print("YENIDEN YUKLENDI")
return cell
}
//MARK: Animation function
func startAnimation(indexPath : IndexPath) {
UIView.animate(withDuration: 0.7, delay: 1.0, options: .curveEaseOut, animations: {
self.tableView.rowHeight = 150.0
}, completion: { finished in
print("Row heights changed!")
})
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: false)
let viewModel = displayedRows[indexPath.row]
if viewModel.children.count > 0 {
let range = indexPath.row+1...indexPath.row+viewModel.children.count
let indexPaths = range.map { IndexPath(row: $0, section: indexPath.section) }
tableView.beginUpdates()
if viewModel.isCollapsed {
displayedRows.insert(contentsOf: viewModel.children, at: indexPath.row + 1)
tableView.cellForRow(at: indexPath)
tableView.insertRows(at: indexPaths, with: .automatic)
} else {
displayedRows.removeSubrange(range)
tableView.deleteRows(at: indexPaths, with: .automatic)
}
tableView.endUpdates()
}
viewModel.isCollapsed = !viewModel.isCollapsed
}
}