为了账号安全,请及时绑定邮箱和手机立即绑定

targetContentOffsetForProposedContentOffset:

targetContentOffsetForProposedContentOffset:

汪汪一只猫 2019-12-07 15:44:36
我的应用程序中有一个非常简单的collectionView(仅一行方形缩略图)。我想拦截滚动,以便偏移量始终在左侧保留完整图像。此刻,它滚动到任何地方,都将留下剪切的图像。无论如何,我知道我需要使用该功能- (CGPoint)targetContentOffsetForProposedContentOffset:withScrollingVelocity做到这一点,但我只是使用一个标准UICollectionViewFlowLayout。我不是子类化。没有子类,有没有办法拦截它UICollectionViewFlowLayout?
查看完整描述

3 回答

?
RISEBY

TA贡献1856条经验 获得超5个赞

好的,答案是否定的,没有子类化UICollectionViewFlowLayout,就无法做到这一点。


但是,对于以后阅读此书的任何人来说,将其分类非常容易。


首先,我设置了子类调用MyCollectionViewFlowLayout,然后在界面构建器中,将集合视图布局更改为“自定义”,然后选择了流布局子类。


因为您是用这种方式做的,所以您无法在IB中指定项目大小等,因此在MyCollectionViewFlowLayout.m中,我有这个...


- (void)awakeFromNib

{

    self.itemSize = CGSizeMake(75.0, 75.0);

    self.minimumInteritemSpacing = 10.0;

    self.minimumLineSpacing = 10.0;

    self.scrollDirection = UICollectionViewScrollDirectionHorizontal;

    self.sectionInset = UIEdgeInsetsMake(10.0, 10.0, 10.0, 10.0);

}

这将为我设置所有尺寸以及滚动方向。


然后 ...


- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity

{

    CGFloat offsetAdjustment = MAXFLOAT;

    CGFloat horizontalOffset = proposedContentOffset.x + 5;


    CGRect targetRect = CGRectMake(proposedContentOffset.x, 0, self.collectionView.bounds.size.width, self.collectionView.bounds.size.height);


    NSArray *array = [super layoutAttributesForElementsInRect:targetRect];


    for (UICollectionViewLayoutAttributes *layoutAttributes in array) {

        CGFloat itemOffset = layoutAttributes.frame.origin.x;

        if (ABS(itemOffset - horizontalOffset) < ABS(offsetAdjustment)) {

            offsetAdjustment = itemOffset - horizontalOffset;

        }

    }


    return CGPointMake(proposedContentOffset.x + offsetAdjustment, proposedContentOffset.y);

}

这样可以确保滚动在左侧边缘以5.0的边距结束。


这就是我要做的。我根本不需要在代码中设置流布局。


查看完整回答
反对 回复 2019-12-07
?
跃然一笑

TA贡献1826条经验 获得超6个赞

它不能很好地处理用户轻弹。用户快速滑动而滚动没有移动太多的情况下,会出现动画故障。


我提出的替代实现与以前提出的分页相同,但是可以处理页面之间的用户滑动。


 #pragma mark - Pagination

 - (CGFloat)pageWidth {

     return self.itemSize.width + self.minimumLineSpacing;

 }


 - (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity

 {           

        CGFloat rawPageValue = self.collectionView.contentOffset.x / self.pageWidth;

        CGFloat currentPage = (velocity.x > 0.0) ? floor(rawPageValue) : ceil(rawPageValue);

        CGFloat nextPage = (velocity.x > 0.0) ? ceil(rawPageValue) : floor(rawPageValue);


        BOOL pannedLessThanAPage = fabs(1 + currentPage - rawPageValue) > 0.5;

        BOOL flicked = fabs(velocity.x) > [self flickVelocity];

        if (pannedLessThanAPage && flicked) {

            proposedContentOffset.x = nextPage * self.pageWidth;

        } else {

            proposedContentOffset.x = round(rawPageValue) * self.pageWidth;

        }


        return proposedContentOffset;

 }


 - (CGFloat)flickVelocity {

     return 0.3;

 }


查看完整回答
反对 回复 2019-12-07
?
隔江千里

TA贡献1906条经验 获得超10个赞

接受答案的Swift版本。


override func targetContentOffsetForProposedContentOffset(proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint {

    var offsetAdjustment = CGFloat.greatestFiniteMagnitude

    let horizontalOffset = proposedContentOffset.x

    let targetRect = CGRect(origin: CGPoint(x: proposedContentOffset.x, y: 0), size: self.collectionView!.bounds.size)


    for layoutAttributes in super.layoutAttributesForElements(in: targetRect)! {

        let itemOffset = layoutAttributes.frame.origin.x

        if (abs(itemOffset - horizontalOffset) < abs(offsetAdjustment)) {

            offsetAdjustment = itemOffset - horizontalOffset

        }

    }


    return CGPoint(x: proposedContentOffset.x + offsetAdjustment, y: proposedContentOffset.y)

}

对Swift 3有效。


查看完整回答
反对 回复 2019-12-07
  • 3 回答
  • 0 关注
  • 1995 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信