expand and contract label not working in UITableViewCell - ios

I am trying to use a UITableView and have cell contents which will expand or contract when the user clicks on the label.
However, the behavior I'm seeing is that the cell will contract (e.g. I am changing the label's numberOfLines from 0 to 1, and then the label will contract). However, when I change the label's numberOfLines from 1 to 0 it doesn't expand.
I put together a simple test program to show the issue I'm having.
I'm using a UITapGestureRecognizer to handle the tap event for the label, and that is where I expand or contract the label. Does anyone have any idea what I'm doing wrong?
Here's my storyboard and view controller code.
import UIKit
class MyCell : UITableViewCell {
#IBOutlet weak var myLabel: UILabel!
}
class TableViewController: UITableViewController {
let cellID = "cell"
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.estimatedRowHeight = 75
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 12
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return "section " + String(section)
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return 4
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: self.cellID, for: indexPath) as! MyCell
cell.myLabel.isUserInteractionEnabled = true
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.handleCellTapped(_:)))
cell.myLabel!.addGestureRecognizer(tapGesture)
// Configure the cell...
if indexPath.row % 2 == 0 {
cell.myLabel?.numberOfLines = 1
cell.myLabel.text = "This is some long text that should be truncated. It should not span over multiple lines. Let's hope this actually works. \(indexPath.row)"
} else {
cell.myLabel?.numberOfLines = 0
cell.myLabel.text = "This is some really, really long text. It should span over multiple lines. Let's hope this actually works. \(indexPath.row)"
}
return cell
}
#objc func handleCellTapped(_ sender: UITapGestureRecognizer) {
print("Inside handleCellTapped...")
guard let label = (sender.view as? UILabel) else { return }
//label.translatesAutoresizingMaskIntoConstraints = false
// expand or contract the cell accordingly
if label.numberOfLines == 0 {
label.numberOfLines = 1
} else {
label.numberOfLines = 0
}
}
}

Do two things.
Set the Vertical Content hugging priority and
Vertical Content compression resistance priority of the Label to 1000.
After changing the number of lines of the Label call the tableView.beginUpdates() and tableView.endUpdates()
This should work definitely.

You almost get it, but here is a couple of things you should care about.
First, handle the label by UIGestureRecognizer it's quite overhead. For that purposes UITableViewDelegate has own method:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
Second, you're using self-sizing cell, because of
self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.estimatedRowHeight = 75
There is one important rule for that: you should pin myLabel to each side of superview (see official docs why):
Last step, when the numberOfLines changed, you should animate cell's height (expand or collapse) without reloading the cell:
tableView.beginUpdates()
tableView.endUpdates()
Docs:
You can also use this method followed by the endUpdates() method to animate the change in the row heights without reloading the cell.
Full code:
class MyCell: UITableViewCell {
#IBOutlet weak var myLabel: UILabel!
}
class TableViewController: UITableViewController {
let cellID = "cell"
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.estimatedRowHeight = 75
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
return 12
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return "section " + String(section)
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 4
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: self.cellID, for: indexPath) as! MyCell
cell.selectionStyle = .none // remove if you need cell selection
if indexPath.row % 2 == 0 {
cell.myLabel?.numberOfLines = 1
cell.myLabel.text = "This is some long text that should be truncated. It should not span over multiple lines. Let's hope this actually works. \(indexPath.row)"
} else {
cell.myLabel?.numberOfLines = 0
cell.myLabel.text = "This is some really, really long text. It should span over multiple lines. Let's hope this actually works. \(indexPath.row)"
}
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: false)
guard let cell = tableView.cellForRow(at: indexPath) as? MyCell else { return }
cell.myLabel.numberOfLines = cell.myLabel.numberOfLines == 0 ? 1 : 0
tableView.beginUpdates()
tableView.endUpdates()
}
}

Try
tableView.beginUpdates()
if label.numberOfLines == 0 {
label.numberOfLines = 1
} else {
label.numberOfLines = 0
}
tableView.endUpdates()

Related

Why cell is display overflow the table view in Swift

I have fix make the cell to cliptobounds in the table view and also assign constraints to fix the table position and height.
Below are some parts of my code.
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if hiddenRow.contains(indexPath.row) || hiddenRow2.contains(indexPath.row){
rowHeight.append(300)
return 300 //Expanded
}
else{
rowHeight.append(120)
return 120 //Not Expanded
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "med_reusable_cell", for: indexPath as IndexPath) as! MedListTableViewCell
cell.backgroundColor = TRANSPARENT
cell.layer.cornerRadius = DEFAULT_CORNER_RADIUS
active_table_height.constant = self.view.frame.size.height * 11/36
expired_table_height.constant = self.view.frame.size.height * 11/36
cell overflow
The different between my code and others are
This is an expendable view cell which the height will be change based whether the cell is expended
I use a reusable cell for two tables.
How can I solve this?
You can achieve this by adding a header to each cell, then when you'll click it, reload the table view with the opened cell look at this example :
DataModel :
struct DataItem {
var isExpand: Bool
var title: String
var value:String
init(isExpand:Bool = false, title:String, value:String) {
self.isExpand = isExpand
self.title = title
self.value = value
}
}
Custom Header witch will listen to events :
protocol CustomHeaderViewDelegate: AnyObject {
func headerViewTap(_ section: Int)
}
class CustomHeaderView: UITableViewHeaderFooterView {
weak var delegate: CustomHeaderViewDelegate?
var sectionNumber: Int?
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
let gesture = UITapGestureRecognizer(target: self, action: #selector(CustomHeaderView.tableViewSectionTapped(_:)))
self.addGestureRecognizer(gesture)
}
#objc func tableViewSectionTapped(_ gesture: UIGestureRecognizer) {
if let sectionNumber = sectionNumber{
delegate?.headerViewTap(sectionNumber)
}
}
}
TableView and Custom Header delegates
extension ViewController : UITableViewDelegate, UITableViewDataSource{
//The number of sections fits the number of cells, the current list is an array of DataObject, holding a title and a content.
func numberOfSections(in tableView: UITableView) -> Int {
return self.currentList.count
}
//Each section(group of cells) contains one row
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as UITableViewCell
return cell
}
//update heights for row if the header has been taped
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
let isExpanded = self.currentList[indexPath.section].isExpand
if isExpanded {
return UITableView.automaticDimension
}
return 0
}
//update the estimatedHeightForRowAt if the hader has been taped
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
let isExpanded = self.currentList[indexPath.section].isExpand
if isExpanded{
return UITableView.automaticDimension
}
return 0
}
//returns a custom header
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView = tableView.dequeueReusableHeaderFooterView(withIdentifier: "Header") as! CustomHeaderView
return headerView
}
}
extension ViewController : CustomeHeaderViewDelegate{
func headerViewTap(_ section: Int) {
selectedItem = self.currentList[section]
let output = self.currentList.map({ (item:DataItem) -> DataItem in
var result = item
if result.title == self.selectedItem?.title{
result.isExpand = !result.isExpand
}
return result
})
self.currentList = output
self.tableView.reloadSections(IndexSet(integer: section), with: UITableView.RowAnimation.automatic)
self.tableView.endUpdates()
}
}

Remove Spacing between two custom cells

I have a tableView on mainStoryboard with two custom cells. I would like to reduce the spacing between two cells.
I was trying to find the answer but could not find any. I have image and code added below.
class HomeViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, MFMailComposeViewControllerDelegate {
#IBOutlet var tblStoryList: UITableView!
var array = PLIST.shared.mainArray
override func viewDidLoad() {
super.viewDidLoad()
//spacing between header and cell
self.tblStoryList.contentInset = UIEdgeInsetsMake(-20, 0, 0, 0)
//delete separator of UITableView
tblStoryList.separatorStyle = .none
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.array.count + 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "HeaderCell", for: indexPath) as! HeaderCell
cell.headerTitle.text = "First Stage"
return cell
}
let cell = tableView.dequeueReusableCell(withIdentifier: "StoryTableviewCell", for: indexPath) as! StoryTableviewCell
//making plist file
let dict = self.array[indexPath.row - 1]
let title = dict["title"] as! String
let imageName = dict["image"] as! String
let temp = dict["phrases"] as! [String:Any]
let arr = temp["array"] as! [[String:Any]]
let detail = "progress \(arr.count)/\(arr.count)"
//property to plist file
cell.imgIcon.image = UIImage.init(named: imageName)
cell.lblTitle.text = title
cell.lblSubtitle.text = detail
cell.selectionStyle = UITableViewCellSelectionStyle.none
return cell
}
header cell
import UIKit
class HeaderCell: UITableViewCell {
#IBOutlet weak var headerTitle: UILabel!
override func layoutSubviews() {
super.layoutSubviews()
headerTitle.layer.cornerRadius = 25
headerTitle.layer.masksToBounds = true
}
}
I think you have set some static height to the cells in heightForRowAt indexPath method, set it to UITableViewAutomaticDimension. and estimatedHeightForRowAt indexPath set it to static value for better performance.
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return 40 //expected minimum height of the cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
And not to forget that you need to set "correct constraints" to get the desired result by this method. Constraints are required to let know the table cell about its height.
Try this..
self.tableView.rowHeight = 0; // in viewdidload
[self.tableView setSeparatorStyle:UITableViewCellSeparatorStyleNone]; // in viewdidload
-(CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section{
return 0.01f;
}
-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
return <your header height>;
}
-(UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section{
return [[UIView alloc] initWithFrame:CGRectZero];
}
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
return <your header view>;
}
Also have table seprator as none.
You need to return height for each cell accordingly . for example
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath.row == 0 {
// return height for first row, i.e
return 40
}
// return height for other cells. i.e
return 90
}
You can set table each and every cell height dynamic with Autolayout table view will take cell hight from Autolayout
for that you dont need write this 2 method
Remove this method
tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) ->
CGFloat
{
}
Write this 2 line in ViewDidload method
self.tblView?.rowHeight = UITableViewAutomaticDimension
self.tblView?.estimatedRowHeight = 60
And set your imageview bottom space with Autolayout that you want to keep for example 10 and set relation of bottom layout is greater then or equal and set priority is 252 instead of 1000
You will get clear idea about this in my screen shot check that as well how to do this Do this in all custom cell this way you can set height dynamic no need to calculate height of each and every cell and not need to return

Dynamically heights for when having multiple UITableViewCells based on the content of the each cell

I'm new to swift and working on a project in Swift 3.0 where I have a UITableView with three custom cells. In the first one I just have a image,button and a label. In the second one I have an image plus a label along with expandable and collapsible headers.Thus I have three different sections for this second cell. And lastly the third one is also contains just a label. In the first cell the UILabel is set underneath the image which contains a description about a person (constraints are been set). My requirement is only for the first cell dynamically adjust the cell size based on the size of the description. Help would much appreciate, the code as bellow.
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
print("Number of Sections: \(section)")
return arrayForTableView[section]
}
func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
let headerView : UITableViewHeaderFooterView = view as! UITableViewHeaderFooterView
headerView.contentView.backgroundColor = UIColor.yellow.withAlphaComponent(1.0)
}
func tapped(sender: UITapGestureRecognizer)
{
if let tag = sender.view?.tag{
expanedSections[tag] = !expanedSections[tag]
}
tableView.reloadData()
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView = UITableViewHeaderFooterView()
headerView.tag = section
let tapRecog = UITapGestureRecognizer(target: self, action: #selector(tapped))
tapRecog.numberOfTapsRequired = 1
tapRecog.numberOfTouchesRequired = 1
tapRecog.delegate = self
headerView.addGestureRecognizer(tapRecog)
return headerView
}
func numberOfSections(in tableView: UITableView) -> Int {
return arrayForTableView.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
switch section {
case 0:
return 1
case 1:
return expanedSections[section] ? getItemsForSection(self.tableData.freeGifts): 0
case 2:
return expanedSections[section] ? getItemsForSection(self.tableData.exclusiveOffers) : 0
case 3:
return expanedSections[section] ? getItemsForSection(self.tableData.allAudios) : 0
case 4:
return expanedSections[section] ? getItemsForSection(self.tableData.testamonials) : 0
default:
return 0
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// var cell: UITableViewCell?
print("Section : \(indexPath.section) : \(indexPath.row)")
switch indexPath.section {
case 0:
let cell = tableView.dequeueReusableCell(withIdentifier: "HealerDetailsCell", for: indexPath) as! HealerDetailsTableViewCell
//cell.aboutLabel.preferredMaxLayoutWidth = (tableView.bounds)
cell.aboutLabel.sizeToFit()
populateHealerDetails.populateTable(cell, self.tableData.healerDetails)
return cell
case 1:
if tableData.freeGifts.count > 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "OffersCell",for: indexPath)
PopulateHealerDetailsAndOffers.populateTable(cell, self.tableData.freeGifts[indexPath.row] as! NSDictionary)
return cell
} else {
let cell = UITableViewCell(style: .default, reuseIdentifier: "Cell")
cell.textLabel?.text = "No Free Gifts At This Time"
return cell
}
case 2:
if tableData.exclusiveOffers.count > 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "OffersCell",for: indexPath)
PopulateHealerDetailsAndOffers.populateTable(cell, self.tableData.exclusiveOffers[indexPath.row] as! NSDictionary)
return cell
}else {
let cell = UITableViewCell(style: .default, reuseIdentifier: "Cell")
cell.textLabel?.text = "No Exclusive Offers At This Time"
return cell
}
case 3:
if tableData.allAudios.count > 0{
let cell = tableView.dequeueReusableCell(withIdentifier: "OffersCell",for: indexPath)
PopulateHealerDetailsAndOffers.populateTable(cell, self.tableData.allAudios[indexPath.row] as! NSDictionary)
return cell
}else{
let cell = UITableViewCell(style: .default, reuseIdentifier: "Cell")
cell.textLabel?.text = "NO Audios To Display"
return cell
}
case 4:
if tableData.testamonials.count > 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "TestamonialsCell", for: indexPath)
return cell
}else{
let cell = UITableViewCell(style: .default, reuseIdentifier: "Cell")
cell.textLabel?.text = "No Testamonials"
return cell
}
default:
let cell = tableView.dequeueReusableCell(withIdentifier: "TestamonialsCell", for: indexPath)
return cell
}
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
//let indexPath = tableView.indexPathForSelectedRow!
//let currentCellValue = tableView.cellForRow(at: indexPath)! as UITableViewCell
}
1.Set the constraint of label.
2.Put numberOflines is equal to 0(Through storyboard or programmatically)
Add this code in viewDidLoad:
tableView.estimatedRowHeight = 300
tableView.rowHeight = UITableViewAutomaticDimension
Use this delegate method
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
For version >= iOS 8
override func viewDidLoad()
{
self.tableView.rowHeight = UITableViewAutomaticDimension;
self.tableView.estimatedRowHeight = 44.0; // set to whatever your "average" cell height is
}
Steps to set constraints on storyboard:here
Important
If multiple lines labels, don't forget set the numberOfLines to 0.
Don't forget label.preferredMaxLayoutWidth =
CGRectGetWidth(tableView.bounds)
I think you want to expand/elapse UITableViewCell depending on the data each cell would have at runtime. I suppose, you already have implemented all of the first aid options regarding UITableView in swift.
Please try this method, which will always be called when your each cell is loaded.
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
//CellAnimator.animateCell(cell: cell, withTransform: CellAnimator.TransformWave, andDuration: 1)
//This commented line possibly might not be your requirement.
//But this is actually used to animate cell while loading.
//You can try some constraints or cell height related stuff here which would definitely work for each cell differently.
//Try calling cell specific loads either.
tableView.scrollToRow(at: indexPath as IndexPath, at: .none, animated: true)
/*let indexPath = IndexPath(item: (selectedCellIndexPath?.row)!, section: 0)
tableView.reloadRows(at: [indexPath], with: .none)
checkTrue = true
*/
}
Please check out this:
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var tableView: UITableView!
var tableViewDataSource = ["fewhf wfh wf wfw h dfw \n\n wufhw f ewfw wf w \n\n f wefe wfef w","fewhf wfh wf wfw h dfw \n\n wufhw f ewfw wf w \n\n f wefe wfef w",
"fewhf wfh wf wfw h dfw \n\n wufhw f ewfw wf w \n\n f wefe wfef w",
"fewhf wfh wf wfw h dfw \n\n wufhw f ewfw wf w \n\n f wefe wfef w"
]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
tableView.delegate = self
tableView.dataSource = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//Tableview
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tableViewDataSource.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CellHere") as! TableViewCellHere
cell.cellHere.text = tableViewDataSource[indexPath.row]
cell.cellHere.textAlignment = .justified
return cell
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath.row == 0 || indexPath.row == 1
{
return 120.0
}
else
{
return 50.0
}
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath.row == 0 || indexPath.row == 1
{
return 120.0
}
else
{
return 50.0
}
}
}
This is working for me like this:
enter image description here

Swift3: UITableViewCell and UIButton - Show and hide UITableViewCell by clicking the UIButton

I'm pretty new to Swift 3.0 and am currently working on a school project on IOS app.
I'm having difficulties with the linkage of the UITableViewCell and UIButton.
This is how my app looks like
Basically, what I'm trying to do is that when I click the UIButton, it will decrease the height of cells (Diary and Trend) to 0 (to hide the cells)
and
increase the height of cells (Share and How to use the BP Monitor)(to show the cells) - assuming that the cells (Share and How to use the BP Monitor) are 'hidden' now.
Appreciate if there's an example to follow.
Thank you very much :)
*After trying the example given by #Sandeep Bhandari
This is the code in my ViewController:
class TableViewController: UITableViewController {
var expandedCellIndex : IndexPath? = nil
override func numberOfSections(in tableView: UITableView) -> Int { return 1 }
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell : UITableViewCell! = nil
if indexPath == expandedCellIndex {
cell = tableView.dequeueReusableCell(withIdentifier: "expandedCell") as! ExpandedTableViewCell
(cell as! ExpandedTableViewCell).label1.text = "shown"
(cell as! ExpandedTableViewCell).label2.text = "Efgh"
(cell as! ExpandedTableViewCell).label3.text = "xyz"
}
else {
cell = tableView.dequeueReusableCell(withIdentifier: "simpleCell") as! SimpleTableViewCell
(cell as! SimpleTableViewCell).label.text = "abcd"
}
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if self.expandedCellIndex == indexPath {
self.expandedCellIndex = nil
}
else {
self.expandedCellIndex = indexPath
}
self.tableView.reloadData()
}
override func viewDidLoad() {
super.viewDidLoad()
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 140
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
I couldn't get the same output as the answer suggested.
My Output
Thank you so much!
Here is a simple code which will not only allow you to expand specific cell you can expand all the cell. In case you want to expand only one cell you can do that as well.
Step 1:
Declare two dynamic prototype cells in storyboard.
Lets call the red one as SimpleCell and Green one as ExpandedCell.
Step 2:
Add reusable identifier for each cell.
Step 3
Create custom classes for both these cells and created IBOutlets to labels.
Step 4:
Now write this in ViewDidLoad of your VC.
override func viewDidLoad() {
super.viewDidLoad()
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 140
}
Step 5:
Assuming there can only be one cell expanded at a time I am declaring single IndexPathVariable you can always declare array if you want multiple cells expanded.
var expandedCellIndex : IndexPath? = nil
Step 6:
Write tableView data source code.
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell : UITableViewCell! = nil
if indexPath == expandedCellIndex {
cell = tableView.dequeueReusableCell(withIdentifier: "expandedCell") as! ExpandedTableViewCell
(cell as! ExpandedTableViewCell).label1.text = "abcd"
(cell as! ExpandedTableViewCell).label2.text = "Efgh"
(cell as! ExpandedTableViewCell).label3.text = "xyz"
}
else {
cell = tableView.dequeueReusableCell(withIdentifier: "simpleCell") as! SimpleTableViewCell
(cell as! SimpleTableViewCell).label.text = "abcd"
}
return cell
}
Step 7:
I am expanding cell on cell tap you can do it on button tap as well :) write this logic in IBAction of button lemme write it in didSelectRow.
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if self.expandedCellIndex == indexPath {
self.expandedCellIndex = nil
}
else {
self.expandedCellIndex = indexPath
}
self.tableView.reloadData()
}
Conclusion :
Disclaimer
I am using Dynamic cell height hence has not written heightForRowAtIndexPath as height of the cell will be automatically calculated.
If you are using any UIComponents in cell which does not have implicit size, you might have to implement heightForRowAtIndexPath as below.
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if self.expandedCellIndex == indexPath {
return expnadedCellHeight
}
else {
return simpleCellHeight
}
}

Xcode: Swift - Table Cell not showing all text

My cells are getting the text fine, but they aren't showing all the text.
Image: http://i.imgur.com/Aql1meS.png
Here is the code for my table view controller:
class ResultsTableViewController: UITableViewController {
var mapItems: [MKMapItem] = [MKMapItem]()
override func viewDidLoad() {
super.viewDidLoad()
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// Return the number of sections.
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// Return the number of rows in the section.
return mapItems.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("resultCell", forIndexPath: indexPath) as! ResultsTableCell
if(indexPath.row % 2 == 0) {
cell.backgroundColor = UIColor.clearColor()
}else{
cell.backgroundColor = UIColor.whiteColor().colorWithAlphaComponent(0.2)
cell.textLabel?.backgroundColor = UIColor.whiteColor().colorWithAlphaComponent(0.0)
}
// Configure the cell...
let row = indexPath.row
let item = mapItems[row]
cell.nameLabel.text = item.name
cell.phoneLabel.text = item.phoneNumber
return cell
}
}
I've searched around to see if I have a character limit set, but can't seem to find anything. Thanks in advance.
It seems like your UILabels aren't wide enough. If you make them wider, (or apply auto layout on all 4 sides, well... that gets more complicating,) then it should work fine.
Hope this helps!!

Resources