How to set the table view cell to adjust to label? - iphone

I am using Xcode to make an app. Using auto layout, I have a tableview contained in a container view which is part of a view controller embedded un a navigation controller.
This table view is my content page, so the individual tableview cells leads to another tableview which contains bulk of the information I would like to display.
I added UIlabel which contains a paragraph of words to each tableview cells and set the constraints to the respective tableview cells.
In the storyboard, it looks alright having to be able to see all the paragraphs. I have set the line to be 0, and word wrap.
When I run the programme with lets say 4s simulator, the table view cells do not display the whole paragraph but rather, just indicate "..." at the end of each paragraph.
How do I set the settings such that the tableview cells will adjust itself according to the UIlabel after being word wrapped giving a certain screen sizes of phone?
PS: I am new to SWIFT programming and thanks for taking your time to help me.

Have you done this?:
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
This is required for self-sizing table view cells. Also make sure of the following things:
a) The number of lines of UILabel is set to 0
b) The autolayout system in the table view cell is proper -- all the views are pinned on all sides and the autolayout can accurately determine the height of the cell.
c) Also do a tableView.estimatedRowHeight = 75 (or your estimated height) for efficiency.

add this two line in viewDidLoad Method and label number of lines 0 and dont give any height.
func viewDidLoad() {
super.viewDidLoad()
tableView.estimatedRowHeight = 44.0
tableView.rowHeight = UITableViewAutomaticDimension
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! CustomCell
//cell.customTexLabel Number 0f lines 0 and dont give height contrains just Leading,Trailing,TOP and Bottom.
cell.customTextLable?.text = "Here index starts from 0 which means first element can be accessed using index as 0, second element can be accessed using index as 1 and so on. Let's check following example to create, initialize and access arrays:Here index starts from 0 which means first element can be accessed using index as 0, second element can be accessed using index as 1 and so on. Let's check following example to create, initialize and access arrays:Here index starts from 0 which means first element can be accessed using index as 0, second element can be accessed using index as 1 and so on. Let's check following example to create, initialize and access arrays:"
return cell
}

Hi #Daniel you can learn how to create self sizing cell here is the demo tutorial for custom dynamic cell
http://developerclouds.com/2016/03/23/table-view-custom-cell-with-self-sizing/

Related

Setting the height: TableViewCells with custom Nib that are different sizes

I have a TableViewController that has a custom TableViewCell under the identifier "customCell". Heres an image of the configuration of the cell along with the IBOulets connected to it:
The cell takes information from my backend and presents it. The description text view (just noticed that I accidentally named it descriptionLabel) doesn't allow scrolling so it expands based off of the content that it's holding. The database is being processed correctly from the database, and it's displaying on the app. The only problem is that the cell is not its correct height. On the TableViewControl that's registering this cell through its identifier, I automatically set the height of the cell using UITableViewAutomaticDimension in heightForRow:
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
but that's not working either. *The only thing that works is when I set the height of each cell to a standard value such as 200. That doesn't work for me because each cell will be a different height because of the length of the textView.
How do I set the height of a custom nib (tableViewCell) so that it adjusts based off of the content within it instead of setting the height to a specific value?
1-Remove both textViews and replace them with labels
2- Title lbl with theses constraints
top,leading,trailing , .lines = 0
3- Description lbl with theses constraints
bottom ,leading,trailing to contentView,top to bottom of title lbl , .lines = 0
Off course you can leave the 2 textviews , but you have to give each one an initial height and do this in
override func layoutSubviews() {
super.layoutSubviews()
self.titleTvHeight.constant = self.titleTv.contentSize.height
self.desTVheight.constant = self.desTv.contentSize.height
}
//
Don't forget to set this in viewDidLoad of the VC
tableView.estimatedRowHeight = 200
tableView.rowHeight = UITableViewAutomaticDimension
Anyway you can remove heightForRowAt

UITableViewAutomaticDimension-10.0

I am trying to set height of the last tableView row different from the others.
Instead of creating a new cell etc, I want to "cut" 10px from the height of this cell. As I have set automatic dimension for height, I can't use a constant value.
This is how it looks like:
tableView.estimatedRowHeight = 54.0
return UITableViewAutomaticDimension
I want something like this, but this does not work:
if isLastLineBla {
tableView.estimatedRowHeight = 44.0
return UITableViewAutomaticDimension-10.0
} else { ...
I hope you have the dataSource for your tableView and returning dataSource.count in your numberOfRowsAt method.
Now implement the heightForRowAt method to return proper value like below:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if lastRow {
return 44
}else{
return UITableViewAutomaticDimension
}
}
And do not set the tableView.estimatedRowHeight = 44.0 at every place, the only place you need to set is in your viewDidLoad method.
Think you're running into issues with the way a table view works. The table view implements a form of lazy loading so that there aren't too many views in memory.
Try using the table view delegate methods to "report" correct heights based off the cell's index.
https://developer.apple.com/reference/uikit/uitableviewdelegate/1614998-tableview
What you have to do is set a flag on your cell, called isLast or something like that. Then, when returning your cells from your table view delegate you should set that flag to true if it is indeed the last cell of your table.
Then, on your cell you should be able to modify your constraints based on that flag, such that the cell has 10 points less then the rest of the cells. I can't tell you exactly what constraint and how to modify it since I have no idea how your cell looks like.

Cell loaded in cellForItemAt, but not in visibleCells

I have a custom UICollectionView and the cells are loaded in cellForItemAt but when I try to get all the visible cells by using visibleCells I'm not getting all the cells.
For example, in cellForItemAt, I'm setting the alpha of the labels in the cells to 0. When panned, I want the alpha of those labels change to 1:
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
handleLabel(scrollView, active: true)
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
if pickerIsActive { handleLabel(scrollView, active: false) }
}
private func handleLabel(_ scrollView: UIScrollView, active: Bool) {
guard let pickerView = scrollView as? UICollectionView else { return }
let cells = pickerView.visibleCells.flatMap { $0 as? CustomCell }
panningIsActive = active
UIView.animate(duration: 0.3) {
cells.forEach { $0.label.alpha = $0.isSelected || active ? 1 : 0 }
}
}
And cellForItemAt:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CustomCell
cell.label.alpha = 0
return cell
}
What can I do to change all the "loaded" cells instead of just the "visible" cells?
The visibleCells are only the on screen cells. This used to be everything initialized in cellForItem:at: but as of iOS 10 UICollectionView now prefetches to improve scrolling performance (see WWD 2016 video) which maybe why you are having this problem. Anyways it sounds like all you want to do is animate the cells to fade in when they come on screen. You can either move your animation logic to willDisplayCell or subclass UICollectionViewCell. UIColectionViewCell inherits from UIView, so you can override didMoveToSuperView in your UICollectionViewCell and call your animation method there, which will cause the cell to animate as it appears.
I am using Xcode 11.4 and Swift 5, and I had the exactly the same issue: .visibleCells is not giving me all the loaded cells.
By reading #Josh Homann's answer and the comments below, I figured out 2 solutions.
The first solution is same as the solution you reached at: customize cell appearance in collectionView(_:willDisplay:_:) after it's loaded but before it's displayed on the screen.
Another quick and dirty solution is to simply uncheck UICollectionView's 'Prefetch' option in attributes inspector.
This fixes the issue because by disabling prefetching, UICollectionView will stop pre-loading cells that are not displayed on the screen, so .visibleCells are now all the loaded cells. This solution will work fine if you're simply loading static or small local data in the cells. If you're prefetching large data (e.g. images) from network for upcoming cells, you probably need Prefetching Enabled, then solution 1 is your go-to option.
It sounds like you might want to try using layoutAttributesForElements(in:).
You'll need to implement your own collection view layout subclass (rather than using the delegate methods) but I think it will be worth it in the long term.
Rather than manually managing the animations (via UIView.animateWithDuration) you use this method to tell the collection view what properties cells should have at different positions, and as people pan the collection view, the correct properties are automatically applied.
I tried to find a good Swift reference for this, but I could't, but here's a post in Objective-C that you can follow if you want to try this approach:
https://bradbambara.wordpress.com/2014/05/24/getting-started-with-custom-uicollectionview-layouts/

Use tags for tableView inside UIViewController to update Labels

I added a table view to my UIViewController. then i added a label to my custom cell inside the table view. i tried to update labels inside the tableview by using tags. seems it does not working.
this is my code.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: UITableViewCell = self.tableView.dequeueReusableCellWithIdentifier("LineItemCell", forIndexPath: indexPath)
let object = lineItemsObject[indexPath.row]
//cell.textLabel?.text = object["quantity"]
print(object["description"]!)
if let descriptionLabel = cell.viewWithTag(500) as? UILabel {
descriptionLabel.text = object["description"]
}
else
{
print("fail")
}
return cell
}
When i call the function always it does not read the tag and prints "fail". i have assigned correct tag value to my label also.
here i have attached a image of my label details in attribute inspector
Please help me the fix the issue.
As #TheAppMentor said code looks fine. Make sure you entered correct cell identifier. Then make sure you connected your view controller to correct class (it's my common mistake). Also make sure that something else in this cell hasn't the same tag. You can also print all subviews to check what's inside.
Your cell is not knowing about your label inside (the one with 500 tag). You are not providing a custom cell, because of this line:
let cell: UITableViewCell = self.tableView.dequeueReusableCellWithIdentifier("LineItemCell", forIndexPath: indexPath)
This is a predefined cell. As of documentation you can have predefined cells or custom ones (obtained by subclassing UITableViewCell):
"When creating cells, you can customize them yourself or use one of several predefined styles. The predefined cell styles are the simplest option. With the predefined styles, the cell provides label and image subviews whose positions and styling are fixed. ... To set the text and images of the cell, use the textLabel, detailTextLabel, and imageView properties."
If you want to go predefined:
If you want to just put the text onto cell use (I see this one is commented on first place).
cell.textLabel?.text = object["quantity"]
Go custom
Extend UITableViewCell on a separate swift file. Do your bindings here and work with your storyboard in parallel. Assign the custom class to your cell. Also, change dequeue:
let cell: MyCustomTableViewCell = self.tableView.dequeueReusableCellWithIdentifier("LineItemCell", forIndexPath: indexPath) as! MyCustomTableViewCell

Making UITableViewCell a square based on screen width

I have a table view controller displaying square videos, and I want each table view cell to be a square as well. Is it possible to have each UITableViewCell dynamically resize according to the width of the screen (for example 320x320 for iPhone5 and 375x375 for iPhone6)?
In my view controller's viewDidLoad function I have:
frameWidth = self.view.frame.size.width
self.videosView.rowHeight = UITableViewAutomaticDimension
self.videosView.estimatedRowHeight = frameWidth
The constraints for the view that displays the video inside the UITableViewCell are:
Leading and trailing space to superview, top space to superview, 1:1 aspect ratio
I still can't get the cell to be a square though. Any help would be appreciated!
You can use this tableview method:
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UIScreen.main.bounds.width
}
Note: Method in Swift 3
There is a good reason that this is hard to do. Cells inside UITableView is reused so it can be allocated once. (for performance)
Resizing view is performance wise costly, that's way you only put one number as height of cell.
What you can do is to have if statement and return accordingly to phone version.
try to use it with bounds instead of frame
frameWidth = view.bounds.size.width