How to Center Horizontally Uicollectionview Cells

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)
}

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

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
}

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.

Swift - Center Horizontally UICollectionView Cell doesn't work

I found the answer but Still I don't know what is wrong with it that it work in other ViewController but not this one, the only difference between this ViewController and others is that in this one I used more than 1 ViewController. I linked the answer below, so if anyone has this issue can fix it, I used the Second solution and it worked. thanks to Cœur for sharing this.

Answer

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)
}
}
}


Related Topics



Leave a reply



Submit