I'm struggling to load a cell in cellForRowAtIndexPath in such way so that I can give a custom offset to one cell only - in my case only to Cell 1, Section 1. I'd like to give a custom offset to the cell, as the same cell (xib) is used in other parts of the project where it extends to the edges of the table without any offset. All my cells are designed as *.xib files. I'm willing to set something in awakeFromNib() or other methods, if there's the need for that.
Is there any way to set the cell offset, inset, margins, padding (not sure about the correct wording) at time of the creation or at time of loading of the cell?
I've tried to set margins in this way, but it doesn't work:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if (indexPath.section == 0) && (indexPath.row) == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! MyCell
cell.layoutMargins = UIEdgeInsetsMake(10, 10, 10, 10)
return cell
}
} else {
// Load other cells
}
I think you're close with your cellForRowAtIndexPath implementation. Try applying the margins to the cell's contentView (the superview for your cell's content, and a subview of the cell). You may also have to set the cell's background colour to clear (the contentView will still be white).
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if (indexPath.section == 0) && (indexPath.row) == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! MyCell
cell.contentView.layoutMargins = UIEdgeInsetsMake(10, 10, 10, 10)
return cell
}
} else {
// Load other cells
}
Related
I have a tableview in my storyboard where the prototype cell has a disclosure indicator by default.
When I populate my table I want to remove the indicator only from the last cell AND center a spinner on it.
I'm doing it like this:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CharacterCell", for: indexPath) as! CharacterCell
if indexPath.row == charactersViewModel.charactersCount - 1 {
cell.accessoryType = .none
cell.accessoryView = .none
// Spinner
let spinner = UIActivityIndicatorView(style: .large)
spinner.color = .white
spinner.center = cell.contentView.center
cell.contentView.addSubview(spinner)
spinner.startAnimating()
}
return cell
}
The problem is that the spinner is offcenter, a little bit to the left, just like if the accessory is still there, but hidden.
I feel maybe I'm missing the lifecycle of a table cell, maybe it's getting the center value of the content view when the accessory is still there, so when it's removed it is offcenter?
I tried on willDisplay as well but the same thing happens.
Any tips on this?
As #Paulw11 mentioned, I used a second subclass and created another cell prototype in my tableview.
Then when the last position at the table is reached, we can use the second prototype on cellForRowAt.
Here how it is:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row >= charactersViewModel.charactersCount - 1 {
reloadRows(indexPath: indexPath)
let cell = tableView.dequeueReusableCell(withIdentifier: "LoadingCharacterCell", for: indexPath) as! LoadingCharacterCell
cell.startSpinner()
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "CharacterCell", for: indexPath) as! CharacterCell
cell.configureCell(charactersViewModel: charactersViewModel, cell: cell, index: indexPath.row)
return cell
}
}
private func reloadRows(indexPath: IndexPath) {
var indexPathList = [IndexPath]()
indexPathList.append(indexPath)
charactersTableView.reloadRows(at: indexPathList, with: .automatic)
}
And with the reloadRows function, the last cell is updated and removed when the table receives more data.
I set my tableview constraints pinch to left and right at zero in the storyboard.
But depends on my indexPath.row, I need to set new constraints (inset & width). I've tried this without success.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
switch dataType! {
case .mycase:
let cell = tableView.dequeueReusableCell(withIdentifier: "NoBrandDeviceFoundTableViewCell", for: indexPath) as! NoBrandDeviceFoundTableViewCell
tableView.isScrollEnabled = false
var frame = tableView.frame
frame.size.width = 343
cell.frame = frame
tableView.contentInset = UIEdgeInsets(top: 0, left: 16, bottom: 0, right: 16)
return cell
}
}
The frame of the cell won't be changed it's been set equal to the width of the table , you can hook the leading/left & trailing/right constraints of the items you want to shift and change their constant's value according to that indexPath in cellForRowAt
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "NoBrandDeviceFoundTableViewCell", for: indexPath) as! NoBrandDeviceFoundTableViewCell
if indexPath.row == <#someValue#> {
cell.lblLeadingCon.constant = <#someValue#>
}
else {
cell.lblLeadingCon.constant = 0
}
return cell
}
you need to take cell leading constanint - nslcLeadingCell
you need to take cell trailing constatint - nslcTrailningCell
based on indexpathrow contion match you need make condition
if indexpath.row == 5
cell.nslcLeadingCell.constant = 10
cell.nslcTrailningCell.constanct = 15
I have UIViewController with UITableView.
In the table I have two different cells and use UITableViewAutomaticDimension.
First and second cell - one style (no space between cells)
Second and third cell - different styles (have some space as in image)
How can I remove this space?
P.S. Xib of cells are good.
You can subclass UITableViewCell and add something like:
// Inside UITableViewCell subclass
override func layoutSubviews() {
super.layoutSubviews()
let frame = contentView.frame
let frameRect = UIEdgeInsetsInsetRect(frame, UIEdgeInsetsMake(5, 5, 5, 5))
contentView.frame = frameRect
}
Then based on the indexPath.row you can chose which tableView cell you want to use, like :
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell:UITableViewCell = self.tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier) as UITableViewCell!
//First cell
if(indexPath.row == 0) {
// Would need to return appropriate cell here
}
if(indexPath.row == 1) {
// Would need to return appropriate cell here
}
return cell
}
Hope this helps.
I'm trying to build two (or more) custom cells into table View and without custom classes for each one, I'm using storyboard to cell prototyping and tableView.dequeueReusableCell(withIdentifier: "customCellName", for: indexPath) to create different cell from cellForRowAt method.
I need cell type 1 with different height than cell type 2 but if a try to use func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat the cell type 2 is not displayed correctly.
I try to build a "dummy project" to understand the right way, here my code:
var cell = self.tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
let value = dataArray[indexPath.row]
if (value == "second") || (value == "Hawaii") {
cell = self.tableView.dequeueReusableCell(withIdentifier: "cellTwo", for: indexPath)
}
let lbl = cell.viewWithTag(100) as! UILabel
lbl.text = dataArray[indexPath.row]
return cell
In ViewDidLoad:
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.dataSource = self
self.tableView.delegate = self
self.tableView.estimatedRowHeight = 200
}
This is the result:
Every cell with the same size, is not working for me.
If you want to create a custom cell appearance, you will have to create a subclass of UITableViewCell - there are some great tutorials on how to do that.
You then have to register your custom cell, so that your UITableView knows about it. See register(_:forCellReuseIdentifier:) method.
In your tableView(_:heightForRowAt:) you can do write the following code in order to figure out the height of particular cell:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
let value = dataArray[indexPath.row]
if (value == "second") || (value == "Hawaii") {
return 180.0
} else {
return 40.0
}
}
No article explains it clearly regarding my query, I have three cells in a static table and I want to hide second cell when users taps on first cell. Any kind of help is appreciated.
Although you cannot stop the static table from trying to show your cells, you can set their height to zero, making them effectively invisible:
Add this method to your table view controller delegate class:
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
let cell = super.tableView(tableView, cellForRowAtIndexPath: indexPath)
return cell == myHiddenCell ? 0 : super.tableView(tableView, heightForRowAtIndexPath:indexPath)
}
In the didSelectCellAtIndexPath method, you can set the height to 0 to hide it :
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if indexPath.row == 0 {
let indexPath = NSIndexPath(forItem: 1, inSection : 0)
let secondCell = tableview.cellForRowAtIndexPath(indexPath)
secondCell.frame.size.height = 0;
self.view.layoutSubviews()
}
}
If you want an animation, just put self.view.layoutSubviews() in an UIView animation method UIView.animateWithDuration... etc
For me, setting the height to 0 for some cells and another height for other cells wasn't an option, as all my cells have different height.
I created another cell in Storyboard, and set row height of 0 (in size inspector). Then in the code, I show the cell with height = 0 if I want to hide it, if not, I show the other cell:
if (hideCell) {
let hiddenCell = tableView.dequeueReusableCell(withIdentifier: "hiddenCell",for: indexPath) as! TheWallTableViewCell
return hiddenCell
}
else {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell",for: indexPath) as! TheWallTableViewCell
return cell
}