CollectionView margin not the same - ios

i'm trying to create a simple collectionView like pinterest. I've reached a problem i've set the margins like in the image, but as u can see the middle margin is 20 since both right and left is 10 how can i make so that its also 10. i've tried changing some values, but it is not working.
for fitting all orientations
Is there a better way?
func collectionView(collectionView : UICollectionView,layout collectionViewLayout:UICollectionViewLayout,sizeForItemAtIndexPath indexPath:NSIndexPath) -> CGSize
{
return CGSizeMake(self.collectionView!.frame.width/2-20, self.collectionView!.frame.width/2-20+50)
}

Use auto layout and view constraints. This will allow you to have each tile maintain its spacing and scale for different orientations.
see the apple docs

Related

Auto Cell Height on UITableView without overlapping bottom part of iPhone X

So my goal is to achieve automatic height for my table view. What I mean by by that is whenever I add new item to the table view, the table is still "full screen" while the cell is decreasing its height.
for example this is what I've done :
on iPhone 6s Simulator
on iPhone 5s Simulator
and I've achieve that using code :
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
let itemCount:CGFloat = CGFloat(items.count)
let statusHeight = UIApplication.shared.statusBarFrame.height
let navHeight = self.navigationController!.navigationBar.frame.height-statusHeight
let viewHeight = view.bounds.height
let cellHeight = (viewHeight-navHeight)/itemCount
return cellHeight
}
but the problem is that in iPhone X it was doing something like :
on iPhone X Simulator
the bottom part of the bottom item is cut/overlapped. How can I fix it?
Thank you.
Edit :
Thanks for the answer Trupesh Vaghasiya and Pankaj I've done your solution, couldn't find it but this is what I've done {Screenshot}
But the outcome was like this {iPhone X Screenshot}. Don't you think that's violates the iPhone X UI guideline?
You need to change TableView Bottom Constraint First Item Safe Area to give SupperView.
Let us know... is working?
Just change your Interface constraint relevant to superView instead of safe area. Check your tableview top and bottom Constraint and make it related to superView. but as per apple said, it is good if you make it related to safe area as iPhone X and higher version have home button on screen so. you can check bellow screen shots. Select Bottom Constraint
Select constraint that you want to change and Double Click at there.
And then select First Item and then select Superview

Adjust UICollectionView Size Dynamically to Ensure No Inter Item Spacing

The goal is to have a UICollectionView with a specific number of columns per row, regardless of the size of the screen.
Currently I am using:
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize
{
//print(collectionView.frame.size.width)
let numberRows:CGFloat = 7
return CGSize(width: collectionView.frame.size.width/numberRows, height: collectionView.frame.size.width/numberRows)
}
To set the size of the cells so that they can fit inside the collection view without inter item spacing. However, the size of the collection view is set based on a percentage of the screen size. If the desired "numberRows" does not divide evenly, then there will be spacing between the cells.
How can I dynamically change the collection view size to ensure the cells will fit without spacing? How can this be accomplished in a more efficient way?
When you set the size of your collection view, you could round it down to a multiple of numberRows. This ensures it will divide evenly.
If you are using AutoLayout, you could set the width or height constraints of the collection view. Then call layoutSubviews: or setNeedsLayout
If you are not using AutoLayout, you can change the size of the collection view using setFrame or setBounds.
You can not break the mathematical rules here. If you get one point/pixel to much you can not break this pixel into two half-pixels.
What you can do is:
size the collection view accordingly so that the number of cells fit perfectly
accept that one of the cells will have one pixel more/less size then the others. (e.g. the last cell in the row)

How to adjust UICollectionView contentSize.height based on number of rows in swift

I'd really appreciate if someone can light up some ideas here. I've been trying to fix this for weeks now (not kidding).
I have a "to do list" using a collectionView where I hide the rows that were completed and move them to the end of the list. I then unhide the items if needed with a button. The collectionView looks exactly as a tableView with one item(cell) per row.
When the items are hidden the collectionView has a lot of empty scrolling space at the bottom instead of automatically deleting the space used by the hidden rows since they technically are still there.
I'm trying to cut that empty space so the collectionView height would be equal to the amount of cells/rows left visible.
override func viewDidAppear(animated: Bool) {
if isCellHidden { //checking if cells are hidden
var heightOfSection0 = 95 + (42 * self.collectionView.numberOfItemsInSection(0))
println(self.collectionView.contentSize.heigh) //returns 2350
self.collectionView.contentSize.height = CGFloat(heightOfSection0)
println(heightOfSection0) //returns 1019
println(self.collectionView.contentSize.heigh) //returns 1019.0 which is correct but as soon as I scroll down it resets to it's original size (2350) and let's me scroll through that empty space...
}}
If I try to read the collectionView height immediately after setting this, it displays the correct value but as soon as I try to scroll down it resets back to it's original height. I also tried disabling the auto layout and it doesn't make a difference
You should not manage contentSize directly - return appropriate number of items to be displayed from collectionView(_:numberOfItemsInSection:) instead (i.e. do not count your "hidden" cells).
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)
}
Changing UI stuff in viewDidAppear() in theory is a good place to do so. However, at this point, you can't be sure that auto layout has operated on the subview that you're manipulating.
You can check when it has and when it's safe to manipulate the frame, by subclassing it and overriding layoutSubviews()
I had a similar issue here: https://stackoverflow.com/a/30446125/4396258

iOS 8 Widget Alignment Issue

I'm having trouble aligning an iOS 8 widget all the way to the left. It seems that setting the x origin to 0 still keeps a certain amount of space between the left edge of the screen and my first view.
I'm not sure how Evernote does this, but it seems that they have it figured out. Any suggestions? I also tried setting the x position programmatically to no success.
Here the answer:
// MARK: NCWidgetProviding protocol methods
func widgetMarginInsetsForProposedMarginInsets(defaultMarginInsets: UIEdgeInsets) -> UIEdgeInsets
{
return UIEdgeInsetsZero
}

Where to update Autolayout constraints when size changes?

I have several UIViews laid out along the bottom of a containing UIView. I want these views to always be equal width, and always stretch to collectively fill the width of the containing view (like the emoji keyboard buttons at the bottom). The way I'm approaching this is to set equal widths to one of the views, then just update the width constraint of that view to be superviewWidth / numberOfViews which will cause all of the other views to update to that same value.
I am wondering where the code to change the constraint constant needs to go. It needs to be set before the keyboard appears on screen for the first time and update when rotating the device.
My first attempt at a solution was to place it in updateViewConstraints and calculate the width via containerView.frame.size.width. But this method is called twice upon load, the first time it calculates the values correctly, but the second time for some reason the containerView's width is 0.0. Another issue is that when rotating, the containerView's width is not the value that it will be after rotation, it's the current value before rotation. But I don't want to wait until after the rotation completes to update the constraint, because the buttons will be the original size then change which will be jarring to the user.
My question is: where is the most appropriate place to put this code? Is there a better way to calculate what the width will be? I can guarantee it will always be the exact same width as the screen width. And I am using Size Classes in Xcode 6, so willRotateToInterfaceOrientation and similar methods are deprecated.
On all classes that implement the UITraitEnvironment protocol the method traitCollectionDidChange will be called when the trait collection changes, like on rotation. This is the appropiate place to manually update the constraints when using the new Size Classes. You can also animate the transition with the method willTransitionToTraitCollection
Basic example:
class ViewController: UIViewController {
var constraints = [NSLayoutConstraint]()
func updateConstraintsWithTraitCollection(traitCollection: UITraitCollection) {
// Remove old constraints
view.removeConstraints(constraints)
// Create new constraints
}
override func willTransitionToTraitCollection(newCollection: UITraitCollection!,
withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator!) {
super.willTransitionToTraitCollection(newCollection, withTransitionCoordinator: coordinator)
coordinator.animateAlongsideTransition({ (context: UIViewControllerTransitionCoordinatorContext!) in
self.updateConstraintsWithTraitCollection(newCollection)
self.view.setNeedsLayout()
}, completion: nil)
}
override func traitCollectionDidChange(previousTraitCollection: UITraitCollection!) {
updateConstraintsWithTraitCollection(traitCollection)
}
}
Besides that I want to recommend Cartography, which is a nice library that helps to make auto layout more readable and enjoyable. https://github.com/robb/Cartography
There is no reason to update the width manually:
Place all the views with equal width in your view with no spacing in between each other
Add an equal width constraint to all of them
Add constraints with 0 width for spacing between sides and each other
Lower the priority of one or more of the equal width constraints just in case the width cannot be divided equally.
Then auto layout will handle everything for you.

Resources