How to center align CollectionView Cell? - ios

Hi have a collectionview.
Each cell's width is screenwidth/3. Means 3 cells in a row.
Now. If have 10 or 11 cells then there will be 4 rows. and there are 1 or 2 cells in last row.
The problem is ,I want to align these cell to center without changing its size . now cells are left align.
Note: I want to achieve this with in a section(Because collection-view already have multiple sections).
Image attached what i want to achieve .

You can solve this using multiple sections. Number of section should be
numberOfSection = totalItemCount/3 > Int(totalItemCount/3) ? Int(totalItemCount/3) + 1 : Int(totalItemCount/3)
dont use ceiling. Then number of items in section should be
numberOfItemInSection = totalItemCount-section*3 < 3 ? totalItemCount-section*3 : 3
Then implement the UICollectionViewDelegateFlowLayout delegate. Where in collectionView(_ collectionView:, layout:, insetForSectionAt:) set,
let minimumInterItemSpacing: CGFloat = 8.0
// minimumInterItemSpacing should be same in the delegate function
let itemCountInSection = collectionView.numberOfItems(inSection: section)
let edgeSpace = (collectionView.bounds.width - ((itemCountInSection*self.itemWidth) + (minimumInterItemSpacing*(itemCountInSection-1)))) / 2
return UIEdgeInsets(top: self.topSpace, left: edgeSpace, bottom: self.bottomSpace, right: edgeSpace)
set other delegate methods as it suits you.

Related

How to set UITextView's height dynamically in UITableViewCell based on string size?

I understand that this question has been asked here, but it didn't solve my problem as the link in the accepted answer is down and the minimal example didn't help.
Here is a picture of my custom UITableViewCell & all its constraints:
Each post contains these UI elements. The only element that could make each cell's height different is messageView, because its height depends on the string being displayed. Question is, how do I dynamically set each cell's height? Here's what I have now (Does NOT work, messageView is not shown at all):
func cellForRowAt(indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(...) as! PostCell
let message = ...
cell.messageView.text = message
return cell
}
func heightForRowAt(indexPath: IndexPath) -> CGFloat {
var cellMinimumHeight: CGFloat = 120
if let cell = tableView.cellForRow(at: indexPath) as? PostCell {
let size = cell.messageView.sizeThatFits(cell.messageView.frame.size)
cellMinimumHeight += size.height
}
return cellMinimumHeight
}
in heightForRowAt function, the if is not being executed, therefore, all cells' heights are cellMinimumHeight = 120.
How could I make each cell's height = 120 + messageView's height?
---------------------------------EDIT 1---------------------------------
Made a mistake in the picture, messageView's height is not set
When using Auto-Layout for dynamically sizing cells, you don't really need to implement sizeThatFits(...). If the constraints are setup correctly, then you only need to disable the scrolling of the UITextView.
From code:
yourTextView.scrollEnabled = false
From IB:
Select your Text View and open Attributes inspector, then
In Attributes Inspector select your UITextView(messageView) and Uncheck "Scrolling Enabled".
And then change your UITextView(messageView)'s content compression resistence priority as follows:
Horizontal = 750
Vertical = 1000
I hope this will help you.
Just disable UITextview scroll...
But here is no use of UITextview, you can use label also.
In HeightForRow tableview delegate method remove that stuff and use
return UITableViewAutomaticDimension
You have used constrain to make cell hight dynamic
form apple documentation
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.
So for your case you need
cell's height = 120 + messageView's height?
So start from Profile Image to measure unbroken chain of constraints from Top to Bottom
Profile Image top = 10 + ImageHeight = 60 ----> 70
MessageView top = 10 + set minimum height to message say 20 one line if every cell should have message even if one word and set this height Greater than or equal to 20 make sure that you set Scroll enable = false
so message Height minimum = 10 top + 20 + 10 bottom ---> 40
Menu Stack view Height ---> 30
So all Total = 70 + 40 + 30 = 140 this default hight no cell will be less than this
Also you must set the table view’s rowHeight property to UITableViewAutomaticDimension. You must also assign a value to the estimatedRowHeight property
tableView.estimatedRowHeight = 130.0
tableView.rowHeight = UITableViewAutomaticDimension
Here is apple documentation Here

Different line spacing for each item at UICollectionView - swift 3

I have a collection view written programmatically with swift 3. It has 1 section and 6 vertical items in it. The default minimum line spacing for each item is 10 I assume, but I want to set different line spacing for each item. For example, the space between item 0 and 1 become 50 but space between item 1 and 2 become 0. How can I do that? I searched a lot but couldn't find solution. Thanks in advance.
It is directly not possible by setting some property of your collection view but you can do one trick I think,
set your minimum line spacing and minimum interitem spacing to 0 like,
layout.minimumInteritemSpacing = 0
layout.minimumLineSpacing = 0
so your collection view cell will not have any space at any side!
now keep your cell's background color as clear color!
and add UIView (your content) in your cell with size(less than cell size) that shows spacing between two cell. So, you can add different size of view in every cell and it will display like different space between every cell!
Or
If you don't want to resize your inner view of cell then you can return different size for your cell from delegate method sizeForItemAtIndexPath for different items!
For example,
I am writing objective c code for example,
your sizeforitem,
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.item == 1 || indexPath.item == 6 || indexPath.item == 7 || indexPath.item == 9 || indexPath.item == 15) {
return CGSizeMake(screenWidth/3 -20, screenWidth/2);
}
return CGSizeMake(screenWidth/3, screenWidth/3);
}
and result is
An idea could be to consider the lines spacing as "other kind of cell", like blank cell, you see? And in the method heightForRowAtIndexPath, when the indexPath correspond to those blank cell, you return their custom height, otherwise you return the row height of your "real" cells.
(This imply to return those blank cell in the cellForRow, and add their number to your current numberOfRowInSection count too)

Different background and collectionCell separator color in UICollectionViewController

I have to create a UI which has 3 UICollectionViewCell in a row. So i created it using UICollectionViewController, with section = 1 and no of rows = coming from api. So i was able to create 6 cells in which every row contains 3 cells. These cells are separated by 0.5 pt vertically and horizontally.
I have given the background color to collectionView which comes in separator.
In particular this is what i need :-
Problem :-
This is the type of UICollectionViewController requirement i have
The separators needs to be red, and the space not rendered needs to be yellow. But I am unable to do that, I can have a single background color for UICollectionView which shows for both separator and free space. Is there a way to have different colors.
I dont want to use UITableView and have a UICollectionView inside UITableViewCell. I know this approach but i want to do the same in UICollectionViewController.
If I understand your question right, you can solve this by removing the space between the cells. Remove the 0.5pt space entirely. Then, all cells will be glued to each other, and you can create your own separators inside each cell. It'll require some logic though, because all cells should not use the same separators (if you do, then the center cells will have double separators on each side).
To achieve your photo, you could set these rules:
The first and the last cell in each row should only show a separator on bottom.
All the other cells in between (in your case, one cell in between) should show separator on bottom, left, and right.
To add these separators, just go into your custom UICollectionViewCell and add some UIViews to each side, and set them to have a width of 0.5pt, and set them visible on demand.
I would suggest a custom cell as Sti suggested. I usually do that. but an easier way would be:
To add a subview to the collectionView every time you reload data of
the collection view.
Code:
let count: CGFloat = CGFloat(items.count)
let numberOfRows: CGFloat = ceil(count / 3.0)
let height: CGFloat = numberOfRows * (cellHeight + seperatorHeight)
if collectionBackView != nil { // controller member object
collectionBackView.removeFromSuperview()
}
collectionBackView = UIView(frame:
CGRect(x: 0, y: 0, width: collectionView.frame.size.width, height: height))
collectionView.addSubview(collectionBackView)
collectionView.sendSubview(toBack: collectionBackView)

UICollectionView spacing is incorrect every other row

I am creating a custom flow layout for a UICollectionView, and I am trying to get the spacing right. Despite setting minimumLineSpacing = 2 every other line, there is only 1px between each row of images, as can be seen here. I believe this is because Apple now uses points instead of pixels, but how do you fix this? Here is my code in my CollectionViewController that sets the flow layout:
let screenWidth = self.collectionView?.bounds.size.width
let flowLayout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
flowLayout.minimumInteritemSpacing = 2
flowLayout.minimumLineSpacing = 2
let totalSpacing = flowLayout.minimumInteritemSpacing * 4.0
let imageSize = (screenWidth!-totalSpacing)/4.0
flowLayout.itemSize = CGSize(width: imageSize, height: imageSize)
I figured it out. If the height of the cell is a repeating float, the spacing between each row will alternate, every other row. For instance, if I want to fit three cells with 2 points spacing between each one, each cell will be 123.6666666667 points wide on an iPhone 6. (An iPhone 6 is 375 points across, leading to the calculation (375-4)/3 = 123.6666666667). If I proceed to use the same value for height as I do width, the last 2/3 of a point will cause the rows' spacing to alternate, as seen here.
What I've found is that the cell height does not necessarily have to be an int to fix this; setting it to say 123.5 will solve this problem, but ints of course will also work.

Set/Override Padding In UICollectionView Between Cells

I have a UICollectionView and I'm running into an issue with getting the padding between cells. In theory, I should be able to divide the screen by 4, and I can get a cellsize that has 4 images which perfectly take up the screen width. But, it chooses not to do that. Instead it creates 3 images with HUGE padding as shown below:
_cellSize = CGSizeMake(UIScreen.mainScreen().bounds.width/4,UIScreen.mainScreen().bounds.width/4)
So I decreased the cell size a bit to create some padding, and this was closer but I need about half this padding:
_cellSize = CGSizeMake(UIScreen.mainScreen().bounds.width/4.4,UIScreen.mainScreen().bounds.width/4.4)
So I tried making the cells a bit bigger and it rolls over to the next row and puts 3 items with HUGE padding again.
_cellSize = CGSizeMake(UIScreen.mainScreen().bounds.width/4.3,UIScreen.mainScreen().bounds.width/4.3)
Can I specify the padding between cells without it deciding that if the padding is below "x" amount that it creates a new row instead? Like can I set the threshold padding before a new row to say, 0?
I want to make it this thin:
You only need to do the correct calculation that includes the spaces you want to the edges as well as the space between the cells. For instance, if you want 3 cells across with 5 points to the edges and between the cells, you should have something like this,
override func viewDidLoad() {
super.viewDidLoad()
var layout = self.collectionView.collectionViewLayout as UICollectionViewFlowLayout
layout.sectionInset = UIEdgeInsetsMake(0, 5, 0, 5);
layout.minimumInteritemSpacing = 5; // this number could be anything <=5. Need it here because the default is 10.
layout.itemSize = CGSizeMake((self.collectionView.frame.size.width - 20)/3, 100) // 20 is 2*5 for the 2 edges plus 2*5 for the spaces between the cells
}

Resources