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?
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.
Detect which UICollectionViewCell of a uicollectionView that is inside another uicollectionview is in the center
Your best bet would be delegates via protocols
Create protocol for your collection view cells
protocol yourDelegate: class {
func didSelectCell(WithIndecPath indexPath: IndexPath, InCollectionView collectionView: UICollectionView) -> Void
}
In your cells, create a function called setup which you can call at cellForRow.
In your cells, create a touch recogniser for self.
Disable cell selection for your collection views since these delegates will be called when the user touches given cell.
class yourCell: UICollectionViewCell {
var indexPath: IndexPath? = nil
var collectionView: UICollectionView? = nil
weak var delegate: yourDelegate? = nil
override func awakeFromNib() {
super.awakeFromNib()
let selfTGR = UITapGestureRecognizer(target: self, action: #selector(self.didTouchSelf))
self.contentView.addGestureRecognizer(selfTGR)
}
@objc func didTouchSelf() {
guard let collectionView = self.collectionView, let indexPath = self.indexPath else {
return
}
delegate?.didSelectCell(WithIndecPath: indexPath, InCollectionView: collectionView)
}
func setupCell(WithIndexPath indexPath: IndexPath, CollectionView collectionView: UICollectionView, Delegate delegate: yourDelegate) {
self.indexPath = indexPath
self.collectionView = collectionView
self.delegate = delegate
}
}
In your viewController, create extension for this protocol and if you do everything right, when the user touches your cell, the cell will call you via this delegation.
extension YourViewController: yourDelegate {
func didSelectCell(WithIndecPath indexPath: IndexPath, InCollectionView collectionView: UICollectionView) {
//You have your index path and you can "if" your colllection view
if collectionView == self.yourFirstCollectionView {
} else if collectionView == self.yourSecondCollectionView {
}
//and so on..
}
}
since protocol is ": class", we can use weak for your delegate property so no memory leak will occur. I use this method for tableViews and collectionViews throughout my projects.
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
Change Duration (Speed) on a Running Animation
Your Credentials Do Not Allow Access to This Resource Twitter API Error
Is There Really No Way to Style Sklabelnode
Uibezierpath + Cashapelayer - Animate a Circle Filling Up
Change Splash Screen Image Programmatically
Storyboard Localization in Swift 4.0
Swift 3 Filter Array of Dictionaries by String Value of Key in Dictionary
Pausing Timer When App Is in Background State Swift
How to Create an Image of Specific Size from Uiview
Cocoa Pods Install on iOS Project Not Working
Updating Label Takes Too Long (Swift)
Find Delegate in a Swift Array of Delegates
Google Cloud Messaging Bridging Header Import Fails
How to Send Emails in Swift Using Mailgun
Ruby: Loaderror - Library Not Found for Class Digest::Sha1 -- Digest/Sha1
Sinch Integration in Swift Project
How to Get a Substring from a Specific Character to the End of the String in Swift 4