Problem with dynamic UITableView cell heights - ios

I want my cells to have dynamic height. I use the below code:
let tableView: UITableView = {
let view = UITableView()
view.register(MyTableViewCell.self, forCellReuseIdentifier: MyTableViewCell.reuseIdentifier)
view.rowHeight = UITableView.automaticDimension
view.estimatedRowHeight = 150
view.separatorStyle = .singleLine
view.isScrollEnabled = true
return view
}()
The cell contains only label that is given one constraint- to be centered inside a cell:
private func setupView() {
addSubview(titleLabel)
titleLabel.snp.makeConstraints { maker in
maker.center.equalToSuperview()
}
}
the label's definition:
let titleLabel: UILabel = {
let label = UILabel()
label.textColor = .black
label.textAlignment = .center
label.numberOfLines = 0
return label
}()
The label's text is then assigned in cellForRowAt method but in each case returns same hight even though the text is sometimes 4 lines and cell's hight should be stretched.
What is there that I'm missing in the above code? Thanks

The cell's content needs to have autolayout constraints setup in such way that there is constraint connection from the top to the bottom of the cell, for the automatic dimensions to work.
private func setupView() {
addSubview(titleLabel)
titleLabel.snp.makeConstraints { maker in
maker.edges.equalToSuperview()
//or add .top, .left, .right, .bottom constraints individually,
//if you need to add .offset() to each of the sides
}
}

You should give the label top , bottom , leading and trailing constraints to make the height dynamic

Related

iOS tableHeaderView in UITableViewController never displayed

I'm trying to implement a tableViewHeader (and not "viewForHeaderInSection") for my tableview in a UITableViewController "TBVC1".
I tried two solution (don't work of course...):
1ST : Added a UIView in the top of my UITableViewController in my storyboard. If I add a UILabel (with constraints etc) in this UIView, and try to display my View TBVC1.... I see nothing. The full View is empty. But, if I delete the UILabel inserted in the header UIView, I can see all my cells and the headerView background Color...
Do you have any idea why I can't put any UI component in this UIView?
2ND : If I try load a specific nib UIView like this :
Bundle.main.loadNibNamed("Title", owner: nil, options: nil)!.first as! UIView
self.tableView.setTableHeaderView(headerView: customView)
self.tableView.updateHeaderViewFrame()
extension UITableView {
/// Set table header view & add Auto layout.
func setTableHeaderView(headerView: UIView) {
headerView.translatesAutoresizingMaskIntoConstraints = false
// Set first.
self.tableHeaderView = headerView
// Then setup AutoLayout.
headerView.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
headerView.widthAnchor.constraint(equalTo: self.widthAnchor).isActive = true
headerView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
}
/// Update header view's frame.
func updateHeaderViewFrame() {
guard let headerView = self.tableHeaderView else { return }
// Update the size of the header based on its internal content.
headerView.layoutIfNeeded()
// ***Trigger table view to know that header should be updated.
let header = self.tableHeaderView
self.tableHeaderView = header
}
}
it doesn't work too... my full View is empty...
Do you have any ideas why I don't succeed to display a simple UILabel in my UIView for the tableViewheader?
I'm not sure my way is proper, but every time I set tableHeaderView, I also set its height manually.
If you want to use auto-layout in your tableHeaderView, you can call systemLayoutSizeFitting(UIView.layoutFittingCompressedSize) on the header view to get the calculated size and assign the height to headerView.
You can try this simple example in Playground.
import UIKit
import PlaygroundSupport
class MyViewController: UITableViewController {
override func loadView() {
super.loadView()
let headerView = UIView()
headerView.backgroundColor = .red
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.text = "Hello World!"
label.textAlignment = .center
label.textColor = .white
headerView.addSubview(label)
let attributes: [NSLayoutConstraint.Attribute] = [.leading, .top, .centerX, .centerY]
NSLayoutConstraint.activate(attributes.map {
NSLayoutConstraint(item: label, attribute: $0, relatedBy: .equal, toItem: headerView, attribute: $0, multiplier: 1, constant: 0)
})
// We have to set height manually, so use `systemLayoutSizeFitting` to get the layouted height
headerView.frame.size.height = headerView.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize).height
tableView.tableHeaderView = headerView
}
}
PlaygroundPage.current.liveView = MyViewController()

Label on Row Separator - Swift Tableview - Hourly Calendar

I want to create an hourly calendar view that is relatively basic, but similar to Apple's native calendar view. How do you add labels to be in line with the row/cell separators, and not contained in a cell. Like this:
Is there a property that lets you add a label to the lines? Do the labels have to be placed outside of the table view? Or is there a separate table that occurs?
In terms of creating colored blocks to represent events on the calendar, what would be the best way to go about doing this? Would it just be a CGRect in a prototype cell? Would you need to create separate xib files?
Thanks in advance for the help, I am still new to learning Swift!
It's not possible (or technically, it would be possible, but the overhead is too high, considering your other options).
Instead of using cell separators, set separatorStyle = .none, and draw the line in the cell (e.g., as a UIView with view.height = 1 and view.backgroundColor = .grey) and normally add the label in the cell.
Basically the solution is very simple: disable standard separator lines, and rather draw separator inside the cell (bottom or top) along with the labels. That's how I've been doing things when the client asked for some custom fancy separators - I added a custom line at the bottom of the cell and used the rest of the cell's contentView as for the cell's content.
EDIT
You can use a following example to start with (note that this is just one of several different approaches how to manage it):
class TimeCellViewController: UITableViewController {
override func loadView() {
super.loadView()
// you can use UITableViewAutomaticDimension instead of static height, if
// there will be variable heights that you don't know upfront
// https://stackoverflow.com/a/18746930/2912282
// or mine:
// https://stackoverflow.com/a/47963680/2912282
tableView.rowHeight = 80
tableView.estimatedRowHeight = 80
tableView.separatorStyle = .none
// to allow scrolling below the last cell
tableView.tableFooterView = UIView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 40))
tableView.register(TimeCell.self, forCellReuseIdentifier: "timeCell")
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 24
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "timeCell", for: indexPath) as! TimeCell
if indexPath.row > 0 {
cell.topTime = "\(indexPath.row):00"
} else {
cell.topTime = ""
}
cell.bottomTime = "\(indexPath.row + 1):00"
return cell
}
}
class TimeCell: UITableViewCell {
// little "hack" using two labels to render time both above and below the cell
private let topTimeLabel = UILabel()
private let bottomTimeLabel = UILabel()
private let separatorLine = UIView()
var topTime: String = "" {
didSet {
topTimeLabel.text = topTime
}
}
var bottomTime: String = "" {
didSet {
bottomTimeLabel.text = bottomTime
}
}
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
selectionStyle = .none
contentView.addSubview(topTimeLabel)
contentView.addSubview(bottomTimeLabel)
contentView.addSubview(separatorLine)
topTimeLabel.textColor = UIColor.gray
topTimeLabel.textAlignment = .right
bottomTimeLabel.textColor = UIColor.gray
bottomTimeLabel.textAlignment = .right
separatorLine.backgroundColor = UIColor.gray
bottomTimeLabel.translatesAutoresizingMaskIntoConstraints = false
topTimeLabel.translatesAutoresizingMaskIntoConstraints = false
separatorLine.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
bottomTimeLabel.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 0),
bottomTimeLabel.centerYAnchor.constraint(equalTo: self.bottomAnchor),
bottomTimeLabel.widthAnchor.constraint(equalToConstant: 50),
topTimeLabel.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 0),
topTimeLabel.centerYAnchor.constraint(equalTo: self.topAnchor),
topTimeLabel.widthAnchor.constraint(equalToConstant: 50),
separatorLine.leftAnchor.constraint(equalTo: bottomTimeLabel.rightAnchor, constant: 8),
separatorLine.bottomAnchor.constraint(equalTo: self.bottomAnchor),
separatorLine.heightAnchor.constraint(equalToConstant: 1),
separatorLine.rightAnchor.constraint(equalTo: self.rightAnchor, constant: 0),
])
// if you use UITableViewAutomaticDimension instead of static height,
// you will have to set priority of one of the height constraints to 999, see
// https://stackoverflow.com/q/44651241/2912282
// and
// https://stackoverflow.com/a/48131525/2912282
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}

create UITableViewCell constraint programmatically

This is all taking place within this class:
class CustomCell2: UITableViewCell {
When I print the value of an existing width constraint (label = 0.7 * width of the cell) that was set in Storyboard, I see this:
<NSLayoutConstraint:0x36b8750 UILabel:0x3d2aac0'Label'.width == 0.7*appName.CustomCell2:0x3e01880'CustomCell2'.width>
When I try to create the same constraint programmatically, I get the error "The view hierarchy is not prepared for the constraint:"
<NSLayoutConstraint:0xee08590 UILabel:0x3d2aac0'Label'.width == 0.9*appName.CustomCell2:0x3e01880'CustomCell2'.width>
Seems exactly the same, so why can't that constraint be added?
Constraint code in awakeFromNib() of CustomCell2:
let widthConstraint = NSLayoutConstraint(item: labelName, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: self, attribute: NSLayoutAttribute.width, multiplier: 0.9, constant: 0)
labelName.addConstraint(widthConstraint)
Rest of the error message:
When added to a view, the constraint's items must be descendants of that view (or the view itself). This will crash if the constraint needs to be resolved before the view hierarchy is assembled. Break on -[UIView(UIConstraintBasedLayout) _viewHierarchyUnpreparedForConstraint:] to debug.
2017-12-03 20:18:51.183 appName[899:684382] View hierarchy unprepared for constraint.
Constraint: <NSLayoutConstraint:0xee08590 UILabel:0x3d2aac0'Label'.width == 0.9*appName.CustomCell2:0x3e01880'CustomCell2'.width>
Container hierarchy:
<UILabel: 0x3d2aac0; frame = (281 43; 674 54); text = 'Label'; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x4233d30>>
View not found in container hierarchy: <appName.CustomCell2: 0x3e01880; baseClass = UITableViewCell; frame = (0 0; 963 160); layer = <CALayer: 0xee08250>>
That view's superview: NO SUPERVIEW
Unable to install constraint on view. Does the constraint reference something from outside the subtree of the view? That's illegal. constraint:<NSLayoutConstraint:0xee08590 UILabel:0x3d2aac0'Label'.width == 0.9*appName.CustomCell2:0x3e01880'CustomCell2'.width> view:<UILabel: 0x3d2aac0; frame = (281 43; 674 54); text = 'Label'; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x4233d30>>
Thanks!
you should be adding your constraints in init for the cell, assuming it will be a dequeued reusable cell, remember to use contentView instead of View for the bounds of the cell:
class CustomCell2: UITableViewCell {
//MARK: Subviews
//Add View Programmatically or in xib
let titleLabel: UILabel = {
let label = UILabel()
label.text = " Title "
//…
label.translatesAutoresizingMaskIntoConstraints = false //Must use
return label
}()
//…
//MARK: init
//Add Subviews and then layout Contraints to the Cell’s contentView
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
addSubViewsAndlayout()
}
/// Add and sets up subviews with programmically added constraints
func addSubViewsAndlayout() {
contentView.addSubview(titleLabel) //will crash if not added
let screenwidth = UIScreen.main.bounds.width //get any other properties you need
titleLabel.topAnchor.constraint(equalTo: self.contentView.topAnchor, constant: 12.0).isActive = true
titleLabel.heightAnchor.constraint(equalToConstant: 30).isActive = true
titleLabel.leftAnchor.constraint(equalTo: self.contentView.leftAnchor, constant: 12).isActive = true
titleLabel.rightAnchor.constraint(equalTo: otherViewToTheSide.rightAnchor, constant: -24).isActive = true
//...
I also like to implement the following methods instead of using hard coded values / strings.
/// Get the Height of the cell
/// use this in heightForRowAt indexPath
/// - Returns: CGFloat
class func height() -> CGFloat {
return 175
}
//CustomCell2.height()
/// Get the string identifier for this class.
///
/// - Retruns: String
class var identifier: String {
return NSStringFromClass(self).components(separatedBy: ".").last!
}
//use when registering cell:
self.tableView.register(CustomCell2.self, forCellReuseIdentifier: CustomCell2.identifier)
You can create UITableViewCell constraint Programatically like :
class ViewController: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(CustomCell2.self, forCellReuseIdentifier: "cell")
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 2
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as? CustomCell2 else { return UITableViewCell() }
cell.model = CellModel(labelString: "set constriant by code")
return cell
}
}
Define Model :
struct CellModel {
let labelString : String
}
Define custom Cell :
class CustomCell2 : UITableViewCell {
private let label : UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false // enable auto-layout
label.backgroundColor = .green // to visualize
label.textAlignment = .center // text alignment in center
return label
}()
private func addLabel() {
addSubview(label)
NSLayoutConstraint.activate([
// label width is 70% width of cell
label.widthAnchor.constraint(equalTo: widthAnchor, multiplier: 0.7),
// center along horizontally
label.centerXAnchor.constraint(equalTo: centerXAnchor)
])
}
var model : CellModel? {
didSet {
label.text = model?.labelString ?? "Test"
}
}
// Init
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
addLabel()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Output
A user on Apple's Developer Forums pointed me in the right direction. The constraint was between the label and the cell (the cell being referred to as 'self' in the class for the custom cell) and the answer here was that I had to addConstraint to the cell instead of adding it to the label. Same exact constraint definition, but it only worked as self.addConstraint() and gave the error "The view hierarchy is not prepared for the constraint" when coded as labelName.addConstraint()

UILabel size changes when scrolling in UICollectionView

I have a custom UICollectionViewCell which I am overwriting. It has a property called nameLabel of type UILabel. I set initialize it without a frame and set the numberOfLines to 3.
let nameLabel: UILabel = {
let label = UILabel()
label.numberOfLines = 3
label.sizeToFit()
return label
}()
The name label has the following VFL constraint applied to it:
addConstraintsWithFormat("V:[v0]-10-[v1]-10-|", views: nameLabel, userLabel)
where addConstraintsWithFormat is defined as the following from Brian Voong's UICollectionView example:
extension UIView {
func addConstraintsWithFormat(format: String, views: UIView...) {
var viewsDictionary = [String: UIView]()
for (index, view) in views.enumerate() {
let key = "v\(index)"
viewsDictionary[key] = view
view.translatesAutoresizingMaskIntoConstraints = false
}
addConstraints(NSLayoutConstraint.constraintsWithVisualFormat(format, options: NSLayoutFormatOptions(), metrics: nil, views: viewsDictionary))
}
}
What happens is, say I have one cell whose nameLabel text is rendered in three lines (enough lines to merit three lines of wrapping, given the constraints).
So what happens is, I scroll to that cell, it shows the nameLabel as having three lines, I scroll past that cell. When I scroll back up to that cell, the very same UILabel now has one line.
How can I keep the flexible display of the UILabel size based on the content it renders?
I was able to reproduce your error, implementing it the way you have above makes the error...
I didn't see how you implemented it inside your -cellForItemAtIndexPath though, Fixed it with some modification from what you have provided, here is my -cellForItemAtIndexPath looks like:
//--
// UICollectionView Delegates
func collectionView(collectionView: UICollectionView,
cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("cvCell", forIndexPath: indexPath)
// just to remove multi existence of identical views
//
cell.subviews.forEach { (view) in
view.removeFromSuperview()
}
let nameLabel: UILabel = {
let label = UILabel()
// declare constant configurations here
//
label.numberOfLines = 3
label.textAlignment = NSTextAlignment.Center
label.text = "Index: \(indexPath.row)\n and this is quite a long text that will occuply 3 lines"
return label
}()
// this is just an example base frame
//
nameLabel.frame = CGRectMake(0, 0, cell.frame.size.width/*your width*/, CGFloat.max)
nameLabel.sizeToFit()
cell.addSubview(nameLabel)
// ...
//
// updates constraints here
return cell
}
Hope this would help you.. Cheers! :)
I ended up solving the error but setting Visual Format Strings of Auto Layout Constraints.
I hadn't applied the horizontal constraint, neither had I given the UILabel a fixed width. My new constraints are the following:
addConstraintsWithFormat("H:|-20-[v0(200)]", views:nameLabel)
addConstraintsWithFormat("V:[v0]-10-[v1]-10-|", views: nameLabel, userLabel)
where as before I only had
addConstraintsWithFormat("V:[v0]-10-[v1]-10-|", views: nameLabel, userLabel)
I didn't use sizeToFit() at all. Only the following were my UILabel settings in my UICollectionViewCell class.
let nameLabel: UILabel = {
let label:UILabel = UILabel(frame: CGRectMake(0, 0, 200, 200))
label.numberOfLines = 3
label.lineBreakMode = NSLineBreakMode.ByWordWrapping
let font = UIFont(name: "HelveticaNeue-Bold", size: 20.0)
label.font = font
return label
}()
and then I set the text later in the class
nameLabel.text = name

Get UITextView dynamic height with auto layout after setting text

I have a UITextView not scrollable with auto layout set by interface builder, and the text increase or decrease dynamically with no problem, but i want know what is the new UITextView height after setting text, i'm trying to do this:
NSLog(#"text before: %.2f",self.myText.frame.size.height);
[self.myText setText:self.string];
NSLog(#"text after: %.2f",self.myText.frame.size.height);
this is the result:
text before: 47.50
text after: 47.50
the text is increased in the view when i run it, but the size is the same, how i can get the real height after setting text?
All you have to do is:
set up all your constraints except the height one AND
set textView's scrollEnabled property to NO
The last part is what does the trick.
Your text view will size automatically depending on its text value.
If you prefer to do it all by auto layout:
In Size Inspector:
Set Content Compression Resistance Priority Vertical to 1000.
Lower the priority of constraint height for your UITextView. Just make it less than 1000.
In Attributes Inspector:
Uncheck Scrolling Enabled.
I have used the code given on following link AutoLayout with Dynamic UITextView height and it worked for me :)
This should work:
NSLog(#"text before: %.2f",self.myText.frame.size.height);
[self.myText setText:self.string];
[self.myText layoutIfNeeded]; // <--- Add this
NSLog(#"text after: %.2f",self.myText.frame.size.height);
Here's an example implementation on my Github: https://github.com/guillaume-algis/SO-27060338
Swift 3.0
textView.isScrollEnabled = false
This allow AutoLayout to do its job.
Use below code:
Objective-C Code
[textView setScrollEnabled:NO];
Swift Code
textView.isScrollEnabled = false
Just after changing the text call
[self.myText sizeToFit];
Unlike UILabel, UITextView's has no intrinsic size property. So how I did it was set up the UITextView's height constraint, hook it via IBOutlet, and change its value in textViewDidChange or when text changes.
#IBOutlet weak var textViewHeight: NSLayoutConstraint!
func textViewDidChange(textView: UITextView) {
// dynamic height adjustments
var height = ceil(textView.contentSize.height) // ceil to avoid decimal
if height != textViewHeight.constant { // set when height changed
textViewHeight.constant = height
textView.setContentOffset(CGPointZero, animated: false) // scroll to top to avoid "wrong contentOffset" artefact when line count changes
}
}
- (void)textViewDidChange:(UITextView *)textView
{
UIFont *myFont = [UIFont systemFontOfSize:14];
CGSize size = [self sizeOfText:textView.text widthOfTextView:TextviewWidth withFont:myFont];
NSLog(#"Height : %f", size.height);
}
-(CGSize)sizeOfText:(NSString *)textToMesure widthOfTextView:(CGFloat)width withFont:(UIFont*)font
{
CGSize ts = [textToMesure sizeWithFont:font constrainedToSize:CGSizeMake(width-20.0, FLT_MAX) lineBreakMode:NSLineBreakByWordWrapping];
return ts;
}
select textview and uncheck "Scrolling enabled"
select textview from top menu "Editor > size to fit content"
select the view below it, set its top constraints with the textview bottom to whatever margin you want, then go to "Size Inspector",double click or edit the constraint you just added, and set the "Relation" to "Greater than or Equal"
Yet another approach is to use
myTextView.textContainer.heightTracksTextView = true
Which allows scroll to be enabled
Well, I haven't converted this code into swift4 syntax, but the logic will remain the same. This is an extension method for Xamarin.ios(C#).
public static nfloat GetEstimateHeight(this UITextView textView, UIView View)
{
var size = new CoreGraphics.CGSize(View.Frame.Width, height: float.PositiveInfinity);
var estimatedSize = textView.SizeThatFits(size);
return estimatedSize.Height;
}
The logic here that will work for swift is
var size = new CoreGraphics.CGSize(View.Frame.Width, height: float.PositiveInfinity);
var estimatedSize = textView.SizeThatFits(size);
var textViewFinalHeight = estimatedSize.Height;
Just an addition as per #Pavel Gurov's answer. If you already set up your height constraint, simply make it inactive. Also worth to call .sizeToFit() afterwards to make sure resize action is performed.
theTextViewHeightConstraint.isActive = false
theTextView.isScrollEnabled = false
theTextView.text = "some text"
theTextView.sizeToFit()
the textview height increase by using pure swift code design. I am just do coding part only.
I take this idea from
https://stackoverflow.com/a/45071002/9110213
First thing create the textView
import UIKit
class TextFieldCell: UITableViewCell {
lazy var btnEdit: UIButton! = {
let button = UIButton()
button.translatesAutoresizingMaskIntoConstraints = false
button.addTarget(self, action: #selector(self.actionEdit(_:)), for: .touchUpInside)
button.setTitle("Edit", for: .normal)
button.titleLabel?.font = UIFont(name: "ProximaNova-Medium", size: 18)
button.setTitleColor( UIColor(red: 0.29, green: 0.56, blue: 0.89, alpha: 1), for: .normal)
button.titleLabel?.textAlignment = .left
return button
}()
lazy var separatorView: UIView! = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
lazy var textView: UITextView! = {
let textView = UITextView.init(frame: .zero)
textView.translatesAutoresizingMaskIntoConstraints = false
textView.delegate = self
textView.isScrollEnabled = false
return textView
}()
lazy var titleLabel: UILabel! = {
let label = UILabel(frame: CGRect(x: 27, y: 318, width: 27, height: 12))
label.text = "Name"
label.font = UIFont(name: "ProximaNova-Medium", size: 10)
label.textColor = UIColor(red: 0.61, green: 0.61, blue: 0.61, alpha: 1)
label.textAlignment = .left
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
deinit {
self.titleLabel = nil
self.textView = nil
self.separatorView = nil
self.btnEdit = nil
}
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
self.selectionStyle = .none
self.addView()
self.setConstraint()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
extension TextFieldCell {
func addView(){
self.contentView.addSubview(self.btnEdit)
self.contentView.addSubview(self.titleLabel)
self.contentView.addSubview(self.textView)
self.contentView.addSubview(self.separatorView)
}
func setConstraint(){
// This part is very important to increase the textview height dyamically
let textViewHeight = self.textView.heightAnchor.constraint(equalToConstant: 27)
textViewHeight.priority = .defaultHigh
self.textView.setContentCompressionResistancePriority(.required, for: .vertical)
self.textView.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal)
NSLayoutConstraint.activate([
self.titleLabel.leadingAnchor.constraint(equalTo: self.contentView.leadingAnchor, constant: 27),
self.titleLabel.topAnchor.constraint(equalTo: self.contentView.topAnchor, constant: 38),
self.textView.topAnchor.constraint(equalTo: self.titleLabel.bottomAnchor, constant: 9),
self.textView.leadingAnchor.constraint(equalTo: self.titleLabel.leadingAnchor),
textViewHeight,
self.textView.trailingAnchor.constraint(equalTo: self.btnEdit.leadingAnchor, constant: -25),
self.btnEdit.centerYAnchor.constraint(equalTo: self.textView.centerYAnchor),
self.btnEdit.widthAnchor.constraint(equalToConstant: 40),
self.btnEdit.trailingAnchor.constraint(equalTo: self.contentView.trailingAnchor, constant: -33),
self.separatorView.topAnchor.constraint(equalTo: self.textView.bottomAnchor, constant: 10),
self.separatorView.heightAnchor.constraint(equalToConstant: 1),
self.separatorView.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor),
self.separatorView.leadingAnchor.constraint(equalTo: self.contentView.leadingAnchor, constant: 27),
self.separatorView.trailingAnchor.constraint(equalTo: self.contentView.trailingAnchor, constant: -15),
])
}
}
extension TextFieldCell {
#objc func actionEdit(_ sender: UIButton) {
}
}
extension TextFieldCell: UITextViewDelegate {
func notifyViewController(text:String){
}
func textViewDidEndEditing(_ textView: UITextView) {
}
}

Resources