Dynamic height for custom collection view cell by using autolayouts - ios

I had created a custom collection view cell. It has a UILabel, UIView, UIButton and then UITextView.
Requirements are:
UILabel's text size can be anything. Based on that it's content size label must re-size. It is working properly.
any number of views can be added to UIView. Based on that this UIView must be re-size.
UIButton is just a normal button. when we click on it, the below TextView will toggle.
The constraints that I applied are:

use this method and calculate the size that is appropriate for you and return it.
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let Labell : UILabel = UILabel()
Labell.text = self.items[indexPath.item]
let labelTextHeight = Labell.intrinsicContentSize.height
//calculate size for UIView, UIButton, TextView and then add it
return CGSize(width: /*fix width*/, height: labelTextHeigh + /*your UIView height and other height*/)
}
don't forget to extend your viewController from UICollectionViewDelegateFlowLayout

Related

How to increase the UICollectionview Cell Size equal to Screen Size in swift 4.2?

How to increase the UICollectionView Cell width & height equal to screen in swift 4.2 ?
Provided your UICollectionViewCell has a subview of UIImageView that is anchored to fill it completely(i.e. UIImageView is anchored UICollectionViewCell in top, bottom, left and right manner).
The following method can be used to size the UICollectionViewCell in accordance to the screen screen holding it, this will automatically result in the UIImageView being as big as the screen itself.
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return self.collectionView.bounds.size //to ensure that this works as intended set self.collectionView size be the screen size.
}
Please note that the UICollectionView is big enough to hold the size of the UICollectionViewCell that you seek.
You need to change your cell size to fit the collectionview. Add this in viewDidLoad
if let flow = self.collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
flow.itemSize = self.collectionView.frame.size
}

Dynamic Buttons in UIScrollView with Equal width and height

I want to display list of buttons in scrollview with dynamic height based on screen size. I can able to do this in UIView, but when I applied same auto layout approach in UIScrollView, it's not increasing the size of buttons. So please guide me How to increase the button size in UIScrollView based on screen size.
if button is dynamic and may be increase and decrease in future than you Should use CollectionView not ScrollView.
Drag CollectionView into ViewController.
Drag Cell in CollectionView.
Add button(or label based on your requirement) In Cell.set button(leading,trailing,top,bottom) == Cell(leading,trailing,top,bottom)
Write dataSource and delegate methods and UICollectionViewDelegateFlowLayout methods.
and change Following Methods to increase button height According To Screen
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: self.view.bounds.width/2, height: self.view.bounds.height*0.15)
}

Dynamic Cell Height for Custom Collection View Layout

I have a collection view which makes use of a custom layout. I'm trying to calculate the height dynamically, but the problem is sizeForItemAt:indexPath is called before cellForItemAt:indexPath.
My cells get loaded in cellForItemAt. But since sizeForItemAt is called before cellForItemAt, then I can't use my calculated height.
I know with Apple's FlowLayout I can just set the estimatedItemSize for the layout. I'm not sure how to do it with a custom layout.
Please advise. Thank you!
I had the same problem, my app uses custom layout with dynamic height. I found that with custom layout that doesn't extend UICollectionViewFlowLayout or any other default layout, dynamic height will not work because as per Apple documentation (and like you probably noticed) with a completely custom layout you have to predefine all the cells X, Y, width, height before the cell load and before you even have data.
I changed my custom layout to subclass UICollectionViewFlowLayout and implemented UICollectionViewDelegateFlowLayout. When this method is called the cell did not load yet but the cell's data is available since I know what the cell should look like (assuming you are using cell prototypes) I could calculate the cell width and height using its data and index, something like this:
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize {
// get the cell's data
if let data = self.fetchedResultsController.fetchedObjects![indexPath.row] as? YourDataType {
// carculate the cell width according to cell position
let cellWidth = carculateCellWidth(indexPath.row)
var cellHeight : CGFloat = 0
// assuming the cell have a label, set the label to have the same attributes as set in the storyboard or set programmatically
let label = UILabel()
label.numberOfLines = 0
label.font = UIFont.preferredFont(forTextStyle: .subheadline)
label.text = data.text
// carculate the height of the cell, assuming here the label width equal the cell width minus 10px left and right padding.
cellHeight += label.systemLayoutSizeFitting(CGSize(width:cellWidth-20, height: CGFloat(Float.greatestFiniteMagnitude))).height
return CGSize(width: cellWidth, height: cellHeight)
}
return .zero
}
This is not a very elegant solution but it works.

Swift auto layout in UICollectionView with intrinsic height of cells

I'm having a hard time with auto layout and UICollectionView. I have a vertical UICollectionVIewFlowLayout that contains two different types of cells, as in the image below:
The SingleCard cell contains a subview with an image (UIImageView). The HorizList cell contains a subview which is a horizontal UICollectionView (a list of thumbnail photos). The heights of the two cell types are as follows:
SingleCard: the width of the cell shall be the same as the screen width. The height shall be dynamic to the height of the UIImageView (to keep proportions of the image and have it fill screen width no matter of device size)
HorizList: the height is constant, say 200 points.
My attempt, in the CollectionViewController is to do
override func viewDidLoad() {
...
let layout = collectionView?.collectionViewLayout as! UICollectionViewFlowLayout
layout.estimatedItemSize = CGSize(width: 200.0, height: 235.0)
}
This I do to get the two cell's intrinsic size to apply. Then I do not implement
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
at all.
My question is, what do I implement in
override var intrinsicContentSize: CGSize {
??
}
for the two different cell types? Maybe this is not the only thing I need to do, if so I'm grateful for additional hints.
Thanks!
/ola

Access custom cell from XIB in UICollectionViewController for sizeForItemAtIndexPath

I have spent 3 days of searching and reading. In my IOS app I have a custom Cell for UICollectionView with xib File. In this custom cell I have 3 labels, images and buttons. 1 label from it is in the middle and always gets different sizes because it's multiline.
So I must calculate all items height. It's not the problem but the problem is only with this one multiline label. So I want calculate the size for each cell and get the size for sizeForItemAtIndexPath in UICollectionViewController.
After 3 days I think I cannot access this. Can I do this from the custom cell class? If yes, how? If I can access it in UICollectionViewController, how?
//MARK: - CollectionView Flow Layout
extension PhotosCollectionViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let viewSize = super.view.bounds.size
let spacing: CGFloat = 0.5
let width = (viewSize.width) - spacing - 10
/*
Here I need my cell with label name "Beschreibungstext"
to calculate the hight from the label with help from rectangle.
return CGSize(width: width, height: customhight)
*/
return CGSize(width: width, height: CGFloat(400))
}
}

Resources