I have a UICollectionViewCell in a UICollectionView configured with a UIImage and UILabel. I am trying to add multiple rows of the cell and have defined it to have 3 cells per row. However, the second cell that renders is aligned on the right side of the view and it just starts goes to the next row instead.
My Storyboard:
When I add multiple cells:
I have tried setting up custom layout sizing but I am still running into the same issue where the second cell is right aligned which messes up the entire layout.
let collectionViewWidth = collectionView.frame.width
let itemWidth = (collectionViewWidth-leftAndRightPaddings)/numberOfItemsPerRow
let itemHeight = (8*itemWidth)/6
let layout = collectionViewLayout as! UICollectionViewFlowLayout
layout.itemSize = CGSize(width: itemWidth, height: itemHeight)
Not sure where I am going wrong here.
I was able to get this one solved. The issue was the spacing between the cells which was messing up the alignment. Adding these two lines did the trick:
layout.minimumInteritemSpacing = 0
layout.minimumLineSpacing = 0
Related
I am creating a dynamic height TableViewCell based on the contents of the Cell. I would like to create a custom separator between the cells. I have the following code in the TableViewCell swift file. It appears that the custom separator is created using the default height of the cell and not the calculated height of the cell based on the contents of the cell - which was calculated in the TableView heightForRowAt override function. As a result, the customer separator is rendered across the cell. It appears that the awakeFromNib is called before the height calculation. Any suggestions?
class FeedTableViewCell: UITableViewCell {
override func awakeFromNib() {
super.awakeFromNib()
// add a custom seperator between table view cells.
let screenSize = UIScreen.main.bounds
let separatorHeight = CGFloat(10.0)
let additionalSeparator = UIView.init(frame: CGRect(x: 0, y: self.frame.size.height-separatorHeight, width: screenSize.width, height: separatorHeight))
additionalSeparator.backgroundColor = UIColor(named: "TEXTVIEWCELL_SEPARATOR")
self.addSubview(additionalSeparator)
}
}
The awakeFromNib is called before the height calculation. While the solution works for fixed height TableViewCells, it won't work for variable height TableViewCells. The solution that I used was to create a view on the bottom of the TableViewCell, use constraints to pin it to the bottom of the TableViewCell. You can size the view to 10pt and of course set the color. I did this in StoryBoards, not programmatically.
I'm trying to get a UICollectionView to display horizontal columns when on iPad.
This is my current layout when on iPhone (Collection view scrolls vertically):
Each UICollectionViewCell has a dynamic height depending on the content but the width is set to 100% of the screen width.
The cell height is set like this:
if let flowLayout = collectionView?.collectionViewLayout
as? UICollectionViewFlowLayout {
flowLayout.estimatedItemSize = CGSize(width: 1, height: 1)
}
It's a standard UICollectionView using the usual dataSource/delegate methods (sizeForItemAtIndexPath, cellForItemAtIndexPath etc.)
When on iPad, I'm adjusting the width depending on the number of columns required:
var numberOfColumns = 1
if screenWidth > 760 {
numberOfColumns = 2
}
let cellWidth = screenWidth/numberOfColumns
Adjusting the width of the columns gives me this:
But i'm trying to get something like this:
Is there a way to achieve this using UICollectionView?
A few notes about the collection view:
Layout is set to Flow
Scroll direction is vertical
Headers are a fixed height
Cell height is dynamic based on content
I need the collection view to scroll vertically if the content extends outside of the screen
I need to make UICollectionView cells in oval shape where height is fixed but width is dynamic and it has a limit also, if text longer than that, then text should scroll. Any third party option available for this or need to create own using UICollectionView. Please guide.
Below is the image what i am trying to achieve. I want to know before starting should i look for third parties or use UICollectionView to make own. I have short time to complete that's why to avoid time on searching asking in starting itself which direction to follow.Please guide.
You can use a UICollectionViewFlowLayout and Auto Layout to achieve this.
Create a UICollectionViewCell with a container view.
Pin this container view the edges of the cell with auto layout
Add a UILabel to this container view and pin it to all edges of the container view (give it a background color to distinguish from the cell background)
In the UICollectionViewCell subclass you'll want to round the corners of the container view, e.g. self.containerView.layer.cornerRadius = self.containerView.height / 2
In the UICollectionViewFlowLayoutDelegate method, estimatedSizeForItem return an approximate size for the cell (auto layout will calculate the actual size.)
The important thing to remember is your cell needs to have enough constraints so that the auto layout engine can calculate the actual height and width based on the content.
Edit: If you want a fixed height, ensure your label can only have a single line. Or add a height constraint.
Finally, i found a library TagListView that can be installed through cocoapods with lots of customisation and swift 4 support also.
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let nw = intersts[indexPath.row]
let options = NSStringDrawingOptions.usesFontLeading.union(.usesLineFragmentOrigin)
let size = CGSize(width: 250, height: 1500)
let estimatedFrame = NSString(string: nw).boundingRect(with: size, options: options, attributes: [NSAttributedStringKey.font : UIFont.systemFont(ofSize: 17)], context: nil)
let attributes = [NSAttributedStringKey.font : UIFont.systemFont(ofSize: 17)]
let yourLabelSize: CGSize = nw.size(withAttributes:attributes )
var width1 = yourLabelSize.width + 30
if width1 < 30 {
width1 = 30
}
return CGSize(width: estimatedFrame.width+20, height: estimatedFrame.height+20)
}
I just extend or implement #Tim answer. So after you build the cell as described in his answer, then specify the cell width and height to be flexible using the sample code below i.e similar to what he described
let collectionViewLayout = UICollectionViewFlowLayout()
collectionViewLayout.scrollDirection = .horizontal
let itemWidth = Constants.myCollectionViewItemWidth
let itemHeight = Constants.myCollectionViewItemHeight
collectionViewLayout.estimatedItemSize = CGSize(width: itemWidth, height: itemHeight)
myCollectionView.collectionViewLayout = collectionViewLayout
I'm having a dilemma maybe someone can help. I followed this tutorial that showed me how to dynamically adjust the height of a collectionview to match the height of the text.
https://possiblemobile.com/2016/02/sizing-uicollectionviewcell-fit-multiline-uilabel/
if let flowLayout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout { flowLayout.estimatedItemSize = CGSizeMake(1, 1) }
cell.label.preferredMaxLayoutWidth = 50
But the issue I'm having is now the collection view wraps around the text instead of conforming to collectionView.bounds.width. So when i have text that is smaller than the collectionview width, the cell wraps around the text. I want the cell to match the height of the text but have a set width set to collectionview bounds. How could I achieve this?
In my app I am using using UICollectionView. I want to set fix space between UICollectionViewCell. so how can I do this?
here is my code:
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAtIndex section: Int) -> CGFloat {
return 20
}
by this line I can set space between cell?
here is my screenshot please see this. and let me know how can i set fix distance in both landscape or portrait mode
Maybe,you need implementation follow method.
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section;
You can adjust the spacing between UICollectionCell by using the storyboard Min. spacing property of UICollectionView.
Here you have to set Min spacing value for cells and lines.
Hope it would help you.
You can also manage the spacing using the size inspector of Collection View
http://i.stack.imgur.com/Nvp3g.png
If you want exact spacing between the cells you need to calculate the size for the cells that will best fit to allow for the spacing you need without wrapping while considering the sectionInsets and CollectionView bounds. eg.
let desiredSpacing: CGFloat = 20.0
if let layout = self.collectionView?.collectionViewLayout as? UICollectionViewFlowLayout {
layout.minimumLineSpacing = desiredSpacing
let totalCellsContentWidth = self.collectionView!.bounds.width - layout.sectionInset.left - layout.sectionInset.right
let numberOfCellsPerRow: CGFloat = 10
let numberOfSpacesPerRow = numberOfCellsPerRow - 1
let cellWidth = (totalCellsContentWidth - (numberOfSpacesPerRow * desiredSpacing) / numberOfCellsPerRow)
layout.itemSize = CGSize(width: cellWidth, height: cellWidth)
}
Assuming your cells are the same size the minimumLineSpacing is simple but would otherwise expand to fit the largest cell on the row before wrapping to the next line. As you can see it's the cell spacing that is a bit more complicated.