UITableView page size when paging enabled
Asked Answered
H

5

14

I'm facing with a simple but tedious problem. What I'm trying to do is make an UITableView to page like an UIScrollView but enabling paging doesn't help me so much because I can't set page size so the tableview scrolls exactly of its height so it shows rows 1...10 or 11...20 and so on. What I'd like instead is that no cell remains clipped above or under the view when I scroll (thus paging) without having a sort of fixed range of shown cells.

Thanks a lot

Histamine answered 25/2, 2010 at 15:38 Comment(0)
H
13

Simple but efficient:

    - (void)scrollViewDidEndDecelerating:(UITableView *)tableView {
            int tomove = ((int)tableView.contentOffset.y%(int)tableView.rowHeight);
            if(tomove < tableView.rowHeight/2) [tableView setContentOffset:CGPointMake(0, tableView.contentOffset.y-tomove) animated:YES];
            else [tableView setContentOffset:CGPointMake(0, tableView.contentOffset.y+(tableView.rowHeight-tomove)) animated:YES];
    }

    - (void)scrollViewDidEndDragging:(UITableView *)scrollView willDecelerate:(BOOL)decelerate {
            if(decelerate) return;

            [self scrollViewDidEndDecelerating:scrollView];
    }
Histamine answered 26/2, 2010 at 15:47 Comment(4)
Doesn't really work for me. Plus, because you are using DidEndDecelerating, the code is not called when there is no deceleration (ie: if the table is not "flicked", but released gently)Dilatation
So you should add the same code to - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate if willDecelerate:(BOOL)decelerate is falseNanosecond
@Nanosecond Yep, I forgot to paste the second method. Nobody noticed it for more than a year! ThxHistamine
My every 4th cell skipping. Pagination is working fine for 1st , 2nd & 3rd but as soon as I am trying to scroll4th it skip to 5thPenutian
B
18

More simple and more efficient :)

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{

    if(decelerate) return;

    [self scrollViewDidEndDecelerating:scrollView];
}


- (void)scrollViewDidEndDecelerating:(UITableView *)tableView {

    [tableView scrollToRowAtIndexPath:[tableView indexPathForRowAtPoint: CGPointMake(tableView.contentOffset.x, tableView.contentOffset.y+tableView.rowHeight/2)] atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
Baden answered 1/8, 2012 at 14:50 Comment(2)
This solution worked perfectly for me, and worked for every scroll. The other solution was a little inconsistent with its results...sometimes it would snap to the top of the cell, other times it would not.Estrella
@Estrella the reason it jumps to the top sometimes, is because you probably have a space between your items in the collectioView. In that case indexPathForRowAtPoint method will return 0,0 - which leads to the top. ;)Emaciated
H
13

Simple but efficient:

    - (void)scrollViewDidEndDecelerating:(UITableView *)tableView {
            int tomove = ((int)tableView.contentOffset.y%(int)tableView.rowHeight);
            if(tomove < tableView.rowHeight/2) [tableView setContentOffset:CGPointMake(0, tableView.contentOffset.y-tomove) animated:YES];
            else [tableView setContentOffset:CGPointMake(0, tableView.contentOffset.y+(tableView.rowHeight-tomove)) animated:YES];
    }

    - (void)scrollViewDidEndDragging:(UITableView *)scrollView willDecelerate:(BOOL)decelerate {
            if(decelerate) return;

            [self scrollViewDidEndDecelerating:scrollView];
    }
Histamine answered 26/2, 2010 at 15:47 Comment(4)
Doesn't really work for me. Plus, because you are using DidEndDecelerating, the code is not called when there is no deceleration (ie: if the table is not "flicked", but released gently)Dilatation
So you should add the same code to - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate if willDecelerate:(BOOL)decelerate is falseNanosecond
@Nanosecond Yep, I forgot to paste the second method. Nobody noticed it for more than a year! ThxHistamine
My every 4th cell skipping. Pagination is working fine for 1st , 2nd & 3rd but as soon as I am trying to scroll4th it skip to 5thPenutian
M
5

Starting with k06a's answer, I've refined it a bit so it works more like the real paginated UITableView. The differences in behaviour are quite noticeable with full screen table rows. Even a mini-flick in either direction should scroll the table to the next page: I do this by checking velocity first.

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView
                     withVelocity:(CGPoint)velocity
              targetContentOffset:(inout CGPoint *)targetContentOffset
{    
    CGFloat rowHeight = tableView.rowHeight;
    int verticalOffset = ((int)targetContentOffset->y % (int)rowHeight);
    if (velocity.y < 0)
    {
        targetContentOffset->y -= verticalOffset;
    }
    else if (velocity.y > 0)
    {
        targetContentOffset->y += (rowHeight - verticalOffset);
    }
    // No velocity, snap to closest page
    else
    {
        if (verticalOffset < rowHeight / 2)
        {
            targetContentOffset->y -= verticalOffset;
        }
        else
        {
            targetContentOffset->y += (rowHeight - verticalOffset);
        }
    }    
}

Note that additionally setting

 self.tableView.decelerationRate = UIScrollViewDecelerationRateFast;

in viewDidLoad: makes it closer to the real thing, but not quite.

I've been fiddling with setting even faster deceleration rates using the code shown here but I couldn't get it right.

Muckworm answered 8/7, 2014 at 15:30 Comment(0)
M
4

This works like real paging:

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView 
                     withVelocity:(CGPoint)velocity
              targetContentOffset:(inout CGPoint *)targetContentOffset
{
    int tomove = ((int)targetContentOffset->y % (int)self.tableView.rowHeight);
    if(tomove < self.tableView.rowHeight/2)
        targetContentOffset->y -= tomove;
    else 
        targetContentOffset->y += (self.tableView.rowHeight-tomove);
}

and make this in -viewDidLoad:

self.tableView.decelerationRate = UIScrollViewDecelerationRateFast;
Metasomatism answered 17/8, 2013 at 15:21 Comment(1)
This almost works perfectly, but fails for full screen sized cells when you do a very gentle flip (not enough of a flip for advancing the page). It instantly moves the cell back, instead of animating it smoothly.Muckworm
G
3

And in Swift...

func scrollViewDidEndDragging(scrollView: UIScrollView, willDecelerate decelerate: Bool) {
    if !decelerate {
        self.scrollViewDidEndDecelerating(scrollView)
    }
}

func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
    if let indexPathToScrollTo: NSIndexPath = self.tableView.indexPathForRowAtPoint(CGPointMake(self.tableView.contentOffset.x, self.tableView.contentOffset.y+tableView.rowHeight/2)) {
        self.tableView.scrollToRowAtIndexPath(indexPathToScrollTo, atScrollPosition: UITableViewScrollPosition.Top, animated: true)
    }
}
Guenna answered 30/6, 2015 at 14:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.