Set UITableView header view height depends on its childviews - swift

I have a headerview in my UITableView but I can't find a solution to make it dynamically height. In my headerview I have a UITextView which height depends on its content.
What I have tried so far.
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
sizeHeaderToFit()
}
func sizeHeaderToFit() {
let headerView = mTabView.tableHeaderView!
mTxtViewDescription.sizeToFit()
mConDescriptionHeight.constant = mTxtViewDescription.frame.height
print(mContainerView.frame.maxY)
headerView.frame.size.height += mTxtViewDescription.frame.height
}
The green area is my headerview

Changing the height of the frame of a UITableView header that's already been set won't recalculate the height, meaning you can't just change the height of a tableHeaderView as its layout is managed by the tableView. You need to set the tableHeaderView again, setting the property triggers the new calculation.
There are a number of questions going into detail about this, several linked from this one.

Related

Automatic height adjustment for static UITableViewCell doesn't work

I have a static UITableView and I want to set the row height for three of the cells dynamically. So in viewDidLoad() I implemented the following code:
tableView.estimatedRowHeight = 100
tableView.rowHeight = UITableView.automaticDimension
I also implemented the heightForRowAt method:
(The first two cells of the first section should have a fixed height)
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath.section == 0 && indexPath.row == 0 {
return CGFloat(85)
} else if indexPath.section == 0 && indexPath.row == 1 {
return CGFloat(145)
}
return UITableView.automaticDimension
}
This the result which I'm currently getting:
I changed the lines of the labels to 0, too and the constraints of the labels inside the cells are 0, 12, 0, 12 (top, right, bottom, left).
Does anybody know, why the cell in section 3 doesn't display the data in the right way?
Edit:
(How it looks after the implementation of the suggestion above)
Because sizeToFit() did not work for you, we are going to try something a little more involved.
The cell in section 3 is displaying the data the right way. This is because UILabels don't automatically adjust their height to accommodate the text inside. Here's what you need to do:
1. Create a height constraint for your UILabel In your interface builder, add a constraint for the height of the UILabel in section 3's cell. Connect this height constraint to your view controller's class via an #IBOutlet:
class YourViewController: UIViewController {
#IBOutlet var cellLabel: UILabel!
#IBOutlet var cellLabelHeight: NSLayoutConstraint!
...
}
2. Add String extension that calculates height I am unsure of where/when you are setting the text of the UILabel in question, but I know you are doing this somewhere as you have described it as being "dynamic". Whenever you do set the text of the UILabel in question, you now also need to change the constant of the height constraint that we made in order to accommodate this text. So, we need to be able to calculate the height of the UILabel based on its width and font. We can add an extension to String in order to do this:
extension String {
func height(withConstrainedWidth width: CGFloat, font: UIFont) -> CGFloat {
let constraintRect = CGSize(width: width, height: .greatestFiniteMagnitude)
let boundingBox = self.boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, attributes: [.font: font], context: nil)
return ceil(boundingBox.height)
}
}
3. Set the height constraint's constant based off the UILabel's text The final step is to set the height of the UILabel height constraint we made by using the extension we just created:
cellLabel.text = "DummyDataDummyDataDummyDataDummyDataDummyDataDummyDataDummyDataDummyData"
//This will be called immediately after you set the text for the UILabel in question
cellLabelHeight.constant = cellLabel.text.height(withConstrainedWidth: cellLabel.frame.width, font: cellLabel.font)
The cell in section 3 is displaying the data the right way. Unless you tell it otherwise, a UILabel will not automatically adjust to accommodate the text within it.
What I need you to do is select the UILabel in question, then in the attributes inspector, set the Number of Lines to 0.
You also said that this UILabel is dynamic, meaning you are setting it's text somewhere in your code. Immediately after you set this UILabel's text, you are going to want to call myLabel.sizeToFit(). This should adjust the label's height to accommodate the text within.
If this doesn't work, I have another, more involved solution that should work for you.
Please look at the below;
Select your cellLabel and set the Lines value to 0:
Also apple says Self-Sizing
Summary :
lay out your table view cell’s content within the cell’s content view. To define the cell’s height, you need an unbroken chain of constraints and views (with defined heights) to fill the area between the content view’s top edge and its bottom edge. If your views have intrinsic content heights, the system uses those values. If not, you must add the appropriate height constraints, either to the views or to the content view itself.
Change the bottom constraint of the AuthorLabel from equal to Greater than or equal

Autolayout CollectionView

I am trying to use autolayout for a CollectionVIew, but when I run it in iPhone plus, a space is created between the cells.
iPhone 8 Plus
iPhone 8
I guess you already set the cell size from collection view's delegate method. One thing you need to do is to call invalidateLayout() whenever the collection view's frame changes, so it will re-render the cells.
IE:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
collectionView.collectionViewLayout.invalidateLayout()
}
I solved it by setting in ViewDidLoad the size of the cell (I just set the width, but you could set the height too)
let layout = YourCollectionView.collectionViewLayout as? UICollectionViewFlowLayout
layout?.estimatedItemSize = CGSize(width: view.bounds.width / 2 , height: 114)

unable to scroll the textview in Swift

I have a TextView as shown below
I am not able to scroll the text view , I have added UITextViewDelegate in UIViewController class as well as set isUserInteractionEnabled property in textViewDidBeginEditing
func textViewDidBeginEditing(_ textView: UITextView) {
textView.backgroundColor = UIColor.lightGray
textView.isEditable = false
textView.isUserInteractionEnabled = true
textView.isScrollEnabled = true
}
What did I need to do?
Also, the scrolling is enabled in attribute inspector
This issue has occurred because the actual UITextView's size was more than screen size as shown below
The real answer is that the UITextView needs its content frame height inferior to its content size height to be able to scroll.
In your case, the content frame height is equal to the content size, so it doesn't scroll.
You just have to set the leading left, trailing, top space and bottom space to the View, but first make sure the Text View is smaller than the actual View (parent).
It starts to get complicated when you have a UITextView on a UIView which is either a view on a UIScrollView or directly on a UIScrollview.
The best thing to do, is to give each of them their own actions when scrolling.
Firstly, make sure you have all of your delegates for EVERYTHING set.
Make sure your UITextViews are not user restricted for what they don't need to be.
What I have to do in one of my published apps is this👇
func scrollViewWillBeginDragging(_ scrollView: UIScrollView)
{
if scrollView == textView1
{
// Do something if you actually want to, or just let textView1 scroll as intended
}
else if scrollView == textView2
{
// Do something if you actually want to, or just let textView2 scroll as intended
}
else if scrollView == zoomingScroll
{
// Do something if you need to or leave it
}
else
{
// Do something with all the other scrollable views if you need to
}
}

Swift, Auto Resize Custom Table View Cells

In my app, I have a table view with an image, label and text view in each cell. I would like to be able to auto-resize the cells depending on the amount of content in the text view. (The text view is the lower most text.)
So far, I have added the correct constraints; leading, trailing, top and bottom to the text view and have disabled scrolling and editing.
In my tableViewController.swift file, I have written this code:
override func viewWillAppear(_ animated: Bool) {
tableView.estimatedRowHeight = 100
tableView.rowHeight = UITableViewAutomaticDimension
}
However, this is not working as when I add more text to the text view, it just cuts off.
Maybe this has something to do with the card like look, I have got a UIView in each cell acting as a card.
I honestly don't know what I am doing wrong
A picture is below of what my app looks like and if anyone could help that would be greatly appreciated
Check if your constraints are like this(based on your image) :
imageView : set to Top and Leading of your container, with fix height and width values.
label : you can set it to top and horizontal space of your image, with fix height and width as well.
textView : leading to image, top space to label, trailing and bottom to container.
And keep using
tableView.estimatedRowHeight = 100
tableView.rowHeight = UITableViewAutomaticDimension
in your viewWillAppear()
Update for swift 4.2
Use:
UITableView.automaticDimension
Instead of:
UITableViewAutomaticDimension
Make sure that the content mode is set to Scale To Fill of your UITextView
Make sure that there are no height constraints for the UITextView and the card UIView
Try to add the estimated height into viewDidLoad:
override func viewDidLoad() {
tableView.estimatedRowHeight = 100
tableView.rowHeight = UITableViewAutomaticDimension
}
Maybe the AutoHeight is not working because of the UIView above the UITextView. Try to call the sizeToFit and layoutIfNeeded methods for the UIView in the cellForRowAt:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Identifier", for: indexPath) as! CustomTableViewCell
cell.vwCard.sizeToFit()
cell.vwCard.layoutIfNeeded()
return cell
}
You can also try the sizeToFit and layoutIfNeeded as well for the UITextView.
Hope this works........
Set bottom of your textView with bottom of that white UIView and make sure that white UIView has left,right,top and bottom constraints :)
Same type of example is explained here programmatically....

UIImageView is not auto height in StackView with TableViewCell

This is the view hierarchy
I want the PhotoImgView auto height depends on the Image size
The image is download from server
I use KingFisher to download the image
when download finished, I set PhotoImgView's height constraint, and do layoutIfNeeded() in the cell class
but it's not update UI immediately
when I scroll to another cell, and let the cell invisible, and then scroll back, the cell would be right
How can I do this?
Same issue with the collectionView, I set collectionview's height constraint after collectionview.reloaData and get collectionview.contentSize.height
Try this:
Replace your current layoutIfNeeded() with this:
DispatchQueue.main.async {
self.layoutIfNeeded()
}
Try to call setNeedsLayout() before layoutIfNeeded().
To get right result for collection view height you can try:
collectionView.reloadData()
collectionView.setNeedsLayout()
collectionView.layoutIfNeeded()
collectionView.collectionViewLayout.invalidateLayout()