sizeToFit() not working properly with attributedText - ios

Here is my cellForRowAtIndexPath
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
//cell init
//set values to cell property
let str2 = NSString(format: "%#", (displayArray[indexPath.row].valueForKey("username") as? String)!)
let attrStr2 = NSMutableAttributedString(string: str2 as String)
attrStr2.addAttribute(NSFontAttributeName, value:UIFont(name: "HelveticaNeue-Bold", size: 12)!, range: NSMakeRange(0, str2.length ))
topCell.username.attributedText = attrStr2
topCell.username.sizeToFit()
topCell.title.backgroundColor = UIColor.redColor()
topCell.username.backgroundColor = UIColor.yellowColor()
//some calculation which is not affecting username.frame.size.width
return topCell;
}
and here is my tableView
You can see label with yellow background,
And yes, autolayout is disable, so I think my code is fine but not working as expected.
Please help me to solve this issue.
Thanks in advance

Related

Swift: How do I achieve adding a background color to a tableView textLabel [duplicate]

This question already has answers here:
How to set background color to UILabel text only
(8 answers)
Closed 3 years ago.
I'm working with TableView and I was hoping to add a background colour to a selected cell's text. Something like this:
The image represents a cell, the background color is separated. This is what is needed.
I tried doing the following but it adds a background colour to the entire cell or to the text only.
The separation between is the most important, adding a backgroundColor applys a color to the entire cell, which is not wanted.
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { //Highlighting text - Add saving text
let cell = tableView.cellForRow(at: indexPath)
print("You selected cell number: \(indexPath.row)!")
cell?.textLabel?.textColor = .yellow
cell?.textLabel?.backgroundColor = .yellow // Is not desired outcome
}
Your image shows a textlabel with yellow background colour and black text colour.
If you are trying to change the background colour, it should be
cell?.textLabel?.backgroundColor = UIColor.yellow
cell?.textLabel?.textColor = UIColor.yellow is used to change the text colour and not the background colour.
( https://www.youtube.com/watch?v=DCc5MKKpfUA . This will help you)
let searchString = "Lorem Lorem"
let baseString = "Ipsum Ipsum Ipsum Ipsum Ipsum Ipsum Ipsum Ipsum"
let attributed = NSMutableAttributedString(string: baseString)
do
{
let regex = try! NSRegularExpression(pattern: searchString,options: .caseInsensitive)
for match in regex.matches(in: baseString, options: NSRegularExpression.MatchingOptions(), range: NSRange(location: 0, length: baseString.characters.count)) as [NSTextCheckingResult] {
attributed.addAttribute(NSBackgroundColorAttributeName, value: UIColor.yellow, range: match.range)
}
self.txtView.attributedText = attributed
}
Modify the below code to use as per your requirement
cell?.textLabel?.attributedText = self.decorateText(myTxtOne: "Use this", myTxtTwo: " Code")
func decorateText(myTxtOne:String, myTxtTwo:String)->NSAttributedString{
let textAttributeOne = [NSAttributedStringKey.foregroundColor: UIColor.white, NSAttributedStringKey.backgroundColor: UIColor.blue, NSAttributedStringKey.font: UIFont(name: "Poppins-Regular", size: 12.0)!] as [NSAttributedStringKey : Any]
let textAttributeTwo = [NSAttributedStringKey.foregroundColor: UIColor.white, NSAttributedStringKey.backgroundColor: UIColor.yellow, NSAttributedStringKey.font: UIFont(name: "Poppins-Regular", size: 12.0)!] as [NSAttributedStringKey : Any]
let textPartOne = NSMutableAttributedString(string: myTxtOne, attributes: textAttributeOne)
let textPartTwo = NSMutableAttributedString(string: myTxtTwo, attributes: textAttributeTwo)
let textCombination = NSMutableAttributedString()
textCombination.append(textPartOne)
textCombination.append(textPartTwo)
return textCombination
}
TheTiger user is correct. All you need to learn is setting your label's attributedText. I've worked on tons of Bible applications with same highlighting verse feature.
From what I can remember, the attribute name is: NSBackgroundColorAttributeName. Good luck!
First you have to add a global variable for identify which cell is selected.
var selectedIndex = -1
And update the value according to selected row
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { //Highlighting text - Add saving text
self.selectedIndex = indexPath.row
tabeview.reoadData()
}
and write the cellForRow as,
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
var cell= (tableView.dequeueReusableCell(withIdentifier: "cellIdentifier") as! YourCell)
if self.selectedIndex == indexPath.row
{
cell?.textLabel?.backgroundColor = UIColor.yellow
}
else
{
cell?.textLabel?.backgroundColor = UIColor.yellow
}
return cell!
}

Bug with UITextField inside UITableViewCell

I have a problem with some TextField inside a UITableViewCell; i got two textfield inside of the table cell, when I tap on the the textField everything works fine as you can see in this two screenshots
1.
The number in red squares are my UITextField, when I tap on one of them it works fine
But when i click on the other textField the entire cell disappear like this
I have an empty space after the click on the other textfield
I have no function implemented, only a function that change font and textColor
func setPickers() {
self.hourPicker.delegate = self
self.minutePicker.delegate = self
hourPicker.textColor = theme.grey
minutePicker.textColor = theme.grey
hourPicker.background = UIImage()
minutePicker.background = UIImage()
hourPicker.textAlignment = .center
minutePicker.textAlignment = .center
hourPicker.font = UIFont(name: "Roboto-Regular", size: 48)
minutePicker.font = UIFont(name: "Roboto-Regular", size: 48)
}
This the cell in my storyboard
EDIT 2
Look my graphic debug what shows before the bug
And after it
The cell is called EventDetailFooterTableViewCell
EDIT 3
Here is where I initialize the cellView for the footer
func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
let cell = tableView.dequeueReusableCell(withIdentifier: "footerCell") as! EventDetailFooterTableViewCell
cell.event = self.event
cell.delegate = self
cell.setView()
cell.backgroundColor = theme.mainColor
return cell
}
func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
var height: CGFloat = 180.0
var calendar = NSCalendar.current
calendar.timeZone = TimeZone(abbreviation: "UTC")! //OR NSTimeZone.localTimeZone()
let dateAtMidnight = calendar.startOfDay(for: Date())
let todayLong = dateAtMidnight.millisecondsSince1970
if let eventDay = event.dateTime?.millisecondsSince1970 {
if eventDay >= todayLong {
height = 280
}
}
return height
}
I see a problem. You are using regular cell as section footer and there is why you see unpredictable behaviour. You should use UITableViewHeaderFooterView instead. It is if you really need such design. Better solution will be to remove footer and make it cell instead.

UITableView Custom Cell Overlapping in ios10 with Swift3

I am making UITableView custom cell because height also changed per cell.
This is my code for initialize cell and after that i want to add UITextView as Subview.
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
{
let dictAd = self.arrAllQuestions[indexPath.row] as! NSDictionary
let fontNew = UIFont(name: "AvenirNext-Regular", size: 19.0)
let strA = "\(indexPath.row+1). \(dictAd.object(forKey: "Title")!)"
let heightTitle = self.heightForView(text: strA, font: fontNew!, width: tableView.frame.size.width-16)
return heightTitle+5;
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let dictAd = self.arrAllQuestions[indexPath.row] as! NSDictionary
let cell = tableView.dequeueReusableCell(withIdentifier: "quesionCell", for: indexPath) as! QuestionCell
let fontNew = UIFont(name: "AvenirNext-Regular", size: 19.0)
let strA = "\(indexPath.row+1). \(dictAd.object(forKey: "Title")!)"
cell.lblName.font = fontNew
cell.lblName.text = strA
cell.lblName.numberOfLines = 0
let heightTitle = self.heightForView(text: strA, font: fontNew!, width: tableView.frame.size.width-16)
var frame = cell.lblName.frame as CGRect
frame.size.height = heightTitle; //you need to adjust this value
cell.lblName.frame = frame;
let txtView = AnimatableTextView(frame: CGRect(x: 8, y: cell.lblName.frame.origin.y+cell.lblName.frame.size.height+5, width: tableView.frame.size.width-16, height: 25))
txtView.borderWidth = 1.0
txtView.borderColor = UIColor.lightGray
txtView.cornerRadius = 4.0
cell.contentView.addSubview(txtView)
return cell
}
You can see output below.
It seems that the height calculation in your heightForRowAtIndexPath is not proper. Consider using self-sizing cells using UITableViewAutomaticDimension and Autolayout to solve your issues. Here is a great tutorial that can help you to get started. One more suggestion if you are using UITextView or subclass of the same in a cell and you want it to take the height of the content set its scrollable property to false.
Declare this in the viewDidLoad
Hope this will help you
tableView.estimatedRowHeight = 44

Dynamic tableView Cell height swift IOS8

I'm trying to create tableView which is suppose to auto resize the height according to the messageLabel. IOS8 has made this a lot of easier, however i can't seem to achieve this. So far i've created tableViewCell custom class with a xib file looking like below:
and then set the messageLabel.numberOfLines = 0
in the viewController i've set following in viewDidLoad
tableView.estimatedRowHeight = 80.0
tableView.rowHeight = UITableViewAutomaticDimension
and in the end the delegate methods
func tableView(tableView:UITableView, numberOfRowsInSection section:Int)->Int
{
return 1
}
func numberOfSectionsInTableView(tableView:UITableView)->Int
{
return 1
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
var cell = tableView.dequeueReusableCellWithIdentifier("TwitterPlainCell", forIndexPath: indexPath) as! TwitterPlainCell
let url = NSURL(string: "https://pbs.twimg.com/profile_images/507493048062713856/KaWKfdgW.jpeg")
let data = NSData(contentsOfURL: url!) //make sure your image in this url does exist, otherwise unwrap in a if let check
cell.selectionStyle = UITableViewCellSelectionStyle.None
// cell.backgroundColor = UIColor(rgba: "#f6f7f9")
var name = "Olof Kajbjer"
var userName = "#olofmCS"
var topText = "\(name) \(userName)"
var topCount = count(topText)
var userCount = count(userName)
var userNameLocation = topCount - userCount
cell.profileImage.image = UIImage(data: data!)
cell.dateLabel.text = "55m"
var myMutableString = NSMutableAttributedString(string: topText, attributes: [NSFontAttributeName:UIFont(name: "PT Sans", size: 18.0)!])
myMutableString.addAttribute(NSForegroundColorAttributeName, value: UIColor(rgba: "#A6B0B5"), range: NSRange(location:userNameLocation,length:count(userName)))
myMutableString.addAttribute(NSFontAttributeName, value: UIFont(name: "PT Sans", size: 13)!, range: NSRange(location:userNameLocation,length:count(userName)))
// set label Attribute
cell.topLabel.attributedText = myMutableString
cell.messageLabel.text = "I FUCKING LOST AGAINST #olofmCS ON AIM AWP IN OVERTIME... GGgg"
cell.setNeedsUpdateConstraints()
cell.updateConstraintsIfNeeded()
return cell
}
The result of this can seen below, why is it not resizing the cell height?
The issue was related to the bottom constraint i had to set it to >= or another value

Expand label/cell size based on text size in UITableView Swift

I am new to iOS development. I have a problem with my cell sizing. I am not using Auto-Laylout feature. My current TableView cell looks something like this. I want to make the label size which is selected in the image to be extended dynamically based on the text content of that Label.
Thanks in advance.
i think the swift version like below, it calculates nearer values not the exact height, for example
class ViewController: UIViewController,UITableViewDataSource,UITableViewDelegate {
var messageArray:[String] = []
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
messageArray = ["One of the most interesting features of Newsstand is that once an asset downloading has started it will continue even if the application is suspended (that is: not running but still in memory) or it is terminated. Of course during while your app is suspended it will not receive any status update but it will be woken up in the background",
"In case that app has been terminated while downloading was in progress, the situation is different. Infact in the event of a finished downloading the app can not be simply woken up and the connection delegate finish download method called, as when an app is terminated its App delegate object doesn’t exist anymore. In such case the system will relaunch the app in the background.",
" If defined, this key will contain the array of all asset identifiers that caused the launch. From my tests it doesn’t seem this check is really required if you reconnect the pending downloading as explained in the next paragraph.",
"Whale&W",
"Rcokey",
"Punch",
"See & Dive"]
}
in the above we have an array which contains string of different length
func numberOfSectionsInTableView(tableView: UITableView) -> Int
{
return 1;
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return messageArray.count;
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
var cell:UITableViewCell? = tableView.dequeueReusableCellWithIdentifier("CELL") as? UITableViewCell;
if(cell == nil)
{
cell = UITableViewCell(style:UITableViewCellStyle.default, reuseIdentifier: "CELL")
cell?.selectionStyle = UITableViewCellSelectionStyle.none
}
cell?.textLabel.font = UIFont.systemFontOfSize(15.0)
cell?.textLabel.sizeToFit()
cell?.textLabel.text = messageArray[indexPath.row]
cell?.textLabel.numberOfLines = 0
return cell!;
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat
{
var height:CGFloat = self.calculateHeightForString(messageArray[indexPath.row])
return height + 70.0
}
func calculateHeight(inString:String) -> CGFloat
{
let messageString = inString
let attributes : [String : Any] = [NSFontAttributeName : UIFont.systemFont(ofSize: 15.0)]
let attributedString : NSAttributedString = NSAttributedString(string: messageString, attributes: attributes)
let rect : CGRect = attributedString.boundingRect(with: CGSize(width: 222.0, height: CGFloat.greatestFiniteMagnitude), options: .usesLineFragmentOrigin, context: nil)
let requredSize:CGRect = rect
return requredSize.height
}
try it in a new project just add the tableview and set its datasource and delegate and past the code above and run
the result will be like below
Try to override methods:
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
override func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
Complete solution:
In iOS 8, Apple introduces a new feature for UITableView known as Self Sizing Cells. Prior to iOS 8, if you displayed dynamic content in table view with varied row, you need to calculate the row height on your own.
In summary, here are the steps to implement when using self sizing cells:
• Add auto layout constraints in your prototype cell
• Specify the estimatedRowHeight of your table view
• Set the rowHeight of your table view to UITableViewAutomaticDimension
Expressing last two points in code, its look like:
tableView.estimatedRowHeight = 43.0;
tableView.rowHeight = UITableViewAutomaticDimension
You should add it in viewDidLoad method.
With just two lines of code, you instruct the table view to calculate the cell’s size matching its content and render it dynamically. This self sizing cell feature should save you tons of code and time.
In Attributes Inspector of your UILabel, change Lines value to 0, so label will automatically adjust the number of lines to fit the content.
Please note that first point is required and remember that you cannot use self sizing cell without applying auto layout.
If you are note familiar with auto layout, please read this, it will be enough:
https://developer.apple.com/library/mac/recipes/xcode_help-IB_auto_layout/chapters/pin-constraints.html
Or, easier way to set auto layout, but maybe not be what you exactly expected is to clear all of your constraints, go to Resolve Auto Layout Issues and for All Views click on Reset to Suggested Constraints.
Just add this in Viewdidload
tableView.estimatedRowHeight = 44.0
tableView.rowHeight = UITableViewAutomaticDimension
func calculateHeight(inString:String) -> CGFloat
{
let messageString = inString
let attributes : [NSAttributedString.Key : Any] = [NSAttributedString.Key(rawValue:
NSAttributedString.Key.font.rawValue) : UIFont.systemFont(ofSize:
15.0)]
let attributedString : NSAttributedString = NSAttributedString(string: messageString, attributes: attributes)
let rect : CGRect = attributedString.boundingRect(with: CGSize(width: 222.0, height: CGFloat.greatestFiniteMagnitude),
options: .usesLineFragmentOrigin, context: nil)
let requredSize:CGRect = rect
return requredSize.height
}

Resources