getting the height of the custom cell in UITableViewCell - ios

I'm creating a bubble chat like application. I created custom functions for the receiving and sending bubble chats.
After creating them, I've added them into the cells that I've created using the UITableView.
However, I am not able to set the height of the cell, depending on the height of the custom cell itself.
For example, some text passed in could be longer than the one before.
Thus I can't seem to set each cell according to the custom bubble chat height.
Please help!
This are my tableview functions
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arrMsg.count
}
// second
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 100
}
// lastly created
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for:indexPath)
if arrMsg[indexPath.row]["type"] as! String == "outgoing" {
cell.contentView.addSubview(createOutGoingBubble(msg: arrMsg[indexPath.row]["message"] as! String))
}
if arrMsg[indexPath.row]["type"] as! String == "incoming" {
cell.contentView.addSubview(createIncomingBubble(mymsg: arrMsg[indexPath.row]["message"] as! String))
}
return cell
}
This is how it looks currently
How do I set the height of the cell according to the custom bubble created inside the heightforrowat function?
Probably using the line to find the height and return it:
arrMsg[indexPath.row]["message"] as! String == "outgoing"
**This is my function to create the custom bubble chats to be added into the tableviewcell
func createOutGoingBubble(msg:String) -> UIView {
let subV = UIView(frame: CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.height))
let label = UILabel()
label.numberOfLines = 0
label.font = UIFont.systemFont(ofSize: 18)
label.textColor = .white
label.text = msg
let constraintRect = CGSize(width: 0.66 * view.frame.width,
height: .greatestFiniteMagnitude)
let boundingBox = msg.boundingRect(with: constraintRect,
options: .usesLineFragmentOrigin,
attributes: [.font: label.font],
context: nil)
label.frame.size = CGSize(width: ceil(boundingBox.width),
height: ceil(boundingBox.height))
let bubbleSize = CGSize(width: label.frame.width + 28,
height: label.frame.height + 20)
let outgoingMessageView = UIImageView(frame:
CGRect(x: view.frame.width - bubbleSize.width - 20,
y: bubbleSize.height - 25,
width: bubbleSize.width,
height: bubbleSize.height))
let bubbleImage = UIImage(named: "outgoing")?
.resizableImage(withCapInsets: UIEdgeInsets(top: 17, left: 21, bottom: 17, right: 21),
resizingMode: .stretch)
.withRenderingMode(UIImage.RenderingMode.alwaysTemplate)
outgoingMessageView.image = bubbleImage
outgoingMessageView.tintColor = UIColor(red: 0.40 , green: 0.71, blue: 1.00, alpha: 1)
subV.addSubview(outgoingMessageView)
label.center = outgoingMessageView.center
subV.addSubview(label)
return subV
}
Thanks in advance!

You can use Autolayout for the same and get free from all the coding part. Just set the constraint of the inner view in association with the cell and then right the following code.
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell:ChatSenderTableViewCell = (tableView.dequeueReusableCell(withIdentifier: "ChatSenderTableViewCell", for: indexPath) as? ChatSenderTableViewCell)!
cell.LabelChatMessage.text = "Your Message"
cell.LabelChatMessage.numberOfLines = 0
cell.LabelChatMessage.sizeToFit()
return cell
}
I am using a custom cell name ChatSenderTableViewCell to create a bubble like effect containing a label for messages send or receive.

Use label inside of view and use margin from top and bottom according to your desire. Also, you need to make 0 number of lines in UIlabel. you can do it by using label.numberoflines = 0.
Also, you need to add the following code to change the height of the row according to the text inside it.
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}

You can try this:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
guard let cell = tableView.cellForRow(at: indexPath) else { return 0 }
return cell.intrinsicContentSize.height
}
The intrinsicContentSize is the natural size for the receiving view, considering only properties of the view itself.

Related

Auto adjust font size for UITableView

For one of my UITableView, to allow more text or large font size text to fit in the fields, I need to add or adjust font size.
I used a boolean for adjustsFontSizeToFitWidth. And clipsToBounds=true. But this does not always work for me, not sure why it's inconsistent, especially when you have bigger font size text to be included. Any correction?
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView = UIView()
let headerLabel = UILabel(frame: CGRect(x: 40, y: 0, width:
tableView.bounds.size.width, height: tableView.bounds.size.height))
headerLabel.textColor = UIColor.white
headerLabel.text = self.tableView(self.tableView, titleForHeaderInSection: section)
headerLabel.sizeToFit()
headerLabel.adjustsFontSizeToFitWidth = true
headerLabel.clipsToBounds=true
headerLabel.numberOfLines=0
headerLabel.lineBreakMode = NSLineBreakMode.byTruncatingTail
headerLabel.minimumScaleFactor = 0.2
headerView.addSubview(headerLabel)
return headerView
}
Delete the following may be?
headerLabel.sizeToFit()
This will allow to make 
adjustsFontSizeToFitWidth
 property working.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell")
if searching {
cell?.textLabel?.text = searchedLabour[indexPath.row]
cell?.textLabel?.sizeToFit()
cell?.textLabel?.adjustsFontSizeToFitWidth = true
cell?.textLabel?.numberOfLines = 2
cell?.textLabel?.lineBreakMode = NSLineBreakMode.byTruncatingTail
} else {
cell?.textLabel?.text = labourWordsArray[indexPath.row]
cell?.textLabel?.sizeToFit()
cell?.textLabel?.adjustsFontSizeToFitWidth = true
cell?.textLabel?.numberOfLines = 2
cell?.textLabel?.lineBreakMode = NSLineBreakMode.byTruncatingTail
}
return cell!
}

UITableViewCell from Xib, cell hight and cell selection area

I have a UITableViewController, which has a custom cell that I want to display an image and labels. screenshots can explain my problem very well, it looks like this
.
And when I select any cell it looks like
In tableviewcontroller cell is not visible in proper shape according to constraints
here is my custom cell with autolayout constraints
How I can fix this issue? ... I created this tableviewcontroller programmatically without using storyboard.
here is code sample of data source and delegates of tableviewcontroller
override func numberOfSections(in tableView: UITableView) -> Int {
var numOfSections: Int = 0
let count = conversations.count
if count > 0 {
// tableView.separatorStyle = .none
numOfSections = 1
tableView.backgroundView = nil
}
else
{
let frame = CGRect(x: 0,
y: 0,
width: tableView.bounds.size.width,
height: tableView.bounds.size.height)
let noDataLabel: UILabel = UILabel(frame: frame)
noDataLabel.text = "You don't have any messages. 🙃"
noDataLabel.textColor = UIColor.black
noDataLabel.textAlignment = .center
tableView.backgroundView = noDataLabel
tableView.separatorStyle = .none
}
return numOfSections
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return conversations.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "inboxCell", for: indexPath) as! InboxCell
cell.conversation = conversations[indexPath.row]
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let uids = conversations[indexPath.row].conversationUseruids
for uid in uids{
if uid == Account.account.user.uid{
}
else{
User.getUser(with: uid, completion: { (user) in
self.selectedUser.append(user!)
})
}
}
tableView.deselectRow(at: indexPath, animated: true)
let index = indexPath.row as Int
messageVC.conversationIndex = index
messageVC.conversation = self.conversations[index]
navigationController?.pushViewController(messageVC, animated: true)
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 80
}
it happen because your image not have upper lower constraint if not working than let me know

How to make multiple level sections in UITableView in Swift 4

How to make nested table (multiple level sections) in swift 4 like the below picture:
A UITableView is designed to show just two levels (sections and rows), but I want to display more than two levels.
Basic Section and Row.
var titleString = [0 : "Bat and Ball", 1 : "Hockey"]
var rowString = [0: ["Baseball", "Softball", "Cricket"], 1: ["Field Hockey", "Ice Hockey", "Roller Hockey"]]
func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return (rowString[section]?.count)!
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! SOTableViewCell
cell.testLbl.text = rowString[indexPath.section]?[indexPath.row]
cell.selectionStyle = .none
return cell
}
// Uncomment for Default design and comment viewForHeaderInSection method
//func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
//return titleString[section]
//}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let sectionView = UIView(frame: CGRect(x: 0, y: 0, width: tableView.frame.size.width, height: 25))
sectionView.backgroundColor = UIColor.magenta
let sectionName = UILabel(frame: CGRect(x: 5, y: 0, width: tableView.frame.size.width, height: 25))
sectionName.text = titleString[section]
sectionName.textColor = UIColor.white
sectionName.font = UIFont.systemFont(ofSize: 14)
sectionName.textAlignment = .left
sectionView.addSubview(sectionName)
return sectionView
}

how to adjust uilabel and uitableviewcell height programmatically?

I know that adjusting UILabel height and UITableViewCell is probably a pretty standard issue, but I'm finding lots of answers that are based on the storyboard and inspectors, but not by just using Swift 3. I've created a table which covers the screen. The height for the cell is being determined as follows:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
My tableViewCell has a couple of objects in it, a UIImageView (myImage) and a UILabel (myText), set-up in a custom class. The positioning and sizing takes place in cellForRowAt.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! CustomCell
cell.myImage.image = UIImage(named: "MyImage")
cell.myImage.layer.frame = CGRect(origin: CGPoint(x: 0, y: 10), size: (cell.myImage?.image?.size)!)
cell.myText.text = myArray[indexPath.row]
cell.myText.frame = CGRect(x: UIScreen.main.bounds.size.width * 0.25, y: 0, width: UIScreen.main.bounds.size.width * 0.7, height: 90)
cell.myText.numberOfLines = 0
return cell
}
The result is a bunch of stacked cells, overlapping each other. What should I do to adjust the height of the UILabel frame to the amount of text coming from myArray and adjust the cell height so that it's at least the height of myImage or myText?
You can make multiline label inside table view in Swift 3.
import UIKit
private let useAutosizingCells = true
class TableViewController: UITableViewController {
fileprivate let cellIdentifier = "Cell"
// MARK: - Lifecycle
override func viewDidLoad() {
super.viewDidLoad()
//setup initial row height here
if useAutosizingCells && tableView.responds(to: #selector(getter: UIView.layoutMargins)) {
tableView.estimatedRowHeight = 44.0
tableView.rowHeight = UITableViewAutomaticDimension
}
}
// MARK: - UITableViewDataSource
extension TableViewController {
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return detailsModel.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath)
let details = detailsModel[indexPath.row]
cell.textLabel?.text = details.title
cell.detailTextLabel?.text = details.description
if useAutosizingCells && tableView.responds(to: #selector(getter: UIView.layoutMargins)) {
cell.textLabel?.numberOfLines = 0
cell.detailTextLabel?.numberOfLines = 0
}
return cell
}
}

UITableView - I want to display blank cell

I set up my tableView and has two springVar as shown in the image below. I want my tableview to show empty cells after the two springVar so that my solve bar is at the bottom of the screen. Any advices on how to go about it? My code is below.
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return springVar.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cellIdentifier = "Cell"
var cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier) as? UITableViewCell
if cell == nil {
cell = UITableViewCell(style: UITableViewCellStyle.Value2, reuseIdentifier: cellIdentifier)
}
cell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "cell")
var data : NSManagedObject = springVar[indexPath.row] as! NSManagedObject
cell!.textLabel!.text = "Spring \(indexPath.row + 1)"
var force : Float = data.valueForKey("force") as! Float
var stiffness : Float = data.valueForKey("stiffness") as! Float
cell!.detailTextLabel!.text = "Force =\(force) \t Stiffness =\(stiffness)"
cell!.detailTextLabel!.textColor = UIColor .darkGrayColor()
return cell!
}
i think this maybe helpfull
if indexPAth.row / 2 == 0
{
return UITableViewCell()
// u can customize ur cell to show a button or anything else
}
this show a custom/blank cell after each 2 cell,(odd)
You can add Footer view in your tableView this way:
override func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
let footerView = UIView(frame: CGRectMake(0, 0, tableView.frame.size.width, 40))
footerView.backgroundColor = UIColor.whiteColor()
//add button in your footer view
var button = UIButton(frame: CGRectMake(0, 0, 75, 30))
button.setTitle("Solve", forState: UIControlState.Normal)
button.setTitleColor(UIColor.brownColor(), forState: UIControlState.Normal)
button.addTarget(self, action: "buttonTapAction:", forControlEvents: UIControlEvents.TouchUpInside)
footerView.addSubview(button)
return footerView
}
override func tableView(tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return 40.0
}
And your result will be:
You can adjust the footerHeight according to your own needs.
override func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
let footerHeight : CGFloat = (tableView.frame.size.height - (CGFloat(springVar.count) * 45.0) - 45.0 - 64.0)
let oneCell = UIView(frame: CGRect(x: 0, y: 0, width: tableView.frame.size.width, height: footerHeight))
return oneCell
}
override func tableView(tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
let footerHeight : CGFloat = (tableView.frame.size.height - (CGFloat(springVar.count) * 45.0) - 45.0 - 64.0)
return footerHeight
}

Resources