I am currently working on a project where I will be using an API to receive some suggestions, which I need to display as a tableview.
My goal is to add a 20-point margin between the cells in the tableview to make the suggestions more visually distinct and easier to read.
However, the methods I have tried so far to add this margin have not been successful.
I am looking for alternative solutions or suggestions on how to achieve the desired margin between the cells in the tableview.
import UIKit
import SnapKit
class SecondOnboardingPageVC: UIViewController, UITableViewDelegate, UITableViewDataSource {
var selectedIndexPath: IndexPath?
let tableData = ["Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eicia deserunt mollit anim id"]
private let tableView: UITableView = {
let tableView = UITableView()
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
tableView.backgroundColor = .bgColor
tableView.rowHeight = UITableView.automaticDimension
return tableView
}()
private let selectLabel: UILabel = {
let label = UILabel()
label.text = "Select An Idea"
label.font = UIFont(name: "Avenir", size: 30)
return label
}()
private let continueButton: UIButton = {
let button = UIButton()
button.setTitle("Continue", for: .normal)
button.backgroundColor = .black
button.layer.cornerRadius = 10
button.addTarget(self, action: #selector(nextVC), for: .touchUpInside)
return button
}()
override func viewDidLoad() {
super.viewDidLoad()
setupUI()
tableView.dataSource = self
tableView.delegate = self
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
tableView.separatorStyle = .none
tableView.separatorInset = UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 10)
self.navigationController?.isNavigationBarHidden = true
}
private func setupUI() {
view.backgroundColor = .bgColor
view.addSubview(selectLabel)
view.addSubview(continueButton)
view.addSubview(tableView)
selectLabel.snp.makeConstraints { make in
make.top.equalTo(view.safeAreaLayoutGuide).offset(0)
make.centerX.equalToSuperview()
}
continueButton.snp.makeConstraints { make in
make.bottom.equalToSuperview().inset(30)
make.left.equalToSuperview().offset(40)
make.right.equalToSuperview().inset(40)
make.height.equalTo(56)
}
tableView.snp.makeConstraints { make in
make.top.equalTo(selectLabel.snp.bottom).offset(20)
make.left.equalToSuperview().offset(20)
make.right.equalToSuperview().inset(20)
make.bottom.equalTo(-160)
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 7
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = tableData.first
cell.textLabel?.numberOfLines = 0
cell.textLabel?.lineBreakMode = .byWordWrapping
cell.backgroundColor = .viewColor
cell.layer.cornerRadius = 10
cell.contentView.layoutMargins = UIEdgeInsets(top: 10, left: 0, bottom: 10, right: 0)
cell.contentView.preservesSuperviewLayoutMargins = false
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 30
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) {
for visibleCell in tableView.visibleCells {
visibleCell.backgroundView = nil
}
let newView = UIView()
newView.backgroundColor = .orangeColor
cell.backgroundView = newView
selectedIndexPath = indexPath
tableView.deselectRow(at: indexPath, animated: true)
}
}
@objc private func nextVC() {
let controller = FifthOnboardingPageVC()
navigationController?.pushViewController(controller, animated: true)
}
}
I will be receiving some suggestions from an API, and I need to list these suggestions as a tableview. I want to add a 20 margin between the cells, but the methods I have tried are not working.
I have tried many methods, but none of them worked.
First... all of this:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = tableData.first
cell.textLabel?.numberOfLines = 0
cell.textLabel?.lineBreakMode = .byWordWrapping
cell.backgroundColor = .viewColor
cell.layer.cornerRadius = 10
cell.contentView.layoutMargins = UIEdgeInsets(top: 10, left: 0, bottom: 10, right: 0)
cell.contentView.preservesSuperviewLayoutMargins = false
return cell
}
is a bad idea.
What you want to do is create a custom cell, designed like this:
.contentView
, inset by 10-points on all 4 sides.The code you posted didn't include your .bgColor
or .orangeColor
definitions, so I'll use:
extension UIColor {
// very light gray
static let bgColor: UIColor = .init(white: 0.95, alpha: 1.0)
// orange
static let orangeColor: UIColor = .systemOrange
}
Quick example cell (since you're using SnapKit):
class ExampleCustomCell: UITableViewCell {
let theLabel = UILabel()
let roundedView = UIView()
let normalColor: UIColor = .bgColor
let selectedColor: UIColor = .orangeColor
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
private func commonInit() {
// properties
theLabel.numberOfLines = 0
roundedView.layer.cornerRadius = 10
roundedView.addSubview(theLabel)
contentView.addSubview(roundedView)
theLabel.snp.makeConstraints { make in
make.edges.equalToSuperview().inset(10.0)
}
roundedView.snp.makeConstraints { make in
make.edges.equalToSuperview().inset(10.0)
}
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
roundedView.backgroundColor = isSelected ? selectedColor : normalColor
}
}
if you notice, we're overriding setSelected()
so we can have the cell itself handle setting the color of the rounded view.
Now the cellForRowAt
function is much simpler:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "customCell", for: indexPath) as! ExampleCustomCell
let str: String = tableData.first ?? ""
cell.theLabel.text = "\(indexPath.row): \(str)"
// we don't want the cell to use its default selection style
cell.selectionStyle = .none
return cell
}
and, because we're letting the table view and cell classes handle the row selection, we don't need to do anything in didSelectRowAt
.
Here'a the complete SecondOnboardingPageVC
:
class SecondOnboardingPageVC: UIViewController, UITableViewDelegate, UITableViewDataSource {
var selectedIndexPath: IndexPath?
let tableData = ["Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eicia deserunt mollit anim id"]
private let tableView: UITableView = {
let tableView = UITableView()
tableView.backgroundColor = .bgColor
return tableView
}()
private let selectLabel: UILabel = {
let label = UILabel()
label.text = "Select An Idea"
label.font = UIFont(name: "Avenir", size: 30)
return label
}()
private lazy var continueButton: UIButton = {
let button = UIButton()
button.setTitle("Continue", for: .normal)
button.backgroundColor = .black
button.layer.cornerRadius = 10
button.addTarget(self, action: #selector(nextVC), for: .touchUpInside)
return button
}()
override func viewDidLoad() {
super.viewDidLoad()
setupUI()
tableView.dataSource = self
tableView.delegate = self
tableView.separatorStyle = .none
// register custom cell
tableView.register(ExampleCustomCell.self, forCellReuseIdentifier: "customCell")
self.navigationController?.isNavigationBarHidden = true
}
private func setupUI() {
view.backgroundColor = .systemBackground // .bgColor
view.addSubview(selectLabel)
view.addSubview(continueButton)
view.addSubview(tableView)
selectLabel.snp.makeConstraints { make in
make.top.equalTo(view.safeAreaLayoutGuide).offset(0)
make.centerX.equalToSuperview()
}
continueButton.snp.makeConstraints { make in
make.bottom.equalToSuperview().inset(30)
make.left.equalToSuperview().offset(40)
make.right.equalToSuperview().inset(40)
make.height.equalTo(56)
}
tableView.snp.makeConstraints { make in
make.top.equalTo(selectLabel.snp.bottom).offset(20)
make.left.equalToSuperview().offset(20)
make.right.equalToSuperview().inset(20)
make.bottom.equalTo(-160)
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// let's return 17 so we can confirm all is working when scrolling
return 17
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "customCell", for: indexPath) as! ExampleCustomCell
let str: String = tableData.first ?? ""
cell.theLabel.text = "\(indexPath.row): \(str)"
// we don't want the cell to use its default selection style
cell.selectionStyle = .none
return cell
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 30
}
@objc private func nextVC() {
// let controller = FifthOnboardingPageVC()
// navigationController?.pushViewController(controller, animated: true)
}
}
and it looks like this: