How to center horizontally UICollectionView Cells?
Its not a good idea to use a library, if your purpose is only this i.e to centre align.
Better you can do this simple calculation in your collectionViewLayout function.
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int) -> UIEdgeInsets {
let totalCellWidth = CellWidth * CellCount
let totalSpacingWidth = CellSpacing * (CellCount - 1)
let leftInset = (collectionViewWidth - CGFloat(totalCellWidth + totalSpacingWidth)) / 2
let rightInset = leftInset
return UIEdgeInsets(top: 0, left: leftInset, bottom: 0, right: rightInset)
}
How to center align the cells of a UICollectionView?
I think you can achieve the single line look by implementing something like this:
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
return UIEdgeInsetsMake(0, 100, 0, 0);
}
You will have to play around with that number to figure out how to force the content into a single line. The first 0, is the top edge argument, you could adjust that one too, if you want to center the content vertically in the screen.
How to center align the cells of a UICollectionView in Swift3.0?
This ended up being the solution I used. Read the code comments for a better understanding. Swift 5
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
//Where elements_count is the count of all your items in that
//Collection view...
let cellCount = CGFloat(elements_count)
//If the cell count is zero, there is no point in calculating anything.
if cellCount > 0 {
let flowLayout = collectionViewLayout as! UICollectionViewFlowLayout
let cellWidth = flowLayout.itemSize.width + flowLayout.minimumInteritemSpacing
//20.00 was just extra spacing I wanted to add to my cell.
let totalCellWidth = cellWidth*cellCount + 20.00 * (cellCount-1)
let contentWidth = collectionView.frame.size.width - collectionView.contentInset.left - collectionView.contentInset.right
if (totalCellWidth < contentWidth) {
//If the number of cells that exists take up less room than the
//collection view width... then there is an actual point to centering them.
//Calculate the right amount of padding to center the cells.
let padding = (contentWidth - totalCellWidth) / 2.0
return UIEdgeInsets(top: 0, left: padding, bottom: 0, right: padding)
} else {
//Pretty much if the number of cells that exist take up
//more room than the actual collectionView width, there is no
// point in trying to center them. So we leave the default behavior.
return UIEdgeInsets(top: 0, left: 40, bottom: 0, right: 40)
}
}
return UIEdgeInsets.zero
}
Align cell in center(horizontally) in UICollectionView
I'd control the focus and the collection content offset (scroll position) separately.
For the content offset you should set the section margins and the inter-item spacing so that you have one cell centred and the adjacent cells visible at the edges. You can get this setup and tested without showing any focus.
Presumably there is difficulty getting the item to move exactly to the centre when you scroll (the focus changes). To resolve this, implement - scrollViewWillEndDragging:withVelocity:targetContentOffset:
to find the item at the targetContentOffset
and get its centre point (from the layout attributes). With that you can modify the targetContentOffset
such that the scroll ends exactly with the item centred.
Now, the focus should be managed by the cell itself, not the collection view. Below is a (slightly large) example of a cell focus change animation. It uses cartography to change image view constraints and applies a transform to a label. You can do something similar depending on how you want the image and label to interact with each other.
Note that the below code also applies a motion effect transform similar to the stock supplied by apple when a UIImageView
has focus and has adjustsImageWhenAncestorFocused
set. If you don't want that you can simplify and shorten the code quite a bit.
override func didUpdateFocusInContext(context: UIFocusUpdateContext, withAnimationCoordinator coordinator: UIFocusAnimationCoordinator) {
super.didUpdateFocusInContext(context, withAnimationCoordinator: coordinator)
if (context.nextFocusedView == self) {
UIView.animateWithDuration(0.1,
animations: { () -> Void in
self.imageConstraints = constrain(self.itemImageView, replace: self.imageConstraints!) {
$0.top == $0.superview!.top
$0.bottom == $0.superview!.bottom
$0.leading == $0.superview!.leading
$0.trailing == $0.superview!.trailing
}
self.itemLabel.transform = CGAffineTransformMakeTranslation(0, 60)
self.itemLabel.layer.backgroundColor = UIColor.darkGrayColor().colorWithAlphaComponent(0).CGColor
self.layer.shadowOpacity = 1
self.layoutIfNeeded()
}, completion: nil)
let minMaxAngle = 10.0
let m34 = CGFloat(1.0 / -1250)
let angle = CGFloat(minMaxAngle * M_PI / 180.0)
var baseTransform = CATransform3DIdentity
baseTransform.m34 = m34
let rotateXmin = CATransform3DRotate(baseTransform, -1 * angle, 1.0, 0.0, 0.0);
let rotateXmax = CATransform3DRotate(baseTransform, angle, 1.0, 0.0, 0.0);
let rotateYmin = CATransform3DRotate(baseTransform, angle, 0.0, 1.0, 0.0);
let rotateYmax = CATransform3DRotate(baseTransform, -1 * angle, 0.0, 1.0, 0.0);
let verticalMotionEffect = UIInterpolatingMotionEffect(keyPath: "layer.transform",
type: .TiltAlongVerticalAxis)
verticalMotionEffect.minimumRelativeValue = NSValue(CATransform3D: rotateXmin)
verticalMotionEffect.maximumRelativeValue = NSValue(CATransform3D: rotateXmax)
let horizontalMotionEffect = UIInterpolatingMotionEffect(keyPath: "layer.transform",
type: .TiltAlongHorizontalAxis)
horizontalMotionEffect.minimumRelativeValue = NSValue(CATransform3D: rotateYmin)
horizontalMotionEffect.maximumRelativeValue = NSValue(CATransform3D: rotateYmax)
let group = UIMotionEffectGroup()
group.motionEffects = [horizontalMotionEffect, verticalMotionEffect]
self.addMotionEffect(group)
}
else {
UIView.animateWithDuration(0.3,
animations: { () -> Void in
self.imageConstraints = constrain(self.itemImageView, replace: self.imageConstraints!) {
$0.top == $0.superview!.top + 20
$0.bottom == $0.superview!.bottom - 20
$0.leading == $0.superview!.leading + 20
$0.trailing == $0.superview!.trailing - 20
}
self.itemLabel.transform = CGAffineTransformIdentity
self.itemLabel.layer.backgroundColor = UIColor.darkGrayColor().colorWithAlphaComponent(0.75).CGColor
self.layer.shadowOpacity = 0
self.layoutIfNeeded()
}, completion: nil)
for effect in self.motionEffects {
self.removeMotionEffect(effect)
}
}
}
Center horizontal UICollectionView based on content
Assuming your current code is working when you the cells will fit - that is, it centers the "row of cells" when desired - change this line:
let leftInset = (collectionViewWidth - CGFloat(totalCellWidth + totalSpacingWidth)) / 2
to:
let leftInset = max(0, (collectionViewWidth - CGFloat(totalCellWidth + totalSpacingWidth)) / 2.0)
That way your insets will never be less than Zero
Related Topics
My App Was Just Rejected for Using the Ad Support Framework. Which Library Is Responsible
Get Device Location (Only Country) in iOS
How to Add Multiple Collection Views in a Uiviewcontroller in Swift
What Are the Device-Width CSS Viewport Sizes of the Iphone6 and iPhone 6 Plus
Ios8 Photos Framework: How to Get the Name(Or Filename) of a Phasset
How to Detect One Button in Tableview Cell
Unbalanced Calls to Begin/End Appearance Transitions for <Uitabbarcontroller: 0X197870>
Creating PDF File from Uiwebview
How to Update a Coredata Entry That Has Already Been Saved in Swift
Change the iOS Keyboard Layout to Emoji
Pod Install -Bash: Pod: Command Not Found
Identify New iPhone Model on Xcode (5, 5C, 5S)
Why Calling Setneedsupdateconstraints Isn't Needed for Constraint Changes or Animations
Fix CSS Hover on Iphone/Ipad/Ipod
Application Crashed While Importing Songs from Ipod Library in iPhone for iOS 5.0
Fatal Error: Unexpectedly Found Nil While Unwrapping an Optional Value
Uitableviewcell with Autolayout Left Margin Different on iPhone and iPad