Autosize for cell in UICollectionViewCell - swift

In my cell I have Title label and description label. Description label can be small and big. I use for it descriptionLabel.sizeToFit(), but how to use the same for cell. If cell.sizeToFit() doesn't work
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! ExercisesCollectionViewCell
let workouts = exercises[indexPath.item]
cell.titleLabel.text = workouts.titleExercise
cell.descriptionLabel.text = workouts.descriptionExercise
cell.descriptionLabel.sizeToFit()
cell.sizeToFit()
return cell
}
image

Use UITableview instead of UICollectionView
First you have to count the number of lines of UILabel
NSInteger lineCount = 0;
CGSize textSize = CGSizeMake(yourLabel.frame.size.width, MAXFLOAT);
int rHeight = lroundf([yourLabel sizeThatFits:textSize].height);
int charSize = lroundf(yourLabel.font.lineHeight);
lineCount = rHeight/charSize;
NSLog(#"No of lines: %i",lineCount);
else you can take extension to count max line of label
extension UILabel {
func calculateMaxLines() -> Int {
let maxSize = CGSize(width: frame.size.width, height: CGFloat(Float.infinity))
let charSize = font.lineHeight
let text = (self.text ?? "") as NSString
let textSize = text.boundingRect(with: maxSize, options: .usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font: font], context: nil)
let linesRoundedUp = Int(ceil(textSize.height/charSize))
return linesRoundedUp
}
}
Use that:
let lineCount = YourLabel. calculateMaxLines
Now Set the height for each line of label
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return lineCount * 18 //If total 3 line so 3*18 = 54 is height else you can take any number instead of 18 according to font size height
}

Related

Adjusting font size of UITableViewCell based on the device size

Have been trying to change the font size inside the UITableViewCell dynamically based on the device size.
Code to create a table inside a UIView (in an SKScene):
suitsView = UIView()
suitsView.backgroundColor = .purple
suitsView.alpha = 0
self.scene?.view?.addSubview(suitsView)
suitsTableView.register(suitsTableCell.self, forCellReuseIdentifier: "cellSuits")
suitsTableView.separatorColor = UIColor(red: 153/255, green: 255/255, blue: 153/255, alpha: 1)
suitsTableView.tableFooterView = UIView()
suitsTableView.allowsMultipleSelection = true
suitsTableView.reloadData()
suitsTableView.alpha = 0
suitsTableView.populateTable()
displayText() // Displays Text
suitsTableView.rowHeight = UITableViewAutomaticDimension
suitsTableView.estimatedRowHeight = 600
suitsView.addSubview(suitsTableView)
This is my UITableView:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let selectedIndexPaths = tableView.indexPathsForSelectedRows
let rowIsSelected = selectedIndexPaths != nil && selectedIndexPaths!.contains(indexPath)
let cell : SuitsTableCell = tableView.dequeueReusableCell(withIdentifier: "cellSuits", for: indexPath as IndexPath) as! SuitsTableCell
cell.lblName.text = self.items[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
{
return self.bounds.height/5
}
This is my UITableViewCell:
override init(style: UITableViewCellStyle, reuseIdentifier: String?)
{
super.init(style: style, reuseIdentifier: reuseIdentifier)
selectionStyle = UITableViewCellSelectionStyle.none
backgroundColor = UIColor.yellow
contentView.backgroundColor = UIColor.yellow
// Font size
var fontSize : CGFloat = 20.0
let marginGuide = contentView.layoutMarginsGuide
lblName = UILabel()
lblName.textColor = UIColor.black
lblName.font = UIFont(name:"Noteworthy-Bold", size: fontSize)
// CONSTRAINTS
lblName.translatesAutoresizingMaskIntoConstraints = false
lblName.topAnchor.constraint(equalTo: marginGuide.topAnchor).isActive = true
lblName.leadingAnchor.constraint(equalTo: marginGuide.leadingAnchor).isActive = true
lblName.bottomAnchor.constraint(equalTo: marginGuide.bottomAnchor).isActive = true
lblName.widthAnchor.constraint(equalToConstant: 200)
lblName.numberOfLines = 0
lblName.adjustsFontSizeToFitWidth = true
lblName.contentScaleFactor = 0.5
contentView.addSubview(lblName)
}
On iPhone 8, my table looks like this:
But on iPad, it looks like this:
I need to have a bigger font in iPad. How can I adjust the font size based on constraints or the row height?
Thanks.
Edit: I am not using Storyboard; please do not suggest it.
Interestingly, if I have this code inside my cellForRow method:
cell.lblName.font = UIFont(name:"Noteworthy-Bold", size: (tableView.bounds.height/14).rounded())
I can adjust the font size but the first row (None) is always empty...
You can use like this:
// Screen width.
public var screenWidth: CGFloat {
return UIScreen.main.bounds.width
}
// Screen height.
public var screenHeight: CGFloat {
return UIScreen.main.bounds.height
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let selectedIndexPaths = tableView.indexPathsForSelectedRows
let rowIsSelected = selectedIndexPaths != nil && selectedIndexPaths!.contains(indexPath)
let cell : SuitsTableCell = tableView.dequeueReusableCell(withIdentifier: "cellSuits", for: indexPath as IndexPath) as! SuitsTableCell
cell.lblName.text = self.items[indexPath.row]
cell.lblName.font = UIFont(name:"Noteworthy-Bold", size: (screenwidth * 0.0373).rounded()) // 0.0373 = requiredfontsize / 375
return cell
}
Note: I don't know whether this method is right or wrong but I have tried this and it worked for me.
You can go through this for more info: Scale text label by screen size
Use Size-Class and hit on + symbol just before the Font tab (in storyboard) and choose Regular * Regular and set the font size as per your wish.

Custom UIImageView in UITableViewCell being cut off in subsequent cells - Swift

UITableViewCell Custom UIImageView
Image:
Custom TableViewCell UIImageView
If you click on the link above, you'll see that after the first row, the custom UIImageView is being cut off horizontally and then vertically in subsequent rows. Any ideas on how to fix this?
In viewDidLoad I changes row heights as follows:
// Set cell row height
self.tableView.rowHeight = 60
Here's the code for the TableView:
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
var count = Int()
if self.names.count != 0 {
count = self.names.count
} else if self.names.count == 0 {
count = 1
}
return count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell : UITableViewCell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as UITableViewCell
for view in cell.contentView.subviews {
// Clear subviews
view.removeFromSuperview()
}
// Customize separator width
tableView.separatorInset = UIEdgeInsetsZero
cell.separatorInset = UIEdgeInsetsZero
cell.layoutMargins = UIEdgeInsetsZero
cell.preservesSuperviewLayoutMargins = false
// Create imageView
let imageView = UIImageView(frame: CGRectMake(10, 5, 50, 50))
imageView.contentMode = UIViewContentMode.ScaleAspectFit
imageView.layer.cornerRadius = 25
imageView.clipsToBounds = true
cell.contentView.addSubview(imageView)
// Create textLabel
let textLabel = UILabel(frame: CGRectMake(70, 10, self.view.frame.width, 20))
textLabel.font = UIFont(name: "Arial", size: 15.0)
textLabel.textAlignment = .Left
cell.contentView.addSubview(textLabel)
// Create lastMessageLabel
let lastMessageLabel = UILabel(frame: CGRectMake(70, 30, self.view.frame.width, 20))
lastMessageLabel.font = UIFont(name: "Arial", size: 12)
lastMessageLabel.textAlignment = .Left
lastMessageLabel.textColor = UIColor.grayColor()
cell.contentView.addSubview(lastMessageLabel)
if self.names.count != 0 {
// Add contact cell
imageView.image = self.images[indexPath.row]
textLabel.text = self.names[indexPath.row] as? String
lastMessageLabel.text = self.lastMessage[indexPath.row] as? String
}
if self.names.count == 0 {
// Add warning
imageView.image = UIImage(named: "user-placeholder.png")
textLabel.text = "No users saved :("
lastMessageLabel.text = "Tap the search tab to find users."
}
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if self.names.count != 0 {
print(self.names.count)
print(self.names[indexPath.row])
print(self.ids[indexPath.row])
self.selectedUserName = self.names[indexPath.row] as! String
self.selectedUserId = self.ids[indexPath.row] as! String
self.selectedUserImage = self.images[indexPath.row]
self.performSegueWithIdentifier("chat", sender: self)
}
}
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == UITableViewCellEditingStyle.Delete && self.userRef.savedUsers.count != 0 {
startActivityIndicator()
let savedUsers = NSMutableArray()
for user in self.userRef.savedUsers {
if user as! String != self.userRef.savedUsers[indexPath.row] as! String {
savedUsers.addObject(user as! String)
}
}
self.rootRef.child("users").child((FIRAuth.auth()?.currentUser?.uid)!).child("savedUsers").setValue(savedUsers, withCompletionBlock: { (error: NSError?, FIRDatabaseReference: FIRDatabaseReference) -> Void in
if error == nil {
print("deleted: \(self.userRef.savedUsers[indexPath.row])")
// Remove user
self.userRef.savedUsers.removeObject(self.userRef.savedUsers[indexPath.row])
self.names.removeObjectAtIndex(indexPath.row)
self.images.removeAtIndex(indexPath.row)
self.lastMessage.removeObjectAtIndex(indexPath.row)
self.stopActivityIndicator()
self.loadUsers()
self.displayAlert("Contact Deleted", message: "The user has been removed from your contacts.")
} else {
self.stopActivityIndicator()
self.displayAlert("Delete Failed", message: "Please try again later.")
}
})
}
}
EDIT:
The problem was imageView.contentMode = UIViewContentMode.ScaleAspectFit which needed to be .ScaleAspectFill

Expandable cell with dynamic data (swift)

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("idcell", forIndexPath: indexPath) as UITableViewCell
let lblTitle : UILabel = cell.contentView.viewWithTag(101) as! UILabel
lblTitle.text = (deptId[indexPath.row] as? String)! + " " + (deptDesc[indexPath.row] as? String)!
var height:CGFloat = 0
cell.backgroundColor = UIColor.whiteColor()
cell.accessoryType = UITableViewCellAccessoryType.DisclosureIndicator
if(indexPath == selectedIndexPath){
cell.backgroundColor = UIColor.grayColor()
for i in 0...deptProfile.count-1{
let deptmentProfile = UIButton(frame: CGRectMake(0,44+height,400,41))
deptmentProfile.addTarget(self, action: "buttonAction:", forControlEvents: UIControlEvents.TouchUpInside)
height = height+41
deptmentProfile.setTitle(deptProfile[i] as! String, forState: UIControlState.Normal)
deptmentProfile.setTitleColor(UIColor.blackColor(), forState: .Normal)
deptmentProfile.contentHorizontalAlignment = UIControlContentHorizontalAlignment.Left
deptmentProfile.backgroundColor = UIColor.whiteColor()
deptmentProfile.titleEdgeInsets = UIEdgeInsetsMake(0, 40, 0, 0); //margin to the left
cell.addSubview(deptmentProfile)
}
cell.accessoryType = UITableViewCellAccessoryType.None
}
return cell
}
Question: since my expanded data is dynamic,(In coding)deptProfrile is dynamic. How can i clear the cell content? it seems the subview will remain to the cell every time.
You should notice that the cell is reused, so, you have not coded for the else case for that if: if(indexPath == selectedIndexPath). You should provide the code for UI for that else.
You can give the estimated cell height for the tableview, so it will expand the cell for you.
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat
{
if(indexPath == selectedIndexPath){
var cellHeight = 100 // Assume this is the height when deptProfile.count = 0
cellHeight = cellHeight + 44 * deptProfile.count
return cellHeight
}
return super.tableView(tableView, heightForRowAtIndexPath: indexPath)
}

UICollectionView - why frame label not work In the first and second cell - swift

my code:
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
cell = collectionView.dequeueReusableCellWithReuseIdentifier("Cell", forIndexPath: indexPath) as? GuideGalleryCell
cell!.configureCell(listImages[indexPath.row])
return cell!
}
the code - func configureCell:
func configureCell(_imageText:ImageText){
imageText = _imageText
image = System.retrieveImage(imageText.nvImage, fromCity: System.instance().currentOrder.packageName)
imageView.image = image
// if let text = imageText.nvText{
lblTitle.text = imageText.nvText
var s:NSString=imageText.nvText
var frame = self.viewLblTitle.frame
frame.origin.y = self.bounds.size.height
self.viewLblTitle.frame = frame
var frmageImage = image.size
if(!(s.isEqualToString("")))
{
UIView.animateWithDuration(0.7, animations: { () -> Void in
if self.image.size.height > self.image.size.width{
var newY = (self.image.size.height - self.viewLblTitle.frame.size.height)
var frame = self.viewLblTitle.frame
frame.origin.y = newY
self.viewLblTitle.frame = frame
}else{
var t = (self.bounds.size.height - 64 - self.image.size.height)/2
var newY = self.image.size.height - self.viewLblTitle.frame.size.height + t
println(newY)
var frame = self.viewLblTitle.frame
frame.origin.y = newY
self.viewLblTitle.frame = frame
}
})
}
}
the frame of the viewLblTitle does not work the first and second cell only following cells it works, why?
What could it be?
When I Come back into the second and first cells it has been working well,
weird, does not it?
Thank watches!
Now it works!
I added:
dispatch_async(dispatch_get_main_queue())
Before calling the function configureCell
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell:GuideGalleryCell = collectionView.dequeueReusableCellWithReuseIdentifier("Cell", forIndexPath: indexPath) as! GuideGalleryCell
dispatch_async(dispatch_get_main_queue()) {
cell.configureCell(self.listImages[indexPath.row])
}
return cell
}
Now it works good!!! :)

Adding margin top to rows in tableView

How can I add margin top to rows in tableView? Now I have:
Can I add space between rows?
My code is:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! UITableViewCell
cell.imageView?.contentMode = .ScaleAspectFit
cell.imageView?.clipsToBounds = true
cell.imageView?.image = UIImage(data: data!)
cell.textLabel?.text = postTitle[indexPath.row]
cell.imageView?.layer.cornerRadius = 39
cell.imageView?.layer.masksToBounds = true;
return cell
}
I did try this line of code, but nothing:
cell.imageView.frame = CGRectOffset(cell.frame, 10, 10);
try this code for spacing between cells:
func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 10; // space b/w cells
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return postTitle.count // count of items
}
func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let header = UIView()
let imageName = "Divider.png"
let image = UIImage(named: imageName)
let imageView = UIImageView(image: image!)
imageView.frame = CGRect(x: 0, y: 0, width: self.view.bounds.size.width, height: 1)
header.addSubview(imageView)
header.backgroundColor = UIColor.clearColor()
return header
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
Here is divider image for you.