How to change UITableView section borders? - swift

I have a UITableView and I simply want to set the same width to all separators. I already know something about customizing uitableview, but this one is a mystery to me..
Basically, I want to set this section headers separators to be the same width as cell separators, have the same leading space to the superview. What's the best way to do it?
EDIT
func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
let header = view as! UITableViewHeaderFooterView
header.textLabel?.font = header.textLabel?.font.withSize(12)
header.textLabel?.textColor = ColorConstants.symbolsColor
}

In the table view method CellForRowAt...
Try adding this code
cell.preservesSuperviewLayoutMargins = false
cell.seperatorInset = UIEdgeInsets.zero
cell.layoutMargins = UIEdgeInsets.zero

Headers and footers don't have separator lines but you can mock them using custom UIViews and putting them in:
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let view = UIView(frame: CGRect(x: 0, y: 0, width: tableView.frame.size.width, height: 50))
let px = 1 / UIScreen.main.scale
let frame = CGRect(x: 0, y: 0, width: self.tableView.frame.size.width, height: px)
let line = UIView(frame: frame)
view.addSubview(line)
line.backgroundColor = self.tableView.separatorColor
self.tableView.tableHeaderView = view
}
And add your other code to this function as well instead of willDisplayHeaderView.
You may need to adjust the CGRect dimensions to match what you want exactly. I believe the default cell separators start at 15 points (not 100% sure on that)
credit to: https://stackoverflow.com/a/28177407/7535093

Related

tableView Cell Labels Stack When I Scroll

I have a custom tableView, entirely created in code. IE, the cells need to be in code too.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "inventoryCell", for: indexPath)
let namelabel = UILabel()
namelabel.frame = CGRect(x: 145, y: 10 , width: 200, height: 30 )
namelabel.text = itemToShow.name
namelabel.font = UIFont.boldSystemFont(ofSize: 20)
namelabel.backgroundColor = .clear
cell.addSubview(namelabel)
let detailLabel = UILabel()
detailLabel.frame = CGRect(x: 145, y: 50 , width: 200, height: 50 )
detailLabel.text = itemToShow.detail
detailLabel.backgroundColor = .clear
cell.addSubview(detailLabel)
let inventoryImage = UIImageView()
inventoryImage.frame = CGRect(x: 10, y: 10, width: 130, height: 130)
inventoryImage.image = UIImage(named: "emptyInventorySlot")
cell.addSubview(inventoryImage)
return cell
}
It works great, and you can see it loads perfectly. The top image is the load, the bottom image is once I scroll to the bottom. You can see the text labels seem to all stack on top of each other.
I would not recommend doing it this way.
It's better to move the code that creates namelabel, detailLabel and inventoryImage to an inventoryCell class derived from UITableViewCell.
But you can make it work.
Since table cells are reused and the reused cells already contain the created subviews, you need to either remove the subviews or treat cells with already created subviews differently.
And you should place your labels in the contentView of your UITableCellView.
To make your code work you can do this:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "inventoryCell", for: indexPath)
// remove any subviews from contentView from recycled cells
cell.contentView.subviews.forEach{ $0.removeFromSuperview() }
let namelabel = UILabel()
namelabel.frame = CGRect(x: 145, y: 10 , width: 200, height: 30 )
namelabel.text = itemToShow.name
namelabel.font = UIFont.boldSystemFont(ofSize: 20)
namelabel.backgroundColor = .clear
// add any label to contentView of the cell
cell.contentView.addSubview(namelabel)
let detailLabel = UILabel()
detailLabel.frame = CGRect(x: 145, y: 50 , width: 200, height: 50 )
detailLabel.text = itemToShow.detail
detailLabel.backgroundColor = .clear
// add any label to contentView of the cell
cell.contentView.addSubview(detailLabel)
let inventoryImage = UIImageView()
inventoryImage.frame = CGRect(x: 10, y: 10, width: 130, height: 130)
inventoryImage.image = UIImage(named: "emptyInventorySlot")
// add any label to contentView of the cell
cell.contentView.addSubview(inventoryImage)
return cell
}
Better would be:
create a UITableViewCell subclass
place your label placement and configuration there
take care of cell reuses, override prepareForReuse() to support cell reuse
register this class as a table view cell for your tableView
cast your dequeued cell to your UITableViewCell subclass

How to make tableview row and label height according to label text in swift?

I am making chat related screen, here i have placed view inside tableview cell and label in side view.
for view and i have given leading, trailing, top, bottom
for label i have given leading, trailing, top, bottom constraints
but here cell and label text not coming well, sometime for short text cell becomes big and for long text it remains same like below its coming
here is the code:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
{
if indexPath.section==0 {
if (indexPath.row%2)==0
{
let cell:ReceiverChatTableViewCell = (chatTableView.dequeueReusableCell(withIdentifier: "ReceiverChatTableViewCell") as! ReceiverChatTableViewCell?)!
let font = UIFont(name: "Helvetica", size: 20.0)
var height = heightForView(text: cell.receiverTextLbl.text!, font: font!, width: 100.0)
if height<60
{
height=60
}
return height
}
}
else
{
return 50
}
return UITableView.automaticDimension
}
func heightForView(text:String, font:UIFont, width:CGFloat) -> CGFloat{
let label:UILabel = UILabel(frame: CGRect(x: 0, y: 0, width: width, height: CGFloat.greatestFiniteMagnitude))
label.numberOfLines = 1000
label.lineBreakMode = NSLineBreakMode.byWordWrapping
label.font = font
label.text = text
label.sizeToFit()
return label.frame.height
}
please help me to solve the code.

TableView Cell view shadow does not coming properly in Swift

I have added view as a background for tableview cell and I am giving shadow for view. Here when I run tableview shadow does not coming properly, once I scroll down and up then shadow coming properly.
I have given shadow according to this answer answer
Code:
extension UIView {
func dropShadow(scale: Bool = true) {
layer.masksToBounds = false
layer.shadowColor = UIColor.black.cgColor
layer.shadowOpacity = 0.5
layer.shadowOffset = CGSize(width: -1, height: 1)
layer.shadowRadius = 1
layer.shadowPath = UIBezierPath(rect: bounds).cgPath
layer.shouldRasterize = true
layer.rasterizationScale = scale ? UIScreen.main.scale : 1
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! PlansTableViewCell
cell.containerView.dropShadow()
return cell
}
Before scrolling shadow coming like this:
after scrolling coming like below:
After running(before scrolling) also i need second image kind of output, Here Help me with the code.
Problem is here
layer.shadowPath = UIBezierPath(rect: bounds).cgPath
bounds isn't correct at that time , try
call it from
override func layoutSubviews() {
super.layoutSubviews()
self.containerViewdropShadow()
}
or
cell.layoutIfNeeded()
cell.containerView.dropShadow()

How to show a table view header's label in the left part of the same table view cell ?

I know that it's possible in the collection view with horizontal scroll style but I need this as vertical one.I was tryed to set table view height to 0,rotate the header label but when I set the negative constraint to the label its not showing due to hierarchy of the views.After that,I was tryed to bring the label to front,too.If you don't understand clearly,I can explain with some screenshots or the source codes.
You can create a headerView and add a label to it and set the text alignment of the header view to left or as per your need.
override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView = UIView(frame: CGRect(x: 0, y: 0, width: tableView.frame.width, height: 50))
headerView.layer.borderWidth = 2
let myLabel = UILabel()
myLabel.frame = CGRectMake(0, 0, tableView.frame.width - 70, 50)
myLabel.font = UIFont.boldSystemFontOfSize(18)
myLabel.textColor = UIColor.whiteColor()
myLabel.textAlignment = .Left
myLabel.text = "This is a left alignmen"
headerView.addSubview(myLabel)
return headerView
}
You can go through theApple Documentation for Table view.
This is header view that have left alignment for the header view.

UITableView header UITableViewAutomaticDimension not working

I want to make my tableview header have automatic height because I have label in my header view that can have multi line text.
I've set following steps:
in view did load ad
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, estimatedHeightForHeaderInSection section: Int) -> CGFloat {
return 200
}
But it still not working.
Here is my storyboard configuration (I have set lines to 0 and line break to word wrap.
Another question: Is the custom view I added on the top of TableViewCell is a header cell?
I've ended up using method to calculate height for label and added the height to the View.
private func heightForView(text: String, font: UIFont, width: CGFloat) -> CGFloat {
let label = UILabel(frame: CGRect(x: 0, y: 0, width: width, height: CGFloat.greatestFiniteMagnitude))
label.numberOfLines = 0
label.lineBreakMode = NSLineBreakMode.byWordWrapping
label.font = font
label.text = text
label.sizeToFit()
return label.frame.height
}
In the viewDidLoad()
let labelHeight = heightForView(text: post.content, font: contentLabel.font, width: contentLabel.frame.width)
headerView.frame.size.height = headerView.frame.size.height + labelHeight
Still curious why the UITableViewAutomaticDimension not working in this case.