UICollectionView Cell滚动到中心

 王瑾瑜2702935333 发布于 2023-01-12 10:50

我在我的UIViewController中使用UICollectionView.

我的collectionview属性设置如下.

在此输入图像描述

现在我希望滚动后单元格在屏幕上居中!选项1:

在此输入图像描述

选项2: 在此输入图像描述

我需要做什么来实现选项2?

更新:

最后我使用下面的代码作为滚动与其他答案不顺利.

  - (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity
{    CGFloat offsetAdjustment = MAXFLOAT;
    CGFloat horizontalCenter = proposedContentOffset.x + (CGRectGetWidth(self.collectionView.bounds) / 2.0);

    CGRect targetRect = CGRectMake(proposedContentOffset.x, 0.0, self.collectionView.bounds.size.width, self.collectionView.bounds.size.height);
    NSArray* array = [super layoutAttributesForElementsInRect:targetRect];

    for (UICollectionViewLayoutAttributes* layoutAttributes in array) {
        CGFloat itemHorizontalCenter = layoutAttributes.center.x;

        if (ABS(itemHorizontalCenter - horizontalCenter) < ABS(offsetAdjustment)) {
            offsetAdjustment = itemHorizontalCenter - horizontalCenter;
        }
    }    
    return CGPointMake(proposedContentOffset.x + offsetAdjustment, proposedContentOffset.y);
}

Dmitry Zhuko.. 15

您可以覆盖子类中的targetContentOffsetForProposedContentOffset:withScrollingVelocity:方法UICollectionViewLayout并计算您的偏移量,如下所示:

@property (nonatomic, assign) CGFloat previousOffset;
@property (nonatomic, assign) NSInteger currentPage;

...

- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity {
    NSInteger itemsCount = [self.collectionView.dataSource collectionView:self.collectionView numberOfItemsInSection:0];

    // Imitating paging behaviour
    // Check previous offset and scroll direction
    if ((self.previousOffset > self.collectionView.contentOffset.x) && (velocity.x < 0.0f)) {
        self.currentPage = MAX(self.currentPage - 1, 0);
    } else if ((self.previousOffset < self.collectionView.contentOffset.x) && (velocity.x > 0.0f)) {
        self.currentPage = MIN(self.currentPage + 1, itemsCount - 1);
    }

    // Update offset by using item size + spacing
    CGFloat updatedOffset = (self.itemSize.width + self.minimumInteritemSpacing) * self.currentPage;
    self.previousOffset = updatedOffset;

    return CGPointMake(updatedOffset, proposedContentOffset.y);
}

编辑:感谢您指出这一点,忘了说您必须先禁用分页:

self.collectionView.pagingEnabled = NO;

更新:附加Swift 4.2版本

...
collectionView.isPagingEnabled = false
...

class YourCollectionLayoutSubclass: UICollectionViewFlowLayout {

    private var previousOffset: CGFloat = 0
    private var currentPage: Int = 0

    override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint {
        guard let collectionView = collectionView else {
            return super.targetContentOffset(forProposedContentOffset: proposedContentOffset, withScrollingVelocity: velocity)
        }

        let itemsCount = collectionView.numberOfItems(inSection: 0)

        // Imitating paging behaviour
        // Check previous offset and scroll direction
        if previousOffset > collectionView.contentOffset.x && velocity.x < 0 {
            currentPage = max(currentPage - 1, 0)
        } else if previousOffset < collectionView.contentOffset.x && velocity.x > 0 {
            currentPage = min(currentPage + 1, itemsCount - 1)
        }

        // Update offset by using item size + spacing
        let updatedOffset = (itemSize.width + minimumInteritemSpacing) * CGFloat(currentPage)
        previousOffset = updatedOffset

        return CGPoint(x: updatedOffset, y: proposedContentOffset.y)
    }
}


小智.. 9

你可以使用代码 self.collectionView.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: true)

3 个回答
  • 您可以覆盖子类中的targetContentOffsetForProposedContentOffset:withScrollingVelocity:方法UICollectionViewLayout并计算您的偏移量,如下所示:

    @property (nonatomic, assign) CGFloat previousOffset;
    @property (nonatomic, assign) NSInteger currentPage;
    
    ...
    
    - (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity {
        NSInteger itemsCount = [self.collectionView.dataSource collectionView:self.collectionView numberOfItemsInSection:0];
    
        // Imitating paging behaviour
        // Check previous offset and scroll direction
        if ((self.previousOffset > self.collectionView.contentOffset.x) && (velocity.x < 0.0f)) {
            self.currentPage = MAX(self.currentPage - 1, 0);
        } else if ((self.previousOffset < self.collectionView.contentOffset.x) && (velocity.x > 0.0f)) {
            self.currentPage = MIN(self.currentPage + 1, itemsCount - 1);
        }
    
        // Update offset by using item size + spacing
        CGFloat updatedOffset = (self.itemSize.width + self.minimumInteritemSpacing) * self.currentPage;
        self.previousOffset = updatedOffset;
    
        return CGPointMake(updatedOffset, proposedContentOffset.y);
    }
    

    编辑:感谢您指出这一点,忘了说您必须先禁用分页:

    self.collectionView.pagingEnabled = NO;
    

    更新:附加Swift 4.2版本

    ...
    collectionView.isPagingEnabled = false
    ...
    
    class YourCollectionLayoutSubclass: UICollectionViewFlowLayout {
    
        private var previousOffset: CGFloat = 0
        private var currentPage: Int = 0
    
        override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint {
            guard let collectionView = collectionView else {
                return super.targetContentOffset(forProposedContentOffset: proposedContentOffset, withScrollingVelocity: velocity)
            }
    
            let itemsCount = collectionView.numberOfItems(inSection: 0)
    
            // Imitating paging behaviour
            // Check previous offset and scroll direction
            if previousOffset > collectionView.contentOffset.x && velocity.x < 0 {
                currentPage = max(currentPage - 1, 0)
            } else if previousOffset < collectionView.contentOffset.x && velocity.x > 0 {
                currentPage = min(currentPage + 1, itemsCount - 1)
            }
    
            // Update offset by using item size + spacing
            let updatedOffset = (itemSize.width + minimumInteritemSpacing) * CGFloat(currentPage)
            previousOffset = updatedOffset
    
            return CGPoint(x: updatedOffset, y: proposedContentOffset.y)
        }
    }
    

    2023-01-12 10:52 回答
  • 你可以使用代码 self.collectionView.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: true)

    2023-01-12 10:52 回答
  • 这是@ dmitry-zhukov的Swift 3版本(非常感谢btw!)

    class PagedCollectionLayout : UICollectionViewFlowLayout {
    
        var previousOffset : CGFloat = 0
        var currentPage : CGFloat = 0
    
        override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint {
    
            let sup = super.targetContentOffset(forProposedContentOffset: proposedContentOffset, withScrollingVelocity: velocity)
    
            guard
                let validCollection = collectionView,
                let dataSource = validCollection.dataSource
                else { return sup }
    
            let itemsCount = dataSource.collectionView(validCollection, numberOfItemsInSection: 0)
    
            // Imitating paging behaviour
            // Check previous offset and scroll direction
            if  (previousOffset > validCollection.contentOffset.x) && (velocity.x < 0) {
                currentPage = max(currentPage - 1, 0)
            }
            else if (previousOffset < validCollection.contentOffset.x) && (velocity.x > 0) {
                currentPage = min(currentPage + 1, CGFloat(itemsCount - 1))
            }
    
            // Update offset by using item size + spacing
            let updatedOffset = ((itemSize.width + minimumInteritemSpacing) * currentPage)
            self.previousOffset = updatedOffset
    
            let updatedPoint = CGPoint(x: updatedOffset, y: proposedContentOffset.y)
    
            return updatedPoint
        }
    }
    

    2023-01-12 10:53 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有