Expandable cell with dynamic data (swift) - 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)
}

Related

UITableViewCell Selected Background Color on DidSelectRow

I want to change the background when I select the table. Right now, when I select two tables, the background changes to 2. I just want to change the background of the last table I chose. So just change the background of one table, not two. Change the background of the last painting I chose.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if tableView == self.tableView1 {
let cell:DeviceTableViewCell2 = tableView1.dequeueReusableCell(withIdentifier: cellId, for: indexPath) as! DeviceTableViewCell2
cell.selectionStyle = .none
cell.backgroundColor = GradientColor(UIGradientStyle.diagonal, frame: self.view.frame, colors: [UIColor.flatPowderBlueDark, UIColor.flatSand])
}
if tableView == self.tableView2 {
let cell:DeviceTableViewCell2 = tableView2.dequeueReusableCell(withIdentifier: cellIdNew, for: indexPath) as! DeviceTableViewCell2
cell.selectionStyle = .none
cell.backgroundColor = GradientColor(UIGradientStyle.diagonal, frame: self.view.frame, colors: [UIColor.flatPowderBlueDark, UIColor.flatSand])
}
if tableView == self.tableView3 {
let cell:DeviceTableViewCell2 = tableView3.dequeueReusableCell(withIdentifier: cellIdNew2, for: indexPath) as! DeviceTableViewCell2
cell.selectionStyle = .none
cell.backgroundColor = GradientColor(UIGradientStyle.diagonal, frame: self.view.frame, colors: [UIColor.flatPowderBlueDark, UIColor.flatSand])
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if tableView == self.tableView1 {
let selectedCell:UITableViewCell = tableView1.cellForRow(at: indexPath)!
selectedCell.contentView.backgroundColor = UIColor.flatGray
}
if tableView == self.tableView2 {
let selectedCell2:UITableViewCell = tableView2.cellForRow(at: indexPath)!
selectedCell2.contentView.backgroundColor = UIColor.flatGray
}
if tableView == self.tableView3 {
let selectedCell3:UITableViewCell = tableView3.cellForRow(at: indexPath)!
selectedCell3.contentView.backgroundColor = UIColor.flatGray
}
Do not change the backgroundColor of the contentView or of the cell itself, use the selectedBackgroundView instead:
cell.backgroundView = UIView()
cell.backgroundView?.backgroundColor = // your color when not selected
cell.selectedBackgroundView = UIView()
cell.selectedBackgroundView?.backgroundColor = // your color when selected
After this initial setup, there is no need to change anything. Everything will work automatically.
Do not set cell.selectionStyle = .none because that will disable selection completely.

Remove specific subviews (swift)

Question: How Can i just remove all the subview of UIButton? if i remove all subviews, it will remove the cell title as well.
This is my code:
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
}
try like this :
for view in subviews {
if view is UIButton {
view.removeFromSuperview()
}
}
NicolasMiari's suggest way:
for view in subviews where view is UIButton{
view.removeFromSuperview()
}
If your just wanna remove all subviews from deptmentProfile
for subview in deptmentProfile.subviews {
subview.removeFromSuperview()
}
if you mean remove the subview which is type of UIButton, using where clause is a proper and elegant way
for subview in testButton.subviews where subview is UIButton {
subview.removeFromSuperview()
}

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

Swift: How to reload row height in UITableViewCell without reloading data

I have a case in which I have to reload only height of a UITableViewCell.
but if I call the function
tableView.reloadRowsAtIndexPaths([NSIndexPath(forRow: webView.tag, inSection: 0)], withRowAnimation: .Automatic)
it reloads the height as well as the data of the cell.
How can i just control the height of cell in Swift?
This is my cellForRow block :
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if indexPath.row == 0 {
let cell = tableView.dequeueReusableCellWithIdentifier("cell1", forIndexPath: indexPath) as! CustomTableViewCell1
cell.heading.text = headerText
return cell
}
else if indexPath.row == 1 {
let cell = tableView.dequeueReusableCellWithIdentifier("cell2", forIndexPath: indexPath) as! CustomTableViewCell2
ImageLoader.sharedLoader.imageForUrl(self.headerImage , completionHandler:{(image: UIImage?, url: String) in
cell.mainImage.image = image
})
return cell
}
else if indexPath.row == 2 {
let cell = tableView.dequeueReusableCellWithIdentifier("cell3", forIndexPath: indexPath) as! CustomTableViewCell3
//cell.aurthorImage.image = UIImage(named : "obama")
ImageLoader.sharedLoader.imageForUrl(self.headerImage , completionHandler:{(image: UIImage?, url: String) in
cell.aurthorImage.image = image
})
cell.aurthorImage.tag = aurthorID
cell.aurthorImage.layer.cornerRadius = cell.aurthorImage.frame.height/2
cell.aurthorImage.clipsToBounds = true
cell.aurthorImage.userInteractionEnabled = true
cell.aurthorImage.addGestureRecognizer(aurthorImageTapRecignizer)
cell.aurthorName.text = self.authorName
cell.time.text = self.time
self.followButton = cell.followButton
return cell
}
else if indexPath.row == 3 {
let cell = tableView.dequeueReusableCellWithIdentifier("cell4", forIndexPath: indexPath) as! CustomTableViewCell4
let htmlHeight = contentHeights[indexPath.row]
cell.webElement.tag = indexPath.row
cell.webElement.delegate = self
cell.webElement.loadHTMLString(HTMLContent, baseURL: nil)
cell.webElement.frame = CGRectMake(0, 0, cell.frame.size.width, htmlHeight)
return cell
}
else if indexPath.row == 4 {
let cell = tableView.dequeueReusableCellWithIdentifier("cell1", forIndexPath: indexPath) as! CustomTableViewCell1
cell.heading.text = "Related Posts"
return cell
}
else if indexPath.row == 5{
let cell = tableView.dequeueReusableCellWithIdentifier("cell6", forIndexPath: indexPath) as! CustomTableViewCell6
return cell
}
else if indexPath.row == 6 {
let cell = tableView.dequeueReusableCellWithIdentifier("cell1", forIndexPath: indexPath) as! CustomTableViewCell1
cell.heading.text = "Comments"
return cell
}
else if indexPath.row == 7 {
let cell = tableView.dequeueReusableCellWithIdentifier("cell5", forIndexPath: indexPath) as! CustomTableViewCell5
let htmlHeight = contentHeights[indexPath.row]
self.commentSection = cell.commentsView
self.commentSection.tag = indexPath.row
self.commentSection.delegate = self
let url = NSURL(string: commentsURL)
let requestObj = NSURLRequest(URL: url! )
self.commentSection.loadRequest(requestObj)
self.commentSection.frame = CGRectMake(0, 0, cell.frame.size.width, htmlHeight)
commentSectionDidNotLoad = false
return cell
}
else {
let cell = tableView.dequeueReusableCellWithIdentifier("cell1", forIndexPath: indexPath) as! CustomTableViewCell1
cell.heading.text = headerText
return cell
}
You can use this code to update the cell's height without reloading their data:
tableView.beginUpdates()
tableView.endUpdates()
You can also use this method followed by the endUpdates method to animate the change in the row heights without reloading the cell.
UITableView Class Reference
start an update of the tableview and then end it without changing anything.
tableView.beginUpdates()
tableView.endUpdates()
This should make the tableview set the new height
You can regulate the height by either implementing the (a)heightForRowAtIndexPath with logic setting the heights or (b)with auto layout and automatic tableview row height
A.
override func tableView(tableView: UITableView!, heightForRowAtIndexPath indexPath: NSIndexPath!) -> CGFloat {
if [your condition, row == 5 in your comment] {
return 100
} else {
return 40
}
}
Whenever you want to change the height you would just call these two rows
tableView.beginUpdates()
tableView.endUpdates()
B.
in viewDidLoad
tableView.estimatedRowHeight = 40.0
tableView.rowHeight = UITableViewAutomaticDimension
and then you can just expose the layout constraint that set's the cells height and access it to set the height when you want
cell.heightConstraint.constant = 100
tableView.beginUpdates()
tableView.endUpdates()
About your question for example, to give a specific height dimension :
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if indexPath.row == 3 {
return 50.0
}
return 72.0
}
But I think you have a webView inside a cell so, generally, to calculate the dynamic height of a UITableViewCell with a UIWebView:
(this example have two webViews)
class MyTableViewController: UITableViewController, UIWebViewDelegate
{
var content : [String] = ["<!DOCTYPE html><html><head><title>Page Title</title></head><body><h1>My First Heading</h1><p>My first paragraph</p></body></html>", "<HTML><HEAD><TITLE>Coca-Cola</TITLE></HEAD><BODY>In Chinese, Coca-Cola means Bite the Wax Tadpole</BODY></HTML>"]
var contentHeights : [CGFloat] = [0.0, 0.0]
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCellWithIdentifier("myCustomCell", forIndexPath: indexPath) as! MyCustomCell
let htmlString = content[indexPath.row]
let htmlHeight = contentHeights[indexPath.row]
cell.webView.tag = indexPath.row
cell.webView.delegate = self
cell.webView.loadHTMLString(htmlString, baseURL: nil)
cell.webView.frame = CGRectMake(0, 0, cell.frame.size.width, htmlHeight)
return cell
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat
{
return contentHeights[indexPath.row]
}
func webViewDidFinishLoad(webView: UIWebView)
{
if (contentHeights[webView.tag] != 0.0)
{
// height knowed, no need to reload cell
return
}
contentHeights[webView.tag] = webView.scrollView.contentSize.height
tableView.reloadRowsAtIndexPaths([NSIndexPath(forRow: webView.tag, inSection: 0)], withRowAnimation: .Automatic)
}
}
You can use the view height constraint in the cell, by updating the view in cell height you can update the specific cell height.
let height = cell.Height_constraint.constant
cell.Height_constraint.constant = height + 200 //200 you can use any number
Height_constraint: is the height constraint of subView in my cell.

Shadow on a UITableViewCell disappears when scrolling

I have a UITableView that has one cell with a shadow. When I do scrolling up and down, the shadow of the cell disappears. As I thought this was a reuse-issue I already only ever use this one cell with a shadow.What may be the problem here ?
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = UITableViewCell()
switch indexPath.row {
case 3: cell = shadowBasicCellAtIndexPath(indexPath)
case 4: cell = contentCellAtIndexPath(indexPath)
case 5: cell = contentCellAtIndexPath(indexPath)
case 6: cell = contentCellAtIndexPath(indexPath)
case 11: cell = contentCellAtIndexPath(indexPath)
default: cell = basicCellAtIndexPath(indexPath)
}
return cell
}
func contentCellAtIndexPath(indexPath: NSIndexPath) -> ContentCell {
let cell = tableView.dequeueReusableCellWithIdentifier(contentCellIdentifier) as! ContentCell
setTitleForCell(cell, indexPath: indexPath)
setContentForCell(cell, indexPath: indexPath)
return cell
}
func shadowBasicCellAtIndexPath(indexPath: NSIndexPath) -> ShadowBasicCell {
// let cell = tableView.dequeueReusableCellWithIdentifier(shadowBasicCellIdentifier) as! ShadowBasicCell
let cell = tableView.dequeueReusableCellWithIdentifier(shadowBasicCellIdentifier, forIndexPath: indexPath) as! ShadowBasicCell
// let cell = ShadowBasicCell(style: <#T##UITableViewCellStyle#>, reuseIdentifier: <#T##String?#>)
cell.icon.image = upperTableIcons[indexPath.row]
cell.textlabel.text = upperTableLabels[indexPath.row]
cell.textlabel.textColor = UIColor.dmvBody1()
cell.textlabel.font = UIFont.dmvBody1()
cell.valueLabel.font = UIFont.dmvBody1()
cell.selectionStyle = UITableViewCellSelectionStyle.None
cell.layer.shadowColor = UIColor.blackColor().CGColor
cell.layer.shadowOffset = CGSizeMake(5, 5);
cell.layer.shadowOpacity = 0.2;
cell.layer.shadowRadius = 3.0;
cell.clipsToBounds = false
let shadowFrame: CGRect = (cell.layer.bounds)
let shadowPath: CGPathRef = UIBezierPath(rect: shadowFrame).CGPath
cell.layer.shadowPath = shadowPath
cell.separatorInset = UIEdgeInsets.init(top: 0, left: cell.frame.width, bottom: 0, right: 0)
return cell
}
func basicCellAtIndexPath(indexPath: NSIndexPath) -> BasicCell {
let cell = tableView.dequeueReusableCellWithIdentifier(basicCellIdentifier) as! BasicCell
cell.icon.image = upperTableIcons[indexPath.row]
cell.textlabel.text = upperTableLabels[indexPath.row]
cell.textlabel.textColor = UIColor.dmvBody1()
cell.valueLabel.text = upperTableValues[indexPath.row]
cell.valueLabel.textColor = UIColor.dmvBody1()
cell.textlabel.font = UIFont.dmvBody1()
cell.valueLabel.font = UIFont.dmvBody1()
cell.selectionStyle = UITableViewCellSelectionStyle.None
if indexPath.row > 6 {cell.backgroundColor = UIColor.dmvBeige30()} else {
cell.backgroundColor = UIColor.whiteColor()
}
return cell
}
I solved the problem myself: The reason the shadow wasn't seen, was because it was covered by the cell beneath that got redrawn. I set the background color of the following cell to clearColor() and everything is fine now.