Add Text Label and Button to Dynamic Tableview Cell Programmatically with Swift

Add Text Label and Button to dynamic tableview cell programmatically with Swift

You can implement like this

let titleArray = ["a", "b", "c"]

func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 50
}

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
//return no.of cell do you want
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cellHeight = tableView(self.tableView, heightForRowAtIndexPath: NSIndexPath(forRow: indexPath.row, inSection: indexPath.section))
var cell = CustomCell(frame: CGRectMake(0, 0, self.view.frame.width, cellHeight), title: titleArray[indexPath.row])
cell.cellLabel.text = //labelText
cell.cellButton.addTarget(self, action: "buttonPressed:", forControlEvents: UIControlEvents.TouchUpInside)

return cell
}

class CustomCell: UITableViewCell {
var cellButton: UIButton!
var cellLabel: UILabel!

init(frame: CGRect, title: String) {
super.init(style: UITableViewCellStyle.Default, reuseIdentifier: "cell")

cellLabel= UILabel(frame: CGRectMake(self.frame.width - 100, 10, 100.0, 40))
cellLabel.textColor = UIColor.blackColor()
cellLabel.font = //set font here

cellButton = UIButton(frame: CGRectMake(5, 5, 50, 30))
cellButton.setTitle(title, forState: UIControlState.Normal)

addSubview(cellLabel)
addSubview(cellButton)
}

required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
}

Add button to uitableview cell programmatically

Create a subclass of UITableViewcell -

class MyCell: UITableViewCell {

var buttonTapCallback: () -> () = { }

let button: UIButton = {
let btn = UIButton()
btn.setTitle("Button", for: .normal)
btn.backgroundColor = .systemPink
btn.titleLabel?.font = UIFont.systemFont(ofSize: 14)
return btn
}()

let label: UILabel = {
let lbl = UILabel()
lbl.font = UIFont.systemFont(ofSize: 16)
lbl.textColor = .systemPink
return lbl
}()

@objc func didTapButton() {
buttonTapCallback()
}

override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
//Add button
contentView.addSubview(button)
button.addTarget(self, action: #selector(didTapButton), for: .touchUpInside)

//Set constraints as per your requirements
button.translatesAutoresizingMaskIntoConstraints = false
button.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20).isActive = true
button.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 10).isActive = true
button.widthAnchor.constraint(equalToConstant: 100).isActive = true
button.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -10).isActive = true

//Add label
contentView.addSubview(label)
//Set constraints as per your requirements
label.translatesAutoresizingMaskIntoConstraints = false
label.leadingAnchor.constraint(equalTo: button.trailingAnchor, constant: 20).isActive = true
label.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 10).isActive = true
label.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -10).isActive = true
label.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -10).isActive = true
}

required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

}

Now in your view controller register this cell -

myTableView.register(MyCell.self, forCellReuseIdentifier: "MyCell")

Now load this cell using cellForRowAt method -

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MyCell", for: indexPath) as! MyCell
cell.label.text = ""
cell.buttonTapCallback = {
cell.label.text = "Hi"
}
return cell
}

Add a Text Field to A UITableViewCell in swift

The text field frame should be with in cell size and check your datasource also

use

cell.contentView.addSubview(tf)

instead of cell.addSubview(tf)

The default height is 44, if you want more then implement respective delegate

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 200
}

add code at last

class customCell: UITableViewCell {

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
}

}

Then change your code:

let cell: customCell = self.extraGuestsTable.dequeueReusableCell(withIdentifier: cellReuseIdentifier) as customCell!

let tf = UITextField(frame: CGRect(x: 20, y: 0, width: 300, height: 20))
tf.placeholder = "Enter text here"
tf.font = UIFont.systemFont(ofSize: 15)

//cell.contentView.addSubview(tf)
cell.addSubview(tf)

return cell

Dynamically adding a custom UITableViewCell

Firstly, you have to subclass UITableViewCell for a UITableViewCell with UITextField. Of course you can add the UITextField inside cellForRowAt delegate function but I prefer to do it with a custom UITableViewCell.

class UITableViewCellWithTextField: UITableViewCell {

var textField: UITextField!

override init(style: UITableViewCellStyle, reuseIdentifier: String?) {

super.init(style: style, reuseIdentifier: reuseIdentifier)
setup()
}

func setup() {

let textField = UITextField(frame: self.contentView.frame)
self.contentView.addSubview(self.textField)
}
}

Next, you have to register this custom UITableViewCell into your UITableView. Add this to your existing UITableViewCell registration line of code.

jobTableView.register(UITableViewCell.self, forCellReuseIdentifier: tableCell)
jobTableView.register(UITableViewCellWithTextField.self, forCellReuseIdentifier: "TextFieldCell")

The next step is to declare a variable to indicate that the user has initiated the add new job function.

public class MiddlePartCell: BaseCell, UITableViewDelegate, UITableViewDataSource {

var isHandlingAddJob = false

...
}

Then in your handleAddJob function

func handleAddJob(){

self.isHandlingAddJob = true
datas.insert("new data", at: 0)
jobTableView.beginUpdates()
jobTableView.insertRows(at: [IndexPath.init(row: 0, section: 0)], with: .automatic)
jobTableView.endUpdates()
}

Lastly is to let the UITableView know that the incoming new cell to handle adding of a new job, and should use the custom text field cell.

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

if indexPath.row == 0 && self.isHandlingAddJob {

// Handling new job cell
let cell = tableView.dequeueReusableCell(withIdentifier: "TextFieldCell", for: indexPath) as! UITableViewCellWithTextField
return cell
}

let cell = tableView.dequeueReusableCell(withIdentifier: tableCell, for: indexPath)

cell.textLabel?.text = datas[indexPath.item]
return cell
}

P.S. Hope I'm understanding your question correctly lol.

To persist the data of the text field in the custom table view cell, you have to use the delegate pattern. Firstly, you have to either conform your custom table view cell or MiddlePartCell class to UITextFieldDelegate. I will be going for the latter.

class MiddlePartCell: BaseCell, UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate {

...
}

Then in your cellForRowAt function, you set your custom cell's text field delegate to your MiddlePartCell.

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

if indexPath.row == 0 && self.isHandlingAddJob {

// Handling new job cell
let cell = tableView.dequeueReusableCell(withIdentifier: "TextFieldCell", for: indexPath) as! UITableViewCellWithTextField
cell.returnKeyType = .Done
cell.textField.delegate = self
return cell
}

...
}

Lastly, use the UITextFieldDelegate function. When the use click done on the keyboard, your cell will be reloaded to be a normal UITableViewCell without UITextField.

func textFieldShouldReturn(textField: UITextField) -> Bool {

self.isHandlingAddJob = false
self.datas.first! = textField.text!
self.jobTableView.reloadRowsAtIndexPaths([NSIndexPath(forRow: 0, inSection: 0)], withRowAnimation: .Automatic)
return true
}

Dynamically change cell height according to label text

The bottom anchor needs to be set:

cevapLabel.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true

Send label text data with segue in TableView in Swift

I've finally done that using this example: Passing data between two UIViewControllers using Swift and Storyboard

It's make a lot easier and helps me finally get it to work!

Thanks!

Dynamic Custom TableView Cell swift

A dynamic table view can be accomplished with an appropriate data model.

For example use an enum for the kind and a struct with a member to indicate the kind

enum CellKind {
case image, label, picker
}

struct Model {
let kind : CellKind

// other struct members
}

How many cells are displayed depends on the items in the data source array

var items = [Model]()

In numberOfRows return the number of items

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}

In cellForRow display the cells depending on the kind rather than on the index path

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let item = items[indexPath.row]
switch item.kind {
case .image:
let cell = tableView.dequeueReusableCell(withIdentifier: "imageCell") as! ImageCell
// Set up cell.image
return cell
case .label:
let cell = tableView.dequeueReusableCell(withIdentifier: "labelCell") as! LabelCell
// Set up cell.label
return cell
case .picker:
let cell = tableView.dequeueReusableCell(withIdentifier: "pickerCell") as! PickerCell
// Set up cell.picker
return cell
}
}

Show labels with dynamic sizes like a table without overlapping

Each of your textField should have the parameter "line" as 0 as follow:
Demo

or programmatically

@IBOutlet weak var text: UITextField!
[...]
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
text.numberOfLines = 0
}

This allow your textField to use an unlimited number of lines.
After that you have to play with autolayout to set constraint between your field.



Related Topics



Leave a reply



Submit