Custom UITableViewCell programmatically with SWIFT - swift

Attached you may find a picture of (left) my attempt to create a similar (right) UITableView. they look like buttons but they're only cells that can be clicked on as a tableview cell.
I have tried many different things including adding a container window inside a custom cell, adding a UIImage inside the custom cell but I just can't replicate these cells!
I have tried using a custom cell class, I have tried doing it through IB and I for the crazyiness of me, cannot recreate it.
Would anyone be able to give me a hint on how to create the (inside cell) text-bounding box/square? with the different background colour lighting?
If this can easily be done with IB I'd rather do it this way, but if you have a sample customcell class that I can take a look at that'd be greatly appreciated too!
Thank you for taking the time to look at my question.

I have made a sample for you close to your requirement. Have a look
https://github.com/RajanMaheshwari/CustomTableCell
I would like to do this using a UITableView.
My approach will be taking a custom cell and add a UIView with some constraints from left, right, up and down.
Also I will provide the same background color to UITableView, UIView which is the superview and the cell content view and also make the separator of UITableView as None and Selection of TableCell as None so that the UI looks like
Next after applying every constraint and making a CustomCell and making IBOutlets we will jump to code.
I will do all the shadow and outlining in Custom Cell's awakeFromNib method
This will be my CustomTableViewCell class
class CustomTableViewCell: UITableViewCell {
#IBOutlet weak var labelBackgroundView: UIView!
#IBOutlet weak var cellLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
labelBackgroundView.layer.borderWidth = 0.5
labelBackgroundView.layer.borderColor = UIColor.lightGrayColor().CGColor
labelBackgroundView.layer.shadowColor = UIColor.lightGrayColor().CGColor
labelBackgroundView.layer.shadowOpacity = 0.8
labelBackgroundView.layer.shadowRadius = 5.0
labelBackgroundView.layer.shadowOffset = CGSizeMake(0.0, 2.0)
labelBackgroundView.layer.masksToBounds = false;
}
I have two outlets.
One is the label in which you will be displaying the name.
Other is the outer view which you want to display with some outlining and shadow.
The ViewController code will be:
class ViewController: UIViewController,UITableViewDataSource,UITableViewDelegate {
var array = [String]()
#IBOutlet weak var myTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
array = ["Wealth","Health","Esteem","Relationship"]
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return array.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("CustomTableViewCell") as! CustomTableViewCell
cell.cellLabel.text = array[indexPath.row]
cell.labelBackgroundView.tag = indexPath.row
cell.labelBackgroundView.userInteractionEnabled = true
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(cellViewTapped))
cell.labelBackgroundView.addGestureRecognizer(tapGesture)
return cell
}
func cellViewTapped(sender:UITapGestureRecognizer) {
let view = sender.view
let index = view?.tag
print(index!)
}
}
Here I have not used didSelectIndex of UITableViewDelegate as I only want the tap on the Outlining LabelBackgroundView and not on complete cell.
So the final outcome is like this

I think you are on the right path. I did something similar in a project. I created a subclass of UIView (too add a shadow to the view) and added a view with this type inside the cell.
class ShadowedView: UIView {
override func awakeFromNib() {
layer.shadowColor = UIColor(red: 157.0/255.0, green: 157.0/255.0, blue: 157.0/255.0, alpha: 0.5).CGColor
layer.shadowOpacity = 0.8
layer.shadowRadius = 5.0
layer.shadowOffset = CGSizeMake(0.0, 2.0)
}
}
Don't forget to add some constraints to the view inside the cell.

You can arrange your collection view layout in "Size insepector"
And customise your image in the cell.

Related

Does iOS 14 have some breaking changes that disable vertical scroll for Collection View? [duplicate]

I have a search form that uses a tableview. After updating Xcode 12 today the UISwitch, UITextField, UISlider no longer work when nested inside a UITableViewCell. Is there a property that has changed that I need to set to make this work again?
To be sure it wasn't just my project, I created a new project and nestled a UITextField inside of it and it doesn't work either.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
let textField = UITextField(frame: CGRect(x: 5, y: 5, width: 400.0, height: 25.0))
textField.delegate = self
textField.backgroundColor = .blue
cell.addSubview(textField)
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("this will get called even when selecting the UITextField")
}
func textFieldDidBeginEditing(_ textField: UITextField) {
print("this is never called")
}
Your code was always wrong:
cell.addSubview(textField)
You must never add a subview to a cell. Add the subview to the cell's contentView.
The same happened to me since I upgraded to iOS 14.
This has worked for me when I add the subViews directly to the cell,
cell.contentView.isUserInteractionEnabled = true
Had similar issue, and been going on around for it... what was issue with my code is that under UITableViewCell I was doing this:
didSet {
if contentView.backgroundColor == backgroundColor { return }
contentView.backgroundColor = backgroundColor
for v in otherView.subview { v.backgroundColor = backgroundColor }
}
Removing this line here contentView.backgroundColor = backgroundColor did the trick. Cell is now visible and there is no duplicated contentView
Maybe this will help someone, since I found only answers regarding adding subviews directly to cell instead to cell.contentView
EDIT 1:
Okay, just wanted to update you on situation, issue was that my subviews where of type UIStackView and I had used subview where I actually should have used arrangedSubviews
Hope this will help someone

How to view remove subview?

let overlayView = UIView()
overlayView.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.35)
overlayView.frame = self.view.bounds
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if indexPath.row == 0{ self.view.addSubview(overlayView) {
performSegue(withIdentifier: "language", sender: nil)
}
}
To do what you ask you could have the overlay view as an optional, class level property, and try to remove it when the view appears
class VC1: UIViewController {
var overlayView: UIView?
override func viewDidAppear() {
super.viewDidAppear()
overlayView?.removeFromSuperView()
}
Or you could use a protocol / delegate pattern to inform VC1 that VC2 was bring removed and use that method to remove the overlayView. This is a cleaner solution.
However if you're doing whatever I think you are tyring to do (see my comment) I think there is a better approach - handle it all in the second view controller. Make the main view of second view controller do the masking by setting it's alpha, then add a container view to the centre of that view and add all your content/functionality into that container view. This way when you dismiss the second the blur layer will go with it.

Add border to CollectionView

I have a collection view with multiple cells in it, I figured out how to add a border to each cell but still stuck with adding a border to the CollectionView (expected Result).
Currently, I'm placing the button outside the CollectionView but don't know how to make it looks like the expected result.
For set the collection view border you can follow this
collectionView.layer.borderColor = UIColor.gray.cgColor
collectionView.layer.borderWidth = 5
And for setting cell position to the middle you need to set the cell insect.
You can easily set the cell insect from storyboard from this. Update the Section Insects value that you want.
you can try like this:
#IBOutlet var CollectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
CollectionView.delegate = self
CollectionView.dataSource = self
CollectionView.layer.borderColor = UIColor.gray.cgColor //change to required color
CollectionView.layer.borderWidth = 5 //change to required borderwidth
}

Dynamic UICollectionView inside dynamic UITableViewCell

I have a collection view that is dynamic and can have any number of cells in it. It is positioned inside a table view cell.
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
My table view is correctly configured to be dynamic because the other cells work fine so the issue is not there.
Here is what I currently have... As you can see there is no collection view below
This is what my desired out come is... (Forcing a height constraint on the collection view)
I have configured constraints on all sides of the collection view correctly, as it works when I give a fix height constraint. But this defeats the object of a dynamic collection view...
I have linked an outlet to the UICollectionViewFlowLayout and set an estimated cell size and given the cell the correct constraints on the label inside as you can see in the image where I forced the height constraint.
Create a subclass for collectionView and override intrinsicContentSize.
class DynamicCollectionView: UICollectionView {
override func layoutSubviews() {
super.layoutSubviews()
if !__CGSizeEqualToSize(bounds.size, self.intrinsicContentSize) {
self.invalidateIntrinsicContentSize()
}
}
override var intrinsicContentSize: CGSize {
return collectionViewLayout.collectionViewContentSize
}
}
In Interface builder change the class of your collectionView to DynamicCollectionView (subclass UICollectionView).
Set estimated cell size of UICollectionViewFlowLayout.
flowLayout.estimatedItemSize = CGSize(width: 1,height: 1)

Width of UITableView content view does not match Container

I have a TableVC embedded in a Container. The width of the Container running on an iPhone5 is 320. However the width of the ContentView in the TableView cell is 600. How can I make them match? (+/- padding). Am I missing a constraint? I have also tried setNeedsLayout() and layoutSubViews() in cellForRowAtIndexPath and in the custom cells subclass, but this doesn't seem to work either.
In the picture below, I want the width of the darkgrey to match the light grey (+- padding)
Any help much appreciated.....
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("EventCell") as! CustomResultsTVCell
// cell.setNeedsLayout()
// cell.layoutSubviews()
// cell.layoutIfNeeded()
let barViewWidth = Float(cell.barView.frame.width)
print("barview width is \(barViewWidth)")
// prints 584
let contentViewWidth = cell.myContentView.frame.width
print("contentView width is \(contentViewWidth)")
// prints 600
The CustomCell class is
import Foundation
import UIKit
class CustomResultsTVCell: UITableViewCell {
#IBOutlet weak var myContentView: UIView!
#IBOutlet weak var barView: UIView!
override func awakeFromNib() {
super.awakeFromNib()
// super.layoutSubviews()
// setNeedsLayout()
// layoutSubviews()
layoutIfNeeded()
}
Can you check property of your leading and trailing constraints. Make sure it unchecked relative to margin for both first item and second item.
see attached screenshots if it helps you.
Hope this will help you to fix your issue.