UICollectionView水平分页不居中

我有一个水平滚动collectionView与每个单元格视图的大小。 当我通过collectionView页面不是逐页。 单元格不在屏幕的中心。 我已经尝试了一堆东西来尝试修复它,并没有任何运气。 这是一个问题的video: https : //www.youtube.com/watch ? v = tXsxWelk16w有什么想法?

删除项目之间的空格。 对于水平滚动collections视图,将最小行间距设置为0.您可以使用界面构build器或UICollectionViewDelegateFlowLayout协议的方法执行此操作:

 - (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section { return 0; } 

在这里输入图像说明

另一种方法是使单元格的宽度小于collectionView的宽度,以获得项目之间的水平空间值。 然后添加与项目之间的水平空间的一半等于左和右插入的部分插入。 例如,您的最小行间距是10:

 - (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section { return 10; } - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { return CGSizeMake(collectionView.frame.size.width - 10, collectionView.frame.size.height); } - (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section { return UIEdgeInsetsMake(0, 5, 0, 5); } 

在这里输入图像说明

第三种方式:在scrollViewDidEndDecelerating:操作collectionView scroll scrollViewDidEndDecelerating:方法:

 - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { if (scrollView == self.collectionView) { CGPoint currentCellOffset = self.collectionView.contentOffset; currentCellOffset.x += self.collectionView.frame.size.width / 2; NSIndexPath *indexPath = [self.collectionView indexPathForItemAtPoint:currentCellOffset]; [self.collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:YES]; } } 

在这里输入图像说明

Swift 3中演示: https : //github.com/damienromito/CollectionViewCustom

 func scrollViewWillEndDragging(_ scrollView:UIScrollView,withVelocity velocity:CGPoint,targetContentOffset:UnsafeMutablePointer){

    让pageWidth = Float(itemWidth + itemSpacing)
    让targetXContentOffset = Float(targetContentOffset.pointee.x)
    让contentWidth = Float(collectionView!.contentSize.width)
     var newPage = Float(self.pageControl.currentPage)

    如果velocity.x == 0 {
         newPage = floor((targetXContentOffset  -  Float(pageWidth)/ 2)/ Float(pageWidth))+ 1.0
     } else {
         newPage = Float(velocity.x> 0?self.pageControl.currentPage + 1:self.pageControl.currentPage  -  1)
         if newPage contentWidth / pageWidth){
             newPage = ceil(contentWidth / pageWidth) -  1.0
         }
     }
     self.pageControl.currentPage = Int(newPage)
    让point = CGPoint(x:CGFloat(newPage * pageWidth),y:targetContentOffset.pointee.y)
     targetContentOffset.pointee =点
 }

能够让单元格与单元格之间的空间较小的collectionView框架允许暗示给用户,其他单元格的任何一方滚动到哪一个对UX来说是一个巨大的胜利。 但是,对于页面居中不能按预期的方式工作,随着用户滚动,每个单元逐渐变得更加偏移。 我发现以下工作良好。 每个单元格上的居中/贴合animation对用户来说几乎是不可见的,因为它只调整collectionView滚动自然结束的位置,而不是将collectionView快速滚动到另一个indexPath 。 将sectionInset属性设置得足够大以允许单元格不能粘到包含的边框上仍然很重要。 另外,由于单元格之间有空格,目标可能会落在indexPath的nil indexPath上,导致collectionView滚动回到开始位置。 我已经解决了这个抵消一点,然后再尝试,但可以采取不同的方法在这里。

 - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset { //Ensure the scrollview is the collectionview we care about if (scrollView == self.collectionView) { // Find cell closest to the frame centre with reference from the targetContentOffset. CGPoint frameCentre = self.collectionView.center; CGPoint targetOffsetToCentre = CGPointMake((* targetContentOffset).x + frameCentre.x, (* targetContentOffset).y + frameCentre.y); NSIndexPath *indexPath = [self.collectionView indexPathForItemAtPoint:targetOffsetToCentre]; //Check for "edgecase" that the target will land between cells and then find a close neighbour to prevent scrolling to index {0,0}. while (!indexPath) { targetOffsetToCentre.x += ((UICollectionViewFlowLayout *)self.collectionView.collectionViewLayout).minimumInteritemSpacing; indexPath = [self.collectionView indexPathForItemAtPoint:targetOffsetToCentre]; } // Find the centre of the target cell CGPoint centreCellPoint = [self.collectionView layoutAttributesForItemAtIndexPath:indexPath].center; // Calculate the desired scrollview offset with reference to desired target cell centre. CGPoint desiredOffset = CGPointMake(centreCellPoint.x - frameCentre.x, centreCellPoint.y - frameCentre.y); *targetContentOffset = desiredOffset; } } 

Swift 3

 func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { if scrollView == self.collectionView { var currentCellOffset = self.collectionView.contentOffset currentCellOffset.x += self.collectionView.frame.width / 2 if let indexPath = self.collectionView.indexPathForItem(at: currentCellOffset) { self.collectionView.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: true) } } } 

Swift 3.0设置你自己的UICollectionViewFlowLayout

 let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout() let width = UIScreen.main.bounds.width layout.itemSize = CGSize(width: width, height: 154) layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) layout.minimumInteritemSpacing = 0 layout.minimumLineSpacing = 0 layout.scrollDirection = .horizontal collectionView?.collectionViewLayout = layout 

有类似的问题后,我通过意识到,当使用水平滚动时,高度现在的宽度和宽度现在是高度,因为默认设置为垂直滚动。 尝试切换值,看看是否有帮助。 https://developer.apple.com/library/content/documentation/WindowsViews/Conceptual/CollectionViewPGforIOS/UsingtheFlowLayout/UsingtheFlowLayout.html

我刚刚从Apple官方指南和示例代码中看到的代码:

AssetViewController.swift:

 self.collectionView?.isPagingEnabled = true self.collectionView?.frame = view.frame.insetBy(dx: -20.0, dy: 0.0) 

Swift 3的解决scheme基于@ Santos的答案,如果你有一个常规的水平分页收集视图没有页面控制像Paolo正在使用他的Swift 3的例子。

我用这个来解决一个问题,一个水平分页的单元格全屏单元格与一个自定义的UICollectionViewFlowLayoutanimation器没有完成旋转和结束偏移,所以全屏单元框架的边缘越来越水平偏离集合视图的边界设置当你滚动(如在videoOP共享)。

  func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) { // Ensure the scrollview is the one on the collectionView we care are working with if (scrollView == self.collectionView) { // Find cell closest to the frame centre with reference from the targetContentOffset. let frameCenter: CGPoint = self.collectionView.center var targetOffsetToCenter: CGPoint = CGPoint(x: targetContentOffset.pointee.x + frameCenter.x, y: targetContentOffset.pointee.y + frameCenter.y) var indexPath: IndexPath? = self.collectionView.indexPathForItem(at: targetOffsetToCenter) // Check for "edge case" where the target will land right between cells and then next neighbor to prevent scrolling to index {0,0}. while indexPath == nil { targetOffsetToCenter.x += 10 indexPath = self.collectionView.indexPathForItem(at: targetOffsetToCenter) } // safe unwrap to make sure we found a valid index path if let index = indexPath { // Find the centre of the target cell if let centerCellPoint: CGPoint = collectionView.layoutAttributesForItem(at: index)?.center { // Calculate the desired scrollview offset with reference to desired target cell centre. let desiredOffset: CGPoint = CGPoint(x: centerCellPoint.x - frameCenter.x, y: centerCellPoint.y - frameCenter.y) targetContentOffset.pointee = desiredOffset } } } }