tableviewCell is cut off from bottom in every cell - ios

Here is my code:
override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
let whiteRoundedView : UIView = UIView(frame: CGRect(x: 10, y: 8, width: self.view.frame.size.width - 20, height: 140))
whiteRoundedView.layer.backgroundColor = CGColor(colorSpace: CGColorSpaceCreateDeviceRGB(), components: [1.0, 1.0, 1.0, 0.9])
whiteRoundedView.layer.masksToBounds = false
whiteRoundedView.layer.cornerRadius = 2.0
whiteRoundedView.layer.shadowOffset = CGSize(width: -1, height: 1)
whiteRoundedView.layer.shadowOpacity = 0.2
whiteRoundedView.layer.borderWidth = 0.5
whiteRoundedView.layer.borderColor = UIColor.orange.cgColor
cell.contentView.backgroundColor = UIColor.clear
cell.contentView.addSubview(whiteRoundedView)
cell.contentView.sendSubview(toBack: whiteRoundedView)
cell.accessoryType = .disclosureIndicator
cell.clipsToBounds = true;
}
Every cell is cut off from the bottom and not showing the complete cell structure.
Any idea?

There is not enough space for the whiteRoundedView over cell height.
Hence, reduce the height <140 of whiteRoundedView while initialization.
let whiteRoundedView : UIView = UIView(frame: CGRect(x: 10, y: 8, width:self.view.frame.size.width - 20, height: YOUR_NEW_HEIGHT))

Your whiteRoundedView should be within the cell content view.
So, try using heightForRowAt indexPath and use the same height for whiteRoundedView in your willDisplay cell

Related

Lable and button in the header section view UITableView

I am trying to add a section title Label and a button in the header section view. but it looks empty. when I run the application the header is empty. the 2nd section code work fine
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
if (section == 0){
let label = UILabel.init(frame: CGRect.init(x: 17, y: 139, width: tableView.frame.size.width, height: 45))
label.textColor = UIColor.black
label.font = UIFont.systemFont(ofSize: 13.0)
label.textAlignment = .left
label.text = " My Balances"
label.backgroundColor = UIColor(red: 0.95, green: 0.95, blue: 0.95, alpha: 1.00)
let frame = tableView.frame
let height:CGFloat = 66
let button = UIButton(frame: CGRect(x: 306, y: 139, width: 15, height: 15)) // create button
button.tag = section
// the button is image - set image
button.setImage(UIImage(named: "remove_button"), for: .normal)
let headerView = UIView(frame: CGRect(x: 0, y: 0, width: frame.size.width, height: height)) // create custom view
headerView.addSubview(button) // add the button to the view
headerView.addSubview(label)
return headerView
//return label
//return label
}
else {
let label = UILabel.init(frame: CGRect.init(x: 0, y: 241, width: tableView.frame.size.width, height: 45))
label.textColor = UIColor.black
label.font = UIFont.systemFont(ofSize: 13.0)
label.textAlignment = .left
label.text = " My Customers"
label.backgroundColor = UIColor(red: 0.95, green: 0.95, blue: 0.95, alpha: 1.00)
return label
}
}
You are not following the proper way. First you have to set height of header view using heightForHeaderInSection from tableview object in viewDidLoad() like -
tableView.heightForHeaderInSection = 250
or by using its delegate method -
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 250
}
You set the height of header view equal to tableview height. Set it less than it let height:CGFloat = 250 -
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let label = UILabel.init(frame: CGRect.init(x: 0, y: 241, width: tableView.frame.size.width, height: 45))
label.textColor = UIColor.black
label.font = UIFont.systemFont(ofSize: 13.0)
label.textAlignment = .left
label.text = " My Balances"
label.backgroundColor = UIColor(red: 0.95, green: 0.95, blue: 0.95, alpha: 1.00)
let frame = tableView.frame
let height:CGFloat = 250
let button = UIButton(frame: CGRect(x: 5, y: 10, width: 15, height: 15)) // create button
button.tag = section
// the button is image - set image
button.setImage(UIImage(named: "remove_button"), for: .normal)
let headerView = UIView(frame: CGRect(x: 0, y: 0, width: frame.size.width, height: height)) // create custom view
headerView.addSubview(button) // add the button to the view
headerView.addSubview(label)
return headerView
//return label
}
Or another way is to make custom reusable header view, register as header view and finally dequeu it.
You can follow the documentation from apple for second way - https://developer.apple.com/documentation/uikit/views_and_controls/table_views/adding_headers_and_footers_to_table_sections

Tableview cell padding and spacing

I have this table with cells which have an image and a text
First thing that I want is to add a padding to cells so that the image with the circle and the scissors doesn't hit the border of the cell. I already tried things like cell.layoutMargins = UIEdgeInsets(top: 50, left: 50, bottom: 50, right: 50) or cell.bounds = CGRect(x: 0, y: 0, width: 100, height: 100), cell.separatorInset = UIEdgeInsets(top: 100, left: 100, bottom: 100, right: 100) but nothing has changed.
Second thing that I would like is to add a spacing between the cell, I tried all the solutions that I found but it doesn't seem to work
CODE (some of the solutions that I tried are written below all toghether, but I also tried them one by time)
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "difficultyCell", for: indexPath)
cell.textLabel?.text = myDict[indexPath.row].key
cell.textLabel?.font = .boldSystemFont(ofSize: 20)
let imageCell = UIImage(named: "scissors.png")
cell.imageView?.image = imageCell
cell.backgroundColor = Esercizio.hexStringToUIColor(hex: "#4cf584").withAlphaComponent(0.85)
cell.layer.borderColor = UIColor.orange.cgColor
cell.layer.borderWidth = 1
cell.layer.cornerRadius = 8
cell.layoutMargins = UIEdgeInsets(top: 50, left: 50, bottom: 50, right: 50)
cell.bounds = CGRect(x: 0, y: 0, width: 100, height: 100)
cell.separatorInset = UIEdgeInsets(top: 100, left: 100, bottom: 100, right: 100)
return cell
}
to solve it easily , if you are using custom UITableViewCell file, in your cell class override the layoutsubView method of the class and there you can add the UIEdgeInset to the frame of the contentView, and also dont forget the added padding amount into total RowHeight estimation in your tableview: this code will work for you for sure,
override func layoutSubviews() {
super.layoutSubviews()
contentView.frame = contentView.frame.inset(by: UIEdgeInsets(top: 0, left: 0, bottom: 10, right: 0))
}
this way you can create padding to whatever direction you want to add the padding.
The best solution here is to create your own cell, add your own image, labels, etc. inside of contentView and tweak them how you want using auto layout constraints.
see: https://www.raywenderlich.com/8549-self-sizing-table-view-cells

UITableViewCell with gradient not working until first reuse of cell

I want to add a gradient to part of a custom UITableViewCell. This is my gradient Code.
func addGradient() {
gradient = CAGradientLayer()
gradient.frame = CGRect(x: 0, y: 0, width: gradientView.frame.width, height: gradientView.frame.height)
gradient.colors = [
UIColor(red:0.23, green:0.24, blue:0.28, alpha:1).cgColor,
UIColor(red:0.11, green:0.11, blue:0.12, alpha:0.6).cgColor
]
gradient.locations = [0, 1]
gradient.startPoint = CGPoint(x: 0.5, y: 0)
gradient.endPoint = CGPoint(x: 0.5, y: 1)
gradientView.layer.addSublayer(gradient)
}
This is my gradientView code.
func addGradientView() {
containerView.addSubview(gradientView)
gradientView.translatesAutoresizingMaskIntoConstraints = false
gradientView.leadingAnchor.constraint(equalTo: containerView.leadingAnchor).isActive = true
gradientView.topAnchor.constraint(equalTo: barChart.bottomAnchor).isActive = true
gradientView.trailingAnchor.constraint(equalTo: containerView.trailingAnchor).isActive = true
gradientView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor).isActive = true
}
addGradient() is called in the layoutSubiviews() method. But the real height and width don't seem to be reflecting until the first reuse of the cell.
Option 1: Call your addGradient() from tableview's willDisplayCell delegate method.
public func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
if cell is YourCustomTableViewCell {
(cell as! YourCustomTableViewCell).addGradient()
}
}
Make sure you add the gradient once. Because of the cell reuse addGradient() may get called several times on the same cell. So better rename your function to addGradientfNeeded() and adjust its logic accordingly.
Option 2:
Instead of adding your gradient in willDisplay method, add the gradient view and the layer in the cell (once) and only update the frame of the gradient layer.
public func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
if cell is YourCustomTableViewCell {
(cell as! YourCustomTableViewCell).updateGradientLayerFrame()
}
}
Option 3:
Create a GradientView class and add it either in the interface builder or programatically to your cell, the gradient will resize as the view's frame changes:
public class GradientView: UIView {
private var gradientLayer: CAGradientLayer?
override public func layoutSubviews() {
super.layoutSubviews()
guard gradientLayer == nil else {
gradientLayer?.frame = CGRect(x: 0, y: 0, width: self.frame.width, height: self.frame.height)
return
}
gradientLayer = CAGradientLayer()
gradientLayer!.frame = CGRect(x: 0, y: 0, width: self.frame.width, height: self.frame.height)
gradientLayer!.colors = [
UIColor(red:0.23, green:0.24, blue:0.28, alpha:1).cgColor,
UIColor(red:0.11, green:0.11, blue:0.12, alpha:0.6).cgColor
]
gradientLayer!.locations = [0, 1]
gradientLayer!.startPoint = CGPoint(x: 0.5, y: 0)
gradientLayer!.endPoint = CGPoint(x: 0.5, y: 1)
self.layer.addSublayer(gradientLayer!)
}
}
Your TableViewCell does not have a frame yet. You may print the frame to check that, it will be a zero frame.
Move the addGradientView method to the layoutSubView override.
override func layoutSubviews() {
super.layoutSubviews()
addGradient()
}
Edit:
I see that you have mentioned it didn't work in layoutSubView. I believe there is some problem in the way you are calling the method.
The below code works for me
class GradientCell: UITableViewCell {
override func layoutSubviews() {
super.layoutSubviews()
print(self.frame)
addGradient()
}
func addGradient() {
let gradient = CAGradientLayer()
gradient.frame = CGRect(x: 0, y: 0, width: self.frame.width, height: self.frame.height)
gradient.colors = [
UIColor(red:0.23, green:0.24, blue:0.28, alpha:1).cgColor,
UIColor(red:0.11, green:0.11, blue:0.12, alpha:0.6).cgColor
]
gradient.locations = [0, 1]
gradient.startPoint = CGPoint(x: 0.5, y: 0)
gradient.endPoint = CGPoint(x: 0.5, y: 1)
self.layer.addSublayer(gradient)
}
}
EDIT 2:
It would be better if you move the didMoveToWindow
Create a global variable inside the cell.
private let gradientLayer: CAGradientLayer = {
let layer = CAGradientLayer()
layer.colors = [UIColor.magenta.cgColor, UIColor.black.cgColor]
layer.locations = [0.0, 1.0]
layer.cornerRadius = 5
layer.masksToBounds = true
return layer
}()
Then add this gradient layer in the initialize method where you are adding UI components.
Now you have to update the frame of the gradient layer.
override func layoutSubviews() {
super.layoutSubviews()
updateGradientFrame()
}
private func updateGradientFrame() {
gradientLayer.frame = // set your frame here...
}

How to manage textlabel height by parent view

I have some issue. I trie to make custom table header sections. Here is my code:
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let sectionHeader = UIView(frame: CGRect(x: 0, y: 0, width: tableView.frame.size.width, height: 36))
sectionHeader.backgroundColor = #colorLiteral(red: 0.1215686277, green: 0.01176470611, blue: 0.4235294163, alpha: 1)
tableView.backgroundColor = colors.background
let headerName = UILabel(frame: CGRect(x: 15, y: 0, width: tableView.frame.size.width, height: sectionHeader.frame.size.height))
headerName.font = UIFont(name: "Helvetica", size: 12)
headerName.text = sectionHeaders[section]
headerName.backgroundColor = #colorLiteral(red: 0.9529411793, green: 0.6862745285, blue: 0.1333333403, alpha: 1)
headerName.clipsToBounds = true
sectionHeader.addSubview(headerName)
return sectionHeader
}
And here is result:
With blue and yellow color i marked and noticed, that label height not the same as headerview. Can some one help me how manage textlabel height to header view height, and how to align text verticaly
label height not the same as headerview
At first you should setup height of your section header:
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 36.0
}
Based on height: 36 from let sectionHeader = UIView(frame: CGRect(x: 0, y: 0, width: tableView.frame.size.width, height: 36))
how to align text verticaly
headerName.textAlignment = .center

UITableViewCell shadows

I'm trying to implement this design but all solutions I have browsed won't work and from what I understand it could be because of the spacing between the cells and the UITableView.
Here's the design:
So basically what I'm trying to achieve is to have shadows from all 4 sides as well as some spacing between each cell and the following cell.
Thanks
Edit:
Here's the code I tried.
let shadowSize : CGFloat = 5.0
let shadowPath = UIBezierPath(rect: CGRect(x: -shadowSize / 2,
y: -shadowSize / 2,
width: self.avatarImageView.frame.size.width + shadowSize,
height: self.avatarImageView.frame.size.height + shadowSize))
self.avatarImageView.layer.masksToBounds = false
self.avatarImageView.layer.shadowColor = UIColor.black.cgColor
self.avatarImageView.layer.shadowOffset = CGSize(width: 0.0, height: 0.0)
self.avatarImageView.layer.shadowOpacity = 0.5
self.avatarImageView.layer.shadowPath = shadowPath.cgPath
Edit 2:
I'd like to point out that all my cell's objects are inside a container UIView. All the above code is applied to this UIView.
You have to make a UIView inside UITableViewCell and work on that view.
FOR SHADOW I AM USING THIS IN UITableViewCell CLASS:-
viewDummy.addShadow() //use from any view
extension UIView {
func addShadow(){
self.layer.shadowColor = UIColor.blackColor().CGColor
self.layer.shadowOpacity = 0.5
self.layer.shadowRadius = 2.0
self.layer.shadowOffset = CGSizeMake(1.0, 1.0)
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.layer.shadowOffset = CGSize(width: 0, height: 0)
cell.layer.shadowColor = UIColor.black.cgColor
cell.layer.shadowRadius = 5
cell.layer.shadowOpacity = 0.40
cell.layer.masksToBounds = false;
cell.clipsToBounds = false;
return cell
}

Resources