Adjusting font size of UITableViewCell based on the device size - swift

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.

Related

Fix sidemenu bar logo display in swift

the swift code below allows you to view a side menu my problem is this, the first element of the menu is an image (attached) now the problem lies in the fact that in the image there is a space to the left of the screen, what I want to do is remove the space so that the image is flush with the screen, and bring the top image flush with the iPhone, the result I want to obtain is the one in figure 2, as I do this?
Swift Code:
protocol MenuControllerDelegate {
func didSelectMenuItem(named: SideMenuItem)
}
enum SideMenuItem: String, CaseIterable {
//DA NASCONDERE PRIMA VOCE MENU - FUNZIONALE PER BANNER HOMEPAGE
case header = "Sito Web SynergyO2"
//BLOCCO 1 - INTRO
case home = "SynergyO2 - SO2 Business"
//BLOCCO 2 - SCOPRI SYNERGY O2
case sito = "Sito SynergyO2"
case prodotti = "Prodotti"
case blog = "Blog"
//BLOCCO 3 - SCOPRI SO2BUSINESS
case sitob = "Sito SO2 Business"
case entra = "Entra nel Team"
case blogb = "Business Blog"
//BLOCCO 4 - STRUMENTI BUSINESS
case bo = "Back Office"
case business = "Sponsor Link"
//BLOCCO 5 - CONTATTI
case webinar = "Webinar"
case circolari = "Circolari e Comunicazioni"
case domande = "Fai una Domanda!"
case seguici = "Seguici su"
}
class MenuController: UITableViewController {
public var delegate: MenuControllerDelegate?
private let menuItems: [SideMenuItem]
private let color = UIColor(red: 33 / 255.0, green: 33 / 255.0, blue: 33 / 255.0, alpha: 1)
init(with menuItems: [SideMenuItem]) {
self.menuItems = menuItems
super.init(nibName: nil, bundle: nil)
tableView.register(UITableViewCell.self,
forCellReuseIdentifier: "cell")
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
tableView.backgroundColor = UIColor.white
view.backgroundColor = UIColor.white
}
// MENU
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return menuItems.count
}
//Recupero immagine da titolo
func getimage(titolo: String) -> UIImage {
var image: UIImage
switch titolo {
case "Scopri SynergyO2":
image = UIImage(named: "sito")!
case "Webinar":
image = UIImage(named: "webinar")!
case "Blog":
image = UIImage(named: "blog")!
case "Seguici su":
image = UIImage(named: "seguici")!
case "Fai una Domanda!":
image = UIImage(named: "domanda")!
case "Back Office":
image = UIImage(named: "backoffice")!
case "Circolari e Comunicazioni":
image = UIImage(named: "circolari")!
case "Area Business":
image = UIImage(named: "area")!
default:
image = UIImage(named: "prodotti")!
}
return image
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = menuItems[indexPath.row].rawValue
cell.textLabel?.textColor = .black
cell.textLabel?.font = UIFont.systemFont(ofSize: 13.0)
cell.backgroundColor = UIColor.white
cell.contentView.backgroundColor = UIColor.white
cell.imageView!.image = getimage(titolo: menuItems[indexPath.row].rawValue)
if menuItems[indexPath.row].rawValue == "Sito Web SynergyO2" {
cell.separatorInset = UIEdgeInsets.zero
cell.layoutMargins = UIEdgeInsets.zero
cell.preservesSuperviewLayoutMargins = false
cell.frame = CGRect(x: 0, y: 0, width: 1600, height: 200)
cell.contentView.backgroundColor = .white
let imageName = "menulogo.png"
let image = UIImage(named: imageName)
cell.imageView?.image = image
}
return cell
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath.row == 0 {
return 115
} else {
return 50
}
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
let selectedItem = menuItems[indexPath.row]
delegate?.didSelectMenuItem(named: selectedItem)
}
}
Have you tried to:
set self.automaticallyAdjustsScrollViewInsets = false on the table view controller? (i think it is deprecated and there is an alternaive call tho)
switch the table view to grouped/plain

Autosize for cell in UICollectionViewCell

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
}

Swift dynamic tableview in proportion to label height filled with text

Hello I'm trying to make the table view with custom cell. The main goal of making it is that I resize the height of tableview cell in proportion to label height which is changed by the size of text. when I run my app with below code, it looks go well. However getStringHeight methods sometimes don't recognize the line of the cell. Even if the number of line is just one, that method allocates the two line of cell which makes the cell unnecessary space.
I think the if it would recognizes two lines, line is over 3/4 filled with text in one line. I think I use Korean font included in the Apple SD Gothic (Family). But I can enter the exact name into UIFont(name: "", size: ) because it doesn't recognize it.
Can you help me? it's so important project. I stayed up all night but I haven't come up with idea to fix this problems.
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat
{
let rowNum = downloadedContents!.count - indexPath.row - 1
let sizeFactory = UINib(nibName: "DownLoadPlayViewControllerCell", bundle: nil).instantiateWithOwner(nil, options: nil)[0] as? DownLoadPlayViewControllerCell
sizeFactory!.frame.size.height = 300
var bounds = CGSize(width: tableView.bounds.width, height: 78.5)
let pod = self.pods[rowNum]
if(sizeFactory != nil)
{
let top = sizeFactory?.programLabel.frame
let bottom = sizeFactory?.dateFilesizeLabel.frame
var labelSize = getStringHeight(pod.contentTitle!, fontSize: 13.0, width: sizeFactory!.titleLabel.frame.width)
let totalCellHeight = labelSize + top!.height + bottom!.height + 28.0
bounds.height = totalCellHeight
}
return bounds.height
}
func getStringHeight(mytext: String, fontSize: CGFloat, width: CGFloat) -> CGFloat
{
let font = UIFont(name: "Apple SD Gothic Neo", size: fontSize)
let size = CGSizeMake(width,CGFloat.max)
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineBreakMode = .ByWordWrapping;
let attributes = [NSFontAttributeName:font! as UIFont,
NSParagraphStyleAttributeName:paragraphStyle.copy()]
let text = mytext as NSString
let rect = text.boundingRectWithSize(size, options:.UsesLineFragmentOrigin, attributes: attributes, context:nil)
return rect.size.height
}
I may suggest that you use:
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 60
This will autosize the height of the cell without looking for the height of the text.
You can put these two lines on viewDidLoad as for the estimated row height, it helps you out in rendering.
Try this code:
Note: Both method should work.Tested in Swift 3.
Method 1:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
tableView.estimatedRowHeight = 44.0 // standard tableViewCell height
tableView.rowHeight = UITableViewAutomaticDimension
return yourArrayName.count
}
Method 2:
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
override func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
Note: You may need to put this code inside your cellForRowAt
yourCellName.sizeToFit()

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)
}