Size height for item collection view - ios

What is the way to set the equal size height for all cells in collection view?
I have this method:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return getCellSize()
}
func getCellSize() -> CGSize {
let screenWidth: CGFloat = UIScreen.main.bounds.width
let spaceBetweenItems: CGFloat = CGFloat(2) * 10
let width: CGFloat = (screenWidth - 10 - spaceBetweenItems) / CGFloat(3.0)
return CGSize(width: width, height: CGFloat(140.0))
}
And these are my customs cell constraints:
This is my actual output:
What is wrong in my code or is missing one constraint ?

create Constraint CollectionViewHeight.
#IBOutlet weak var collectionViewHeight: NSLayoutConstraint!
and then, try this Code.
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let height = collectionView.collectionViewLayout.collectionViewContentSize.height
collectionViewHeight.constant = height
self.view.layoutIfNeeded()
}

In storyboard with collection view: select your collection view -> go to size inspector -> change field "Estimate size" from "automatic" to "none"
like here.
But then if you text will be too large it will be clipped with dots like "Some large text..", so you can change field "Autoshrink" of your UILabel in attribute inspector to "Minimum Font Scale".

Related

Change horizontal uicollectionivew width bases on uiLabel text

I have a horizontal collection view.
Each cell has a label and an image.
The problem that I am facing is that when label renders data from the server, sometimes the text is too big and overlaps the image because the width of each cell is fixed.
How can I change the width of the collection View view cell according to the data it contains so that the label does not overlap the image?
CollectionView does have a delegate method which returns cell size.
Please inherit UICollectionViewDelegateFlowLayout and implement the following method.
func collectionView(_ collectionView: UICollectionView,layout collectionViewLayout: UICollectionViewLayout,sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: 30, height: 30)
}
You can calculate your label width and return it to the function.
Hope this will help.
Calculate the width of the label text first with the font associated with the text.
extension String {
func size(with font: UIFont) -> CGSize {
let fontAttribute = [NSAttributedString.Key.font: font]
let size = self.size(withAttributes: fontAttribute)
return size
}
}
Return the calculated width along with collectionView height in collectionView(_, collectionViewLayout:_, sizeForItemAt)
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
// Note: Margins are spaces around the cell
// model[indexPath.row].text is the text of label to be shown
let newWidth = model[indexPath.row].text.size(with: labelFont!).width + margins + imageView.width
return CGSize(width: newWidth, height: collectionView.bounds.height)
}
Note:
Don't forgot to confirm your viewController to UICollectionViewDataSource, UICollectionViewDelegateFlowLayout.

Table view Custom Cell Design issue

I am trying to create a custom table cell that will have rounded corners and a shadow. The end goal being to create a "card" look and feel. My storyboard setup is below. I created a separate view onto the content view of the cell so that I could manipulate that view to have the effects that I want. The problem is that the effects only seem to be affecting the top portion of the view. The bottom corners and not rounded and you can also see that the border is surrounding the entire view. I have included the custom cell class file as well. Any ideas on how to get the rest of the view to have the rounded corners and border?
class EventTableCell: UITableViewCell {
#IBOutlet weak var collectionView: UIView!
#IBOutlet weak var address: UILabel!
#IBOutlet weak var statusImage: UIImageView!
#IBOutlet weak var customerName: UILabel!
#IBOutlet weak var customerTime: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
//collectionView.backgroundColor = UIColor.gray
collectionView.clipsToBounds = false
collectionView.layer.cornerRadius = 10
collectionView.layer.borderWidth = 1
collectionView.layer.borderColor = UIColor.gray.cgColor
collectionView.layer.shadowColor = UIColor.lightGray.cgColor
collectionView.layer.shadowOpacity = 1
collectionView.layer.shadowOffset = CGSize.zero
collectionView.layer.shadowRadius = 3
}
}
Screen Shot of UiTableview in Main Storyboard:
Screen Shot of output:
Use this method:
extension UIView {
func addShadow(offset: CGSize, color: UIColor, radius: CGFloat, opacity: Float) {
layer.masksToBounds = false
layer.shadowOffset = offset
layer.shadowColor = color.cgColor
layer.shadowRadius = radius
layer.shadowOpacity = opacity
let backgroundCGColor = backgroundColor?.cgColor
backgroundColor = nil
layer.backgroundColor = backgroundCGColor
}
}
Call this method like this:
view.addShadow(offset: CGSize(width: 5, height: 5), color: .lightGray, radius: 5, opacity: 0.5)
You can call this method in the method 'awakeFromNib' of tableCell.
Note: Give proper height of table row also.
If your subviews of UICollectionView constraints are correct then set height automatic dimension in heightForRowAt and estimatedHeightForRowAt in UITableView delegate methods and reload the UICollectionView after start rendering.
Maintain some padding to all sides between cell contentView and containerView (*from your attached image) to visible shadow in all sides.
You can add following method where size will be yours preference and set "UICollectionViewDelegateFlowLayout" delegate to your class
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
{
let cellSize = CGSize(width: 100, height: 100)
return cellSize
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat
{
return 10
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets
{
let sectionInset = UIEdgeInsetsMake(10, 10, 10, 10)
return sectionInset
}
By applying these method you can able to display cell with proper way , currently your size of cell is exceeded then default size so this is happening , by implementing size method will remove default height and replace with your requested cell size.
Hope this will solve your problem.

How to make UICollectioncell width dynamic according to text

Guys I want to change the size of the cell like this
Auto adjusting to the text. what I am able to achieve is
I have tried to search but not able to find out the solution. How can I make it dynamic to text.
The tags are coming from a model class and the colour and background is changing from custom class for the cell.
Its explained in the answer below.
HorizontalCollectionView Content width and spacing
Calculate size of string with associate font.
extension String {
func size(with font: UIFont) -> CGSize {
let fontAttribute = [NSAttributedString.Key.font: font]
let size = self.size(withAttributes: fontAttribute)
return size
}
}
Return the calculated width along with collectionView height in collectionView(_, collectionViewLayout:_, sizeForItemAt).
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let newWidth = titles[indexPath.row].size(with: labelFont!).width + 10 //Added 10 to make the label visibility very clear
return CGSize(width: newWidth, height: collectionView.bounds.height)
}
Check the code below:-
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let btn = UIButton()
btn.setTitle(?*self.arr[indexPath.row].name, for: .normal)
let btnWidth = ?*btn.intrinsicContentSize.width > UIScreen.main.bounds.width - 32 ? ?*btn.intrinsicContentSize.width - 32 : ?*btn.intrinsicContentSize.width
return CGSize(width: (?*btnWidth), height: 48)
}
You can modify it according to your requirement. Comment if you need any help in this.
Hope it helps :)

Collection View Frame in View Debug is different from code

When debugging custom UICollectionView via View Debug it's width is 829, but when it's width is accessed via code it's width is 820. What am I missing?
Visual debug:
Code:
func collectionView(_ collectionView: UICollectionView, layout: UICollectionViewLayout, sizeForItemAt: IndexPath) -> CGSize
{
let widthForCulculation = self.frame.size.width // 820.0
...
return CGSize(width: segmentWidth, height: segmentHeight)
}
Pretty hacky way, but try to invalidate layout when layouting subviews
var width : CGFloat = 0
override func layoutSubviews() {
super.layoutSubviews()
if (self.width != self.frame.size.width)
{
self.width = self.frame.size.width
self.collectionViewLayout.invalidateLayout()
}
}

Resize images automatically in CollectionViewCell in CollectionView with Auto Layout

I have a collectionView with horizontal UICollectionViewFlowLayout.
I am trying to achieve:
If a device orientation is portrait, UIImageView width will be qual to view.width and let the height be calculated automatically (like it usually happens with Auto Layout). And the same for the landscape mode. Example - standard photo app on the Iphone.
Unfortunately i don't see how to achieve it with autoLayout. I set constraints on UIImageView for it to be equal in size to the cell. But looks like the sell itself cannot be pinned to the Parent View.
After reading similar questions looks like cells must be resized programmatically using
func collectionView(collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
return CGSize(width: width, height: height)
}
And here i am stuck because i know the width of the screen but don't know how to calculate the height dynamically.
About image height:
I have my image declared like this:
var pageImages = [UIImage]()
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell: ImageDetailViewCell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! ImageDetailViewCell
let curr = indexPath.row
let imgName = data[albumNumber][curr]["image"]
cell.DetailImageView.image = UIImage(named: imgName!)
return cell
}
If you use the proper UIImageView resize setting (say, aspect fit/fill), then you just need to set the cell's height to your collectionView's (you get a pointer to it as one of the ...sizeForItemAtIndexPath... method parameters) height. You also should call the - layoutIfNeeded method on your cell afterwards.
You can use sizeForItemAtIndexPath: to change the size of collection view cell.
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
var numberOfCellInRow : Int = 3
var padding : Int = 5
var collectionCellWidth : CGFloat = (self.view.frame.size.width/CGFloat(numberOfCellInRow)) - CGFloat(padding)
return CGSize(width: collectionCellWidth , height: collectionCellWidth)
}
You can get the size of cell via :
((UICollectionViewFlowLayout) self.collectionViewName).itemSize.height)
You can get the image size via :
let sizeOfImage = image.size
let height = image.height
If you want to change the height then change it manually by return CGSize(width: collectionCellWidth , height: cellheight)

Resources