I have not added any prototype cells but it should work according to the latest iOS 8 tableView. Here is my code
class ViewController: UIViewController,UITableViewDelegate {
#IBOutlet weak var tableView: UITableView!
var tabledata = ["hn, helooo dnsjakdnksandksajndksandkasjnkc sacjkasc jkas kjdjknasjkdnsaklmdlksamxklsamxlksamdklsandk cnsdjdnsklnjnfkdnflasfnlfnkdsnfjkdnfjkdsnjkd njsdkadnaksjdnjkasndsakdnkasdnsalkdn cjkndskasdnsakndksandjksandksajndkj ndsjkadnksalndls;adnklsa;mdas,mcjksanckasdjnklscaskncjks" , "hi i am ishan, helooo dnsjakdnksandksajndksandkasjnkc sacjkasc jkas kjdjknasjkdnsaklmdlksamxklsamxlksamdklsandk cnsdjdnsklnjnfkdnflasfnlfnkdsnfjkdnfjkdsnjkd njsdkadnaksjdnjkasndsakdnkasdnsalkdn cjkndskasdnsakndksandjksandksajndkj ndsjkadnksalndls;adnklsa;mdas,mcjksanckasdjnklscaskncjkssndjkasndjksandkjasndkjasndkjasndkjasndjka ", "a" ]
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tabledata.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell")
cell.textLabel.text = self.tabledata[indexPath.row]
return cell
}
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.estimatedRowHeight = 100.0;
self.tableView.rowHeight = UITableViewAutomaticDimension;
tableView.reloadData()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
I don't see any changes when I remove/add these lines
self.tableView.estimatedRowHeight = 100.0;
self.tableView.rowHeight = UITableViewAutomaticDimension;
For automatic cell sizing to work, you must add layout constraints to the cell subviews that fully describe the vertical size of the views. Without these constraints, your cell's have no way of knowing how big they actually need to be. This is most easily done in a storyboard.
estimatedRowHeight is just a hint to the table view that increases the table load time by deferring geometric calculations for the cells to scroll time (autolayout can be expensive to calculate). Autolayout is still required to tell the table view what size each cell should be.
Also worth noting is that you're not reusing cells in your table view. In your tableView(_:cellForRowAtIndexPath:) method, you should be dequeuing cells instead of creating a new one every time:
func tableView(tableView: UITableView, cellForRowAtAindexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! UITableViewCell
// configure cell...
return cell
}
1 :Add in ViewDidLoad
tableView.estimatedRowHeight = 140 // prototype cell height
tableView.rowHeight = UITableViewAutomaticDimension
2:reload your tableview in viewDidAppear
Important NOTE:to make UITableViewAutomaticDimension work you have to set all left, right, bottom, and top constraints relative to cell container view.
It will helps to give Table View Row Height Dynamically
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
NSDictionary *dictItinararay=[arrCodes objectAtIndex:indexPath.row];
CGSize sizeOfName = [[dictItinararay valueForKey:#"Name"] sizeWithFont:[UIFont systemFontOfSize:16] constrainedToSize:CGSizeMake(180, 1000) lineBreakMode:NSLineBreakByWordWrapping];
if(sizeOfName.height>45) {
return sizeOfName.height+10;
}
else {
return 45;
}
}
you can simple add line to set cell height
cell.textLabel.numberOfLines = 20
Related
I am building an app that lets the user create a "Story" which consists of a title and a text.
I am implementing a tableView that shows all created stories. So far everything works. But here is my issue:
When the user enters a title or text that is longer that what tableViewCell would be able to display, that cell doesn't show up at all.
Others with shorter names still do though.
I am using the cell style "subtitle".
How does one go about limiting the amount of text showing in the cell and what causes this bug? Because even if I find a way to fix it, there will probably still be a problem with text running off the screen.
Here is the code in my UITableViewController class:
class StoryTableViewController: UITableViewController {
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return savedStories.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "myCell", for: indexPath)
cell.textLabel?.text = savedStories[indexPath.row].title
cell.detailTextLabel?.text = savedStories[indexPath.row].text
return cell
}
override func viewDidLoad() {
super.viewDidLoad()
// 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()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
Here is a screenshot of the UI from the interface builder:
You need to create your custom UITableViewCell. And you can use available dynamic resizable cells for adjusting cell automatically to text length.
IB steps:
Make a UILabel on cell. Don't give any height constraint to it. just pin it up from all sides and do the followings :
label.numberOfLines = 0
In viewDidLoad:
self.tableView.estimatedRowHeight = 88.0 //Any estimated Height
self.tableView.rowHeight = UITableViewAutomaticDimension
Don't write heightForRow: method but if you want to use it because of several cells existing there , you can return UITableViewAutomaticDimension for that particular cell height.
Try this one out
You have to implement these two delegates, don't forget to bind tableView delegate and datasource with VC and set you label description property numberOfLines = 0 from storyboard.
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 60; // height of default cell
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return UITableViewAutomaticDimension; // It takes automatic height of cell
}
Now in storyboard do this below
Your view hierarchy should be like this
check only ViewLabelContatainer
Add a view and put all labels into it.
Label Container contraints
Label Title constraint
Label Description constraint
output
For that you need to use variable height TableViewCell
override func viewDidLoad()
{
super.viewDidLoad()
self.tableView.estimatedRowHeight = 200 // give maximum height you required
self.tableView.rowHeight = UITableViewAutomaticDimension
}
then add this delegate methode in your view controller
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat
{
return UITableViewAutomaticDimension
}
I have many customCells each cell may have a button which acts like a textbox or textArea.When the View loads they have very less height.
override func viewDidLoad() {
super.viewDidLoad();
self.view.backgroundColor = UIColor.groupTableViewBackground
self.tableView.separatorStyle = UITableViewCellSeparatorStyle.none
self.tableView.estimatedRowHeight = 100
tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.setNeedsLayout()
self.tableView.layoutIfNeeded()
}
And i have the following constraints defined on the cell
Will auto layout work with prototype cells at all?
If not how to implement this?
I tried with HeightforrowAtIndexPath method layout looks good only after scroll. Initial load of the view will not come with good layout.
below is my code for this.
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if (eleData.elementType=="apple")
{
return 90;
}
else if (eleData.elementType=="banana")
{
return 50;
}
else
{
return 30;
}
}
Any suggestions .
Thank you in advance.
Quick google search gives you your answer...
UITableView dynamic cell heights only correct after some scrolling
You need to add layout if needed before returning your cell in the cellForRowAtIndexPath method:
cell.layoutIfNeeded()
I have a UITableView inside a regular ViewController and I'd like to adjust the tableview's entire height.
I created the tableview through storyboard, and I'm loading data from an API in my ViewDidLoad. I set up the cells in the typical tableview method.
override func viewDidLoad() {
self.loadPerformers()
setupTableView(performersTableView)
}
func setupTableView(tableView: UITableView) {
tableView.dataSource = self
tableView.delegate = self
tableView.estimatedRowHeight = 90
tableView.rowHeight = UITableViewAutomaticDimension
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if tableView == self.performersTableView {
let performerCell = tableView.dequeueReusableCellWithIdentifier("PerformerCell", forIndexPath: indexPath) as! PerformersTableViewCell
let performer = self.performersArray[indexPath.row]
performerCell.performerPic.image = getPerformerImage(performer.english_name)
performerCell.performerName.text = performer.english_name + " " + performer.japanese_name
cell = performerCell
}
return cell!
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
var count:Int?
tableView.separatorStyle = UITableViewCellSeparatorStyle.None
tableView.separatorColor = UIColor.clearColor()
tableView.allowsSelection = false
if tableView == self.performersTableView {
count = self.performersArray.count
}
return count!
}
The problem I'm having is the tableview stays the same height after loading the data. Below I'm loading four items, but it's only showing 2. The tableview height doesn't change.
I've tried a few things, among them is changing the height of the tableview frame in the viewWillAppear:
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
let newHeight = self.performersTableView.rowHeight * CGFloat(self.numberOfPerformers)
self.performersTableView.frame = CGRectMake(performersTableView.frame.origin.x, performersTableView.frame.origin.y,
performersTableView.frame.size.width, newHeight)
}
This does nothing though, so I'm misunderstanding something in the rendering process. How do I redisplay the table with my desired height?
I have 2 solutions for your problem:
If you want to set height of Tableview based on Tableview Cells.
so first of when you get data from server Reload your Tableview and after reloading tableview you will get content height of Filled tableview using this code:
self.performersTableView.contentSize.height
then set this height as your tableview frame.
In design, set fix height of tableview and set reference of constraint and after reloading tableview:
self.performersTableViewHeightReference.constant = self.performersTableView.contentSize.height
I hope this helps You.
[self.theTableView setNeedsLayout];
[self.theTableView layoutIfNeeded];
Add this code in your setupTableView and numberOfRowsInSection is data count. And if you want to expend cell also according to content write code in cellForRowAtIndexpath: cell.detailTextLabel.numberOfLines = 0;
I put a UICollectionView into the UITableViewCell by following this tutorial and in my UICollectionViewCell, there's a Image View. So when I run my app, the collection view is not resizing itself at the same time in my cell I put a Text View which is resizing itself according to content, see the below images:
In this first image, I have a text view at the top which have some text in it, and below it with (pink background) is my collection view and inside of that with greenBackground is my image view, as you can see that collection view is taking the extra space instead of reducing itself as Text View Did.
in this second image you can see that my textView haves more content then before so its resized itself now overlapping the CollectionView
this is my TableViewCell:
class TableViewCell: UITableViewCell {
#IBOutlet var txtView: UITextView!
#IBOutlet private weak var collectionView: UICollectionView!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
// collectionView.frame = self.bounds;
// collectionView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
func setCollectionViewDataSourceDelegate
<D: protocol<UICollectionViewDataSource, UICollectionViewDelegate>>
(dataSourceDelegate: D, forRow row: Int) {
collectionView.delegate = dataSourceDelegate
collectionView.dataSource = dataSourceDelegate
collectionView.tag = row
collectionView.reloadData()
}
var collectionViewOffset: CGFloat {
get {
return collectionView.contentOffset.x
}
set {
collectionView.contentOffset.x = newValue
}
}
}
this is my collectionViewCell
class CollectionViewCell: UICollectionViewCell {
#IBOutlet var imgView: UIImageView!
override func awakeFromNib() {
self.setNeedsLayout()
//
// self.contentView.frame = self.bounds;
// self.contentView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
}
}
and this is my TableviewController
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(tableView: UITableView,
numberOfRowsInSection section: Int) -> Int {
return imageModel.count
}
override func tableView(tableView: UITableView,
cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell",
forIndexPath: indexPath) as! TableViewCell
cell.txtView.text = txtArray[indexPath.row]
return cell
}
override func tableView(tableView: UITableView,
willDisplayCell cell: UITableViewCell,
forRowAtIndexPath indexPath: NSIndexPath) {
guard let tableViewCell = cell as? TableViewCell else { return }
tableViewCell.setCollectionViewDataSourceDelegate(self, forRow: indexPath.row)
tableViewCell.collectionViewOffset = storedOffsets[indexPath.row] ?? 0
}
override func tableView(tableView: UITableView,
didEndDisplayingCell cell: UITableViewCell,
forRowAtIndexPath indexPath: NSIndexPath) {
guard let tableViewCell = cell as? TableViewCell else { return }
storedOffsets[indexPath.row] = tableViewCell.collectionViewOffset
}
}
extension TableViewController: UICollectionViewDelegate, UICollectionViewDataSource {
func collectionView(collectionView: UICollectionView,
numberOfItemsInSection section: Int) -> Int {
return imageModel[collectionView.tag].count
}
func collectionView(collectionView: UICollectionView,
cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("Cell",
forIndexPath: indexPath) as! CollectionViewCell
cell.imgView.frame = CGRectMake(0, 0, collectionView.frame.width, collectionView.frame.height)
cell.imgView.contentMode = .ScaleAspectFit
//cell.addSubview(imageView)
cell.imgView.image = ResizeImage(UIImage(named: imageModel[collectionView.tag][indexPath.item])!, targetSize: CGSizeMake( cell.imgView.frame.width , cell.imgView.frame.height))
//imageView.image = UIImage(named: imageModel[collectionView.tag][indexPath.item])
return cell
}
}
How can I make this collection view to AutoLayout itself according to the content in it? I also tried this:
self.tableView.rowHeight = UITableViewAutomaticDimension;
self.tableView.estimatedRowHeight = 100;
but didn't worked (my collection view got disappear) if anybody knows how to do this, then please guide me..
I faced a similar issue when i used collection view inside a table view cell. No matter what i did i couldn't get the table view to resize automatically but the collection view did. Soo instead of autolayout i did it using code.
I ended up having to calculate the size of the label in the collection view numberOfSections in collection view and passing this height using a delegate to the view controller that has the tableView's delegate and dataSource and reloading the appropriate row of the table view.
As it happens, the numberOfSections in collectionview data source gets called everytime and the delegate resizes the table view height.
Some thing like this-
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{
[self.delegate setViewHeight:[self getHeightForCellAtIndexPath:[NSIndexPath indexPathForRow:currentSelected inSection:0]]];
return 1;
}
This ought to give you a general idea.
EDIT: Sorry i misunderstood, your question before. Here is something that should work for you:
As per my understanding, you have a table view cell with a label view and collection view inside of it.
Now, inside your table view cell, you should add top, leading and trailing constraints space to the label. Now inside your collection view position your image vertically in the center and add an appropriate top and bottom to the cell superview. Your collection view itself should have a CONSTANT value in leading, trailing, top to label and bottom to superview. Also add a fixed height constraint to your collection View (assuming you want the image sizes to remain the same).
Now lets says View Controller A is the data source for your table view and the table view cell is the data source for your collection view.
In your viewController A, you should write your height for row at indexPath as-
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
CGSize stringSize = [yourStringArray[indexPath.row] boundingRectWithSize:CGSizeMake(_yourCollectionView.frame.size.width, FLT_MAX)
options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading)
attributes:#{NSFontAttributeName:[UIFont yourFont size:yourFontSize]} context:nil].
return stringSize.height + 35; //magic number 35, play around with it to suit your need. Did this to always have a minimum fixed height.
}
This will allow your tableViewRowForHeight for that particular index to have the height of your label added to it and the constraints ought to do the rest.
I have a table with some customizations.
Here is my code:
import UIKit
class ViewController: UIViewController, UITableViewDelegate {
var exercises : [String] = ["Swimming", "Running", "Weight Lifting", "Biking", "Climbing"]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
//Necessary for basic tableView setup. Defines number of rows in a specific section.
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
//Setting the amount of rows to the number of elements in exercises. This function returns that.
tableView.backgroundColor = UIColor.clearColor()
return exercises.count
}
//Necessary for basic tableView setup. Helps us out content for every cell in the index path. Runs = rows
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
tableView.separatorColor = UIColor.clearColor()
//Setting the footer to default so the extra junk does not show
tableView.tableFooterView = UIView()
//This will be returned. This automatically creates a prototype cell
var cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell")
//Setting every cell to the respective item in exercises
cell.textLabel?.text = exercises[indexPath.row]
cell.textLabel?.font = UIFont(name: "Avenir-Light", size: 17)
cell.textLabel?.textColor = UIColor.whiteColor()
cell.textLabel?.textAlignment = .Center
//Border Code
cell.layer.borderWidth = 2.0
cell.layer.borderColor = UIColor.whiteColor().CGColor
//Round Corners
cell.layer.cornerRadius = 20
return cell
}
func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
cell.backgroundColor = UIColor.clearColor()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
I want to have some spacing between each UITableViewCell. I have already tried the following:
Change the height of each row. This option does not work because I have borders. Adding more height just makes each row look larger.
Convert each row into a section and then use heightForHeader in section.The post. I want to avoid this option because I would have to convert all my rows to sections.
Add a transparent UIView within each row. Again, this option does not work because I have borders.
Is there any other alternative?
Thanks
First of all, you should move tableView related code out of tableView:cellForRowAtIndexPath, preferably to viewDidLoad:
override func viewDidLoad {
super.viewDidLoad()
tableView.separatorColor = UIColor.clearColor()
tableView.tableFooterView = UIView()
}
Secondly, UITableViewCells are reusable objects so they are dequeued by the tableView when required:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("Cell")
if cell == nil {
cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell")
}
...
}
As for your problem, you should either set rowHeight on tableView
override func viewDidLoad {
super.viewDidLoad()
...
tableView.rowHeight = 100.0
}
or implement tableView:heightForRowAtIndexPath: instead:
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 100.0
}
You should also update textLabel's border and corner radius value instead of the cell:
//Border Code
cell.textLabel.layer.borderWidth = 2.0
cell.textLabel.layer.borderColor = UIColor.whiteColor().CGColor
//Round Corners
cell.textLabel.layer.cornerRadius = 20
I tried ozgur's method but it didn't work because I had borders between my table view cells. Eventually, I used the answer from this post. Hope it helps
You can add spacing by creating an extra view inside the cell that contains the content of the cell that has spacing between the top and the bottom. Make the background color of the cell translucent and it'll appear as though the cell has spacing above and below it