Enable bounce/scroll for UICollectionView while no cells
Asked Answered
M

5

14

Due to some purposes(like pull to refresh), I need a UICollectionView can bounce or scroll when there is no cells -- means numberOfItemsInSection: return 0

I have my code like this:

...
        UICollectionViewFlowLayout *flowLayout =[[UICollectionViewFlowLayout alloc] init];
        flowLayout.scrollDirection = UICollectionViewScrollDirectionVertical;
        flowLayout.minimumInteritemSpacing = SPLIT_SPACE;
        flowLayout.minimumLineSpacing = SPLIT_SPACE;
        targetCollection = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height - TABBAR_HEIGHT)
                                                    collectionViewLayout:flowLayout];
        [targetCollection registerNib:[UINib nibWithNibName:@"DashboardCell" bundle:[NSBundle mainBundle]] forCellWithReuseIdentifier:@"DashboardCell"];

        targetCollection.autoresizingMask = UIViewAutoresizingFlexibleHeight;
        targetCollection.backgroundColor = [UIColor colorWithHex:@"#EAEAEA"];
        targetCollection.contentInset = UIEdgeInsetsMake(0, 0, 20, 0);
        targetCollection.alwaysBounceVertical = YES; 
...
    #pragma mark - UICollectionViewDataSource
    - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section;
    {
        return 0;
    }

However, when testing, this empty UICollectionView cannot bounce nor scroll. I suspect it is related to empty cell, but I do need to enable the bounce or scroll when no cell. This is similar to another of my problem:SVPullToRefresh cannot pull on an empty UICollectionView

Megaphone answered 10/3, 2015 at 3:42 Comment(4)
The reason this happened is your scrollview's contentSize is less than your scrollview's frameSize.You can set contentSize bigger than the framesize when initialized or reload.Perrotta
I have tried collectionView.contentSize = CGRectMake(0,0,collectionView.bounds.size.width, collectionView.bounds.size.height + 10); but no luckMegaphone
you can add a observer with keypath 'collectionView.contentSize', when contentSize changed, you can assign a new value if not bigger than the framesizePerrotta
I prefer not to use KVO right now... Could try post an answer? Thanks!Megaphone
P
-3
 - (void)_edgeInsetsToFit {
    UIEdgeInsets edgeInsets = self.collectionView.contentInset;
    CGSize contentSize = self.collectionView.contentSize;
    CGSize size = self.collectionView.bounds.size;
    CGFloat heightOffset = (contentSize.height + edgeInsets.top) - size.height;
    if (heightOffset < 0) {
        edgeInsets.bottom = size.height - (contentSize.height + edgeInsets.top) + 1;
        self.collectionView.contentInset = edgeInsets;
    } else {
        edgeInsets.bottom = 0;
        self.collectionView.contentInset = edgeInsets;
    }
}

I called that method after layoutSubviews

- (void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];
    _STAssetViewController *weakSelf = self;
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 
        [weakSelf _edgeInsetsToFit]; 
    });
}

You can try that way

Perrotta answered 10/3, 2015 at 4:4 Comment(9)
I tried your code, but still not working; I feel it is not this case. The collectionView just cannot scroll, while no cells drown on screen. If there is at least one cell, everything ok. Have you tried with an empty collection view with the code?Megaphone
I feel it is not about contentSize, when I am having one cell, the contentSize is {375, 117} and apparently 117 is within the screen, and I can still scroll or bounce; but when no cell, the content size is {375, 7}, and I dont think 117 can trigger pull while 7 cannotMegaphone
@Megaphone I tried, it works. bcs.duapp.com/vendor/product/code.png bcs.duapp.com/vendor/product/effect.png the first image is the code , i add a red view to scrollview to valid if scrolls, the second image is the result, i dragged the collectionview.Perrotta
I am sad, but what is the wrong with mine... Yours looks like my code. My lldb saying:po 0x1371ad200 <UICollectionView: 0x1371ad200; frame = (0 0; 375 559); clipsToBounds = YES; autoresize = H; gestureRecognizers = <NSArray: 0x170e55870>; layer = <CALayer: 0x170a20920>; contentOffset: {0, 0}; contentSize: {375, 7}> collection view layout: <UICollectionViewFlowLayout: 0x136f81570>, bounces:YES, Bounce Vertically On. Do you know where to look for the reason?Megaphone
@Megaphone what's the contentinsetsPerrotta
It is (top = 0, left = 0, bottom = 20, right = 0). Are you familiar with SVPullToRefresh? Now I am wondering if the gesture conflicts, because my real app is more complicated, I got a UICollectionView inside a UICollectionViewCell. I suspect my inner UICollectionView does not catch my pull gesture if no cells inside the inner UICollectionViewMegaphone
@Megaphone your height is 559, your contentHeight is 7, try make contentInset.bottom = 559-7+1Perrotta
Let us continue this discussion in chat.Megaphone
I figured out that the old project I have tried to disabled the user interaction in a silent way while updating and hit a code path does not re-enable it again.... problem solvedMegaphone
C
60

Do it like this:

self.collectionView.alwaysBounceVertical = YES;

answer by @VNJ at here

Cacao answered 17/4, 2015 at 6:30 Comment(1)
This! Took me while to find your answer. Thank you. This is default behavior for UITableView. Does anybody know why it is not the case with UICollectionViews?Vilma
P
16

Change this setting in your storyboard:

enter image description here

Potboy answered 7/2, 2016 at 22:12 Comment(0)
B
1

Swift Solution

collectionView.alwaysBounceVertical = true
Bromley answered 20/11, 2020 at 23:56 Comment(0)
M
0

You can try this:

collectionView.isScrollEnabled = false
Musky answered 7/10, 2020 at 10:14 Comment(0)
P
-3
 - (void)_edgeInsetsToFit {
    UIEdgeInsets edgeInsets = self.collectionView.contentInset;
    CGSize contentSize = self.collectionView.contentSize;
    CGSize size = self.collectionView.bounds.size;
    CGFloat heightOffset = (contentSize.height + edgeInsets.top) - size.height;
    if (heightOffset < 0) {
        edgeInsets.bottom = size.height - (contentSize.height + edgeInsets.top) + 1;
        self.collectionView.contentInset = edgeInsets;
    } else {
        edgeInsets.bottom = 0;
        self.collectionView.contentInset = edgeInsets;
    }
}

I called that method after layoutSubviews

- (void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];
    _STAssetViewController *weakSelf = self;
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 
        [weakSelf _edgeInsetsToFit]; 
    });
}

You can try that way

Perrotta answered 10/3, 2015 at 4:4 Comment(9)
I tried your code, but still not working; I feel it is not this case. The collectionView just cannot scroll, while no cells drown on screen. If there is at least one cell, everything ok. Have you tried with an empty collection view with the code?Megaphone
I feel it is not about contentSize, when I am having one cell, the contentSize is {375, 117} and apparently 117 is within the screen, and I can still scroll or bounce; but when no cell, the content size is {375, 7}, and I dont think 117 can trigger pull while 7 cannotMegaphone
@Megaphone I tried, it works. bcs.duapp.com/vendor/product/code.png bcs.duapp.com/vendor/product/effect.png the first image is the code , i add a red view to scrollview to valid if scrolls, the second image is the result, i dragged the collectionview.Perrotta
I am sad, but what is the wrong with mine... Yours looks like my code. My lldb saying:po 0x1371ad200 <UICollectionView: 0x1371ad200; frame = (0 0; 375 559); clipsToBounds = YES; autoresize = H; gestureRecognizers = <NSArray: 0x170e55870>; layer = <CALayer: 0x170a20920>; contentOffset: {0, 0}; contentSize: {375, 7}> collection view layout: <UICollectionViewFlowLayout: 0x136f81570>, bounces:YES, Bounce Vertically On. Do you know where to look for the reason?Megaphone
@Megaphone what's the contentinsetsPerrotta
It is (top = 0, left = 0, bottom = 20, right = 0). Are you familiar with SVPullToRefresh? Now I am wondering if the gesture conflicts, because my real app is more complicated, I got a UICollectionView inside a UICollectionViewCell. I suspect my inner UICollectionView does not catch my pull gesture if no cells inside the inner UICollectionViewMegaphone
@Megaphone your height is 559, your contentHeight is 7, try make contentInset.bottom = 559-7+1Perrotta
Let us continue this discussion in chat.Megaphone
I figured out that the old project I have tried to disabled the user interaction in a silent way while updating and hit a code path does not re-enable it again.... problem solvedMegaphone

© 2022 - 2024 — McMap. All rights reserved.