设置 contentInset 后 UICollectionView 不滚动 [英] UICollectionView doesn't scroll after setting contentInset

查看:82
本文介绍了设置 contentInset 后 UICollectionView 不滚动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个水平滚动并跨越其父视图全宽的集合视图.我实现分页的廉价方法是将单元格宽度设置为等于集合视图宽度的 1/3,并将宽度设置为与左右内容插入相同的宽度.

我在 IB 中禁用滚动并替换为左右滑动识别器.我的代码几乎没有设置 contentInset 就可以工作,但是设置 contentInset 似乎可以防止任何滚动发生

- (void)viewDidLayoutSubviews {[超级viewDidLayoutSubviews];CGFloat itemWidth = self.collectionView.bounds.size.width/3.0;NSInteger count = [self collectionView:self.collectionView numberOfItemsInSection:0];self.collectionView.contentSize = (CGSize){ .width=itemWidth*count, .height=self.collectionView.bounds.size.height };//取消注释这一行,下面滑动中的滚动代码不起作用//self.collectionView.contentInset = UIEdgeInsetsMake(0, itemWidth, 0, itemWidth);self.collectionView.contentOffset = (CGPoint){ .x=self.collectionView.contentSize.width/2.0, .y=0 };}- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {CGFloat 宽度 = self.view.bounds.size.width/3.0;return (CGSize){ .width=width, .height=collectionView.bounds.size.height };}

此代码处理滑动...

- (NSIndexPath *)centerIndexPath {CGRectvisibleRect = (CGRect){.origin = self.collectionView.contentOffset, .size = self.collectionView.bounds.size};CGPoint 可见点 = CGPointMake(CGRectGetMidX(visibleRect), CGRectGetMidY(visibleRect));返回 [self.collectionView indexPathForItemAtPoint:visiblePoint];}- (void)swipeLeft:(UISwipeGestureRecognizer *)gr {NSIndexPath *centerIndexPath = [self centerIndexPath];NSLog(@"at %@", centerIndexPath);if (centerIndexPath.row < [self collectionView:self.collectionView numberOfItemsInSection:0]-1) {[self.collectionView scrollToItemAtIndexPath:centerIndexPath atScrollPosition:UICollectionViewScrollPositionLeft 动画:YES];}}- (void)swipeRight:(UISwipeGestureRecognizer *)gr {NSIndexPath *centerIndexPath = [self centerIndexPath];NSLog(@"at %@", centerIndexPath);如果(centerIndexPath.row > 0){[self.collectionView scrollToItemAtIndexPath:centerIndexPath atScrollPosition:UICollectionViewScrollPositionRight 动画:YES];}}

所有这些都有效,除非我在上面的设置中设置了 contentInsets.然后,即使我到达了调试器中的 scrollToItemAtIndexPath: 代码,也不会发生滚动.

拥有这些插图很重要,因为我希望用户了解中心项目是所选项目.

有人可以解释为什么 contentInset 会破坏滚动以及如何修复吗?

解决方案

看起来 UICollectionView 有自己的内置方式来处理插入:

I have a collection view that scrolls horizontally and spans its parent view's full width. My cheap way to achieve paging on it is to set the cell widths to be equal to 1/3 of the collection view width, and to set that same amount of width as left and right content insets.

I disable scrolling in IB and replace with left and right swipe recognizers. My code almost works without setting contentInset, but setting the contentInset seems prevent any scrolling from happening

- (void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];

    CGFloat itemWidth = self.collectionView.bounds.size.width/3.0;
    NSInteger count = [self collectionView:self.collectionView numberOfItemsInSection:0];
    self.collectionView.contentSize = (CGSize){ .width=itemWidth*count, .height=self.collectionView.bounds.size.height };
    // uncomment this line, and the scroll code in the swipes below fails to work
    //self.collectionView.contentInset = UIEdgeInsetsMake(0, itemWidth, 0, itemWidth);
    self.collectionView.contentOffset = (CGPoint){ .x=self.collectionView.contentSize.width/2.0, .y=0 };
}

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
    CGFloat width = self.view.bounds.size.width/3.0;
    return (CGSize){ .width=width, .height=collectionView.bounds.size.height };
}

This code handles the swipes...

- (NSIndexPath *)centerIndexPath {
    CGRect visibleRect = (CGRect){.origin = self.collectionView.contentOffset, .size = self.collectionView.bounds.size};
    CGPoint visiblePoint = CGPointMake(CGRectGetMidX(visibleRect), CGRectGetMidY(visibleRect));
    return [self.collectionView indexPathForItemAtPoint:visiblePoint];
}

- (void)swipeLeft:(UISwipeGestureRecognizer *)gr {
    NSIndexPath *centerIndexPath = [self centerIndexPath];
    NSLog(@"at %@", centerIndexPath);

    if (centerIndexPath.row < [self collectionView:self.collectionView numberOfItemsInSection:0]-1) {
        [self.collectionView scrollToItemAtIndexPath:centerIndexPath atScrollPosition:UICollectionViewScrollPositionLeft animated:YES];
    }
}

- (void)swipeRight:(UISwipeGestureRecognizer *)gr {
    NSIndexPath *centerIndexPath = [self centerIndexPath];
    NSLog(@"at %@", centerIndexPath);

    if (centerIndexPath.row > 0) {
        [self.collectionView scrollToItemAtIndexPath:centerIndexPath atScrollPosition:UICollectionViewScrollPositionRight animated:YES];
    }
}

All of this works, except when I set the contentInsets in the setup above. Then, even though I reach the scrollToItemAtIndexPath: code in the debugger, no scrolling occurs.

It's important to have those insets, because I want user to understand that center item is the selected item.

Can somebody explain why contentInset spoils scrolling and how to fix?

解决方案

It looks like UICollectionView has its own built-in way to handle insets:

https://developer.apple.com/library/content/documentation/WindowsViews/Conceptual/CollectionViewPGforIOS/UsingtheFlowLayout/UsingtheFlowLayout.html#//apple_ref/doc/uid/TP40012334-CH3-SW1

Using Section Insets to Tweak the Margins of Your Content Section insets are a way to adjust the space available for laying out cells. You can use insets to insert space after a section’s header view and before its footer view. You can also use insets to insert space around the sides of the content. Figure 3-5 demonstrates how insets affect some content in a vertically scrolling flow layout.

Figure 3-5 Section insets change the available space for laying out cells

这篇关于设置 contentInset 后 UICollectionView 不滚动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆