I have been having alignment issues.The message label keeps over writing the time stamp and the username is disappearing. I have tried the suggested constraints but nothing has worked for me.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell")
//Transform Data From ^ to load at the bottom
tableView.transform = CGAffineTransform (scaleX: 1,y: -1);
cell?.contentView.transform = CGAffineTransform (scaleX: 1,y: -1);
cell?.accessoryView?.transform = CGAffineTransform (scaleX: 1,y: -1);
//Set username label to display username
let usernameLabel = cell?.viewWithTag(1) as! UILabel
usernameLabel.text = generalRoomDataArr[indexPath.row].username
//Set message label to display message
let messageLabel = cell?.viewWithTag(2) as! UILabel
messageLabel.text = generalRoomDataArr[indexPath.row].message
messageLabel.numberOfLines = 0
//initialize UI Profile Image
let imageView = cell?.viewWithTag(3) as! UIImageView
//Make Porfile Image Cirlce
imageView.layer.cornerRadius = imageView.frame.size.width/2
imageView.clipsToBounds = true
//Set timeStampLabel to current time AGO
let timeStampLabel = cell?.viewWithTag(4) as! UILabel
timeStampLabel.text = generalRoomDataArr[indexPath.row].timeStamp
timeStampLabel.numberOfLines = 0
//Loading and change of Usesrs profile image on chat cell
let userProfileChatImage = generalRoomDataArr[indexPath.row].photoURL
//Load profile image(on cell) with URL & Alamofire Library
let downloadURL = NSURL(string: userProfileChatImage!)
imageView.af_setImage(withURL: downloadURL as! URL)
// your cell coding
return cell!
}
Problem
StoryBoard
//TableView Cell word wrap (Dynamic Text)
self.tableView.dataSource = self
self.tableView.delegate = self
self.tableView.estimatedRowHeight = 78
self.tableView.rowHeight = UITableViewAutomaticDimension
Do i need to set the time stamp label to 0 as well?
messageLabel.numberOfLines = 0
I used to use labels like you are using and found out about NSMutableAttributedString(). There are tons of videos and web pages that explain how it works. If there are people who like a specific one, they can link it in the comments! I use the attributedString with a UITextView in order to display everything (text-based) that I need. I defer to this video (beginning at 12:00 mins) on YouTube because it is difficult to explain in text. In order to tackle the problem of creating a UITableViewCell that fits varying amounts of text, you will want to drag in a UITextView that does not have a specific width or height constraint. This will allow it to change with the cell. Then, using the code you have...
self.tableView.estimatedRowHeight = 78
self.tableView.rowHeight = UITableViewAutomaticDimension
Your cells will dynamically change. One trick to get this working is to do the following steps:
1) Disable user interaction on the UITextView using isUserInteractionEnabled = false
2) Uncheck Editable and Selectable in the Interface Builder (Storyboard), as well as unchecking Scrolling Enabled in the IB.
If you've already captured all the constraints in that screenshot. I think you missed a vertical spacing constraint between timestamp label and message label. After add this constraint, you will also need to change vertical compress resistance and hugging priority for 1 of three labels. I recommend decrease message label's.
Related
I am using a UITableViewController to display rows of playing cards. I've set the Mode to "Aspect Fit" and I've checked the "Clip Subviews" in the Storyboard for the ImageView in each row's cell, its ContentView parent, and the Cell that contains the ContentView.
Everything looks as expected when the table is initially displayed but, when I swipe to scroll through the table, some (not all) of the new rows that scroll into view have images scaled to the wrong size, as shown.
It seems like if I drag quickly, I get more rows that are of the wrong size. If I drag slowly, all the new rows are scaled appropriately. When I use a different emulator, the incorrect scaling would make some of the images too big rather than too small and so the entire row of cards would not fit within the display.
In the code, I've set the contentMode and clipToBounds, but they do not seem to help:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("LineCell", forIndexPath: indexPath)
let index = indexPath.row % 4
let imagename = "cards\(index)"
let im = UIImage(named: imagename)
cell.contentMode = UIViewContentMode.ScaleAspectFit
cell.clipsToBounds = true
cell.contentView.contentMode = UIViewContentMode.ScaleAspectFit
cell.contentView.clipsToBounds = true
cell.imageView?.contentMode = UIViewContentMode.ScaleAspectFit
cell.imageView?.clipsToBounds = true
cell.imageView?.image = im
return cell
}
Did I miss something obvious? Thanks!
I ended up using a programmatic way around the problem.
let cellImage : UIImageView = UIImageView(frame: CGRectMake(0, 0, cell.bounds.size.width, cell.bounds.size.height))
cellImage.contentMode = UIViewContentMode.ScaleAspectFit
cellImage.clipsToBounds = true
cellImage.image = im
cell.addSubview(cellImage)
I would still like to find a way to do it via the Storyboard, which I recall used to work in a straightforward manner...back before Apple started coming out with devices of all shapes and sizes leading to their need to offer increasingly complicated ways to accommodate all the sizes in a semi-automated, constraint-based system that requires quite a bit of overhead even for the simplest tasks. But, for now, this will do.
i'm using tableview in iOS 9, Swift 2
I don't understand why , when i create a table view with simple cells, i get a wrong width of the contentview, even if i set container view to 1000.
The cell width is exactly 1000, but the textLabel inside is less than 1000. Also separators are centered and with wrong width.
How can i get my cells displayed correctly , and covering the entire container view?
Everything is created programmatically.
Here is my code:
if tableView == nil {
tableView = UITableView(frame: CGRect(x: 0, y: 44/*88*/, width: self.view.bounds.size.width, height: self.view.bounds.size.height - 44/*88*/), style: UITableViewStyle.Plain)
tableView!.delegate = self
tableView!.backgroundColor = .clearColor()
tableView!.dataSource = self
tableView!.rowHeight = 40.0
tableView!.allowsSelection = false
tableView!.registerClass(UITableViewCell.self, forCellReuseIdentifier: "cell")
view.addSubview(tableView!)
tableView!.reloadData()
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var MyIdentifier: String = "MyReuseIdentifier"
var cell: UITableViewCell? = tableView.dequeueReusableCellWithIdentifier(MyIdentifier)
if cell == nil {
cell = UITableViewCell(style: .Default, reuseIdentifier: MyIdentifier)
}
cell!.textLabel!.text = "Test"
cell!.backgroundColor = .clearColor()
cell!.textLabel!.textColor = .blackColor()
return cell!
}
tableView!.cellLayoutMarginsFollowReadableWidth = false
This is the solution!
It is not necessary to set contentInsets.
While the cells's width is the width of the entire view, it's content view is inset on all sides by (I think) 8 points, so it makes sense for the label not to be across the whole screen
To have a label that goes across the entire width of the screen create a custom cell class and add constraints to its label to account for this. (Label's leading to content view leading = -8.0)
You can check
tableView.contentInset
And then update left inset. Also, check that you have not given any constraint, like leadingSpace. Or margin to the UITableView itself. Similarly you have
cell.separatorInset
By default there is left padding of 5, so make this 0.
So I have a TableView with 2 prototype cells. Here is my code:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if indexPath.row == 0 {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! ItemDetailsCell
cell.centerImage.image = mainImage
cell.heading.text = detailsHeadings[indexPath.row]
let headingString = detailsHeadings[indexPath.row]
cell.body.text = details[headingString]
tableView.rowHeight = cell.labelBlack.frame.height + 40
return cell
} else {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell2", forIndexPath: indexPath) as! ItemDetailsCell
cell.heading.text = detailsHeadings[indexPath.row]
let headingString = detailsHeadings[indexPath.row]
cell.body.text = details[headingString]
let bodyString = details[headingString]
let labelWidth = Int(cell.body.frame.width)
println(labelWidth)
let label = UILabel(frame: CGRect(x: 0, y: 0, width: labelWidth, height: 10000))
label.text = bodyString
label.numberOfLines = 100
label.font = UIFont(name: "OpenSans-Light", size: 12.0)
label.sizeToFit()
tableView.rowHeight = label.frame.height + 3
return cell
}
}
So the second prototype cell has just two labels with the values being assigned from a Dictionary. The cell size needs to expand or contract based upon how many lines of text there are. In auto layout I have the number of lines set to 0 so it will pick however many lines are needed. This works fine except when you scroll within the app it will snap the view up as users scroll back up from the bottom. Is there a way to avoid this?
Thanks in advance for any help.
I found this actually after spending some more time looking:
http://candycode.io/automatically-resizing-uitableviewcells-with-dynamic-text-height-using-auto-layout/
It gave me what I needed. I removed the parts of my code that set the rowHeight and then used the viewDidLoad method as well as auto layout to constrain my cell sizes and after a bit of trial and error it is working without snapping to place when you scroll.
You are changing the rowHeight of the tableview. That's most likely very wrong. The rowHeight of the tableView is the default for all rows that don't have their own height, so you are effectively changing the height of all cells.
You should use the delegate method tableView:heightForRowAtIndexPath:
I have a dynamic cell with autolayout that has an image and a dynamic label. Currently I try to draw the bubble image but I need to know what is the size of the label given its text. I have to say that I always receive a bad size and when I scroll the tableview, the bubble image is placed corectlly but it ads another bubble.
Here is my code:
func imageCellAtIndexPath(indexPath:NSIndexPath) -> SenderTableViewCell{
let cell = self.tableView.dequeueReusableCellWithIdentifier("SenderIdentifier") as! SenderTableViewCell
cell.senderMessageLAbel.text = "fadfasdfasdfasdfasdfasdadfasdfsb"
cell.senderMessageLAbel.sizeToFit()
cell.senderNameLabel.text = "Stefan"
let padding: CGFloat = 10.0
// 4. Calculation of new width and height of the chat bubble view
var viewHeight: CGFloat = 0.0
var viewWidth: CGFloat = 0.0
viewHeight = cell.senderMessageLAbel.frame.size.height + padding
viewWidth = cell.senderMessageLAbel.frame.size.width + padding/2
if viewHeight > viewWidth {
viewHeight = cell.senderMessageLAbel.frame.size.width + padding/2
viewWidth = cell.senderMessageLAbel.frame.size.height + padding
}
let bubbleImageFileName = "bubbleMine"
let imageViewBG : UIImageView = UIImageView(frame: CGRectMake(cell.senderMessageLAbel.frame.origin.x - 5, cell.senderMessageLAbel.frame.origin.y - 10,viewWidth,viewHeight ))
imageViewBG.image = UIImage(named: bubbleImageFileName)?.resizableImageWithCapInsets(UIEdgeInsetsMake(14, 22,17 , 20))
cell.insertSubview(imageViewBG, atIndex: 0)
imageViewBG.center = cell.senderMessageLAbel.center
return cell
}
I can't figure out what is wrong with my code. Any suggestions?
I'm assuming your function is being called at cellForItemAtIndexPath function of UICollectionView DataSource. That function is called multiple times, whenever there is a need of drawing collection view cells that come into view. So each time that happens, you're inserting imageViewBG to the cell, and hence the duplicates.
A quick solution would be to add a specific tag to the imageViewBG as below and remove it each time before re-adding it.
cell.viewWithTag(99)?.removeFromSuperview()
let imageViewBG = //Configure
imageViewBG.tag = 99
cell.insertSubview(imageViewBG, atIndex: 0)
Although this would help solve the duplicates problem, I would strongly suggest you to add the imageView to your custom cell on the storyboard and configure the image that it should display in cellForItemAtIndexPath .
Thanks in advance for the help.
I have a UITableView within a main view contoller. Within the prototype cell, I have a UIImageview. In the code below everything works until I add the 5 lines to apply a circular mask and border. Once I do that, the images will not load unless I scroll the cells. The mask and border do get applied perfectly however. Will be great when it works... but until then.
Certainly this has been seen before. I'm a swift/objective-C newbie.
Working in swift for this one.
Code below;
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("mixerCell", forIndexPath: indexPath) as! MixerTableViewCell
// set label background color to clear
cell.textLabel?.backgroundColor = UIColor.clearColor()
// set highlight selection to none
cell.selectionStyle = .None
// set image for cell
let imageView = cell.viewWithTag(1) as! UIImageView
// put circular mask and border. This is the problem code that causes initial load of the tableview images to show up blank.
imageView.layer.cornerRadius = imageView.frame.size.width / 2;
imageView.clipsToBounds = true;
let color1 = UIColor(white: 1.0, alpha: 0.5).CGColor as CGColorRef
imageView.layer.borderWidth = 2;
imageView.layer.borderColor = color1
// assign image
imageView.image = UIImage(named: mixerSounds[indexPath.row])
return cell
}
initial view load
after scroll
your code is perfectly working for me. Here i am using Xcode-7. i think you are using Xcode-6.3 or less version. just upgrade it to Xcode- 7. and if you are using the same then just check your heightforRowAtIndexpath or other delegates there should be some issue.
thanks
Try changing the below lines,
// replace this
let imageView = cell.viewWithTag(1) as! UIImageView
// to
let imageView = cell.yourImageViewName
/* yourImageViewName is the outlet
reference name you have given in the
MixerTableViewCell custom class.
*/
Edit 2: Just for debugging purposes,
hardcode the image name and check if the image appears on the all the cells.
imageView.image = UIImage(named: "first1.png")
override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell!
{
let cellIdentifier = "cell"
var cell : UITableViewCell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier) as UITableViewCell
cell.image_View.image = UIImage(named: mixerSounds[indexPath.row])
println("The loaded image: \(image)")
cell.image_View.layer.masksToBounds = false
cell.image_View.layer.borderColor = UIColor.blackColor().CGColor
cell.image_View.layer.cornerRadius = image.frame.height/2
cell.image_View.clipsToBounds = true
return cell
}
Give imageview outlet to cell and not give imageview name because by default name is imageview so take diffrent name
It looks like the problem is using clipToBounds = true I am facing the same issue while making circular UIImageView inside UITableViewCell
I didn't find the exact solution but for now I found a way to do this
if (indexPath.row == indexPath.length && !isTableReloaded)
{
let dispatchTime: dispatch_time_t = dispatch_time(DISPATCH_TIME_NOW, Int64(0.000000001 * Double(NSEC_PER_SEC)))
dispatch_after(dispatchTime, dispatch_get_main_queue(), {
self.reloadTableView()
})
}
func reloadTableView()
{
isTableReloaded = true
self.tableViewContacts.reloadData()
}
Here isTableReloaded is a Bool type var which is initialized to false in viewDidLoad()
and the if condition is to be placed at the last of cellForRowAtIndexPath but before return statement
This will resolve our problem but do not rely on this as this is not the best approach.
Please post solution for this if any one found the better approach.
Here is a perfect and state away solution for circular image in UITableview Cell.
Simply modify your UITableviewCell (custom cell) class with below code.
override func awakeFromNib() {
super.awakeFromNib()
imgEvent.layer.frame = (imgEvent.layer.frame).insetBy(dx: 0, dy: 0)
imgEvent.layer.borderColor = UIColor.gray.cgColor
imgEvent.layer.cornerRadius = (imgEvent.frame.height)/2
imgEvent.layer.masksToBounds = false
imgEvent.clipsToBounds = true
imgEvent.layer.borderWidth = 0.5
imgEvent.contentMode = UIViewContentMode.scaleAspectFill
}
It will also helps to solve the problem of image circular only after scrolling table..(if any!)
let width = cell.frame.size.width
cell.img.layer.cornerRadius = width * 0.72 / 2
0.72 is the ratio of the cell width to image width, for eg. cellWidth = 125 and imageWidth = 90, so 125/90 would give 0.72. Do similar calculation for your image.
First: Images doesn't load until you scroll, because when cellForRowAtIndexPath methods called the constraints doesn't set for image until now, so when scrolling the constraints was added and the image appears, so if you set proportional width and height for imageView (width==height) in cell then
do that
let w = tableview.frame.width*(proportional value like 0.2)
imageView.layer.cornerRadius = w / 2
imageView.clipsToBounds = true;