web-dev-qa-db-fra.com

Comment savoir quand UITableView a défilé jusqu'en bas dans l'iPhone

Je voudrais savoir quand un UITableView a défilé jusqu'en bas pour charger et afficher plus de contenu, quelque chose comme un délégué ou quelque chose d'autre pour que le contrôleur sache quand le tableau est descendu en bas.

Est-ce que quelqu'un sait cela, aidez-moi s'il vous plaît, merci d'avance! 

95
Son Nguyen

Le meilleur moyen est de tester un point en bas de l'écran et d'utiliser cette méthode lorsque l'utilisateur fait défiler (scrollViewDidScroll):

- (NSIndexPath *)indexPathForRowAtPoint:(CGPoint)point

Testez un point près du bas de l'écran, puis utilisez indexPath pour vérifier si indexPath est la dernière ligne, puis ajoutez-le.

17
Ajay

dans le délégué de tableview faire quelque chose comme ça

- (void)scrollViewDidScroll:(UIScrollView *)aScrollView {
    CGPoint offset = aScrollView.contentOffset;
    CGRect bounds = aScrollView.bounds;
    CGSize size = aScrollView.contentSize;
    UIEdgeInsets inset = aScrollView.contentInset;
    float y = offset.y + bounds.size.height - inset.bottom;
    float h = size.height;
    // NSLog(@"offset: %f", offset.y);   
    // NSLog(@"content.height: %f", size.height);   
    // NSLog(@"bounds.height: %f", bounds.size.height);   
    // NSLog(@"inset.top: %f", inset.top);   
    // NSLog(@"inset.bottom: %f", inset.bottom);   
    // NSLog(@"pos: %f of %f", y, h);

    float reload_distance = 10;
    if(y > h + reload_distance) {
        NSLog(@"load more rows");
    }
}
243
neoneye

_ {Les néo-modes modifiés répondent un peu.

Cette réponse s'adresse à ceux d'entre vous qui veulent seulement que l'événement soit déclenché une fois par relâchement du doigt.

Convient lorsque vous chargez plus de contenu à partir d'un fournisseur de contenu (service Web, données de base, etc.) . Notez que cette approche ne respecte pas le temps de réponse de votre service Web.

- (void)scrollViewDidEndDragging:(UIScrollView *)aScrollView
                  willDecelerate:(BOOL)decelerate
{
    CGPoint offset = aScrollView.contentOffset;
    CGRect bounds = aScrollView.bounds;
    CGSize size = aScrollView.contentSize;
    UIEdgeInsets inset = aScrollView.contentInset;
    float y = offset.y + bounds.size.height - inset.bottom;
    float h = size.height;

    float reload_distance = 50;
    if(y > h + reload_distance) {
        NSLog(@"load more rows");
    }
}
61
Eyeball

ajoutez cette méthode dans la UITableViewDelegate:

-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{   
    CGFloat height = scrollView.frame.size.height;

    CGFloat contentYoffset = scrollView.contentOffset.y;

    CGFloat distanceFromBottom = scrollView.contentSize.height - contentYoffset;

    if(distanceFromBottom < height) 
    {
        NSLog(@"end of the table");
    }
}
38
8suhas

Aucune des réponses ci-dessus ne m'a aidé, alors je suis venu avec ceci:

- (void)scrollViewDidEndDecelerating:(UIScrollView *)aScrollView
{   
    NSArray *visibleRows = [self.tableView visibleCells];
    UITableViewCell *lastVisibleCell = [visibleRows lastObject];
    NSIndexPath *path = [self.tableView indexPathForCell:lastVisibleCell];
    if(path.section == lastSection && path.row == lastRow)
    {
        // Do something here
    }
}
19
Iftach Orr

Utiliser la méthode – tableView:willDisplayCell:forRowAtIndexPath: (UITableViewDelegate)

Il vous suffit de comparer la indexPath avec les éléments de votre tableau de données (ou la source de données que vous utilisez pour la vue tableau) pour déterminer si le dernier élément est affiché.

Docs: http://developer.Apple.com/library/ios/documentation/uikit/reference/UITableViewDelegate_Protocol/Reference/Reference.html#//Apple_ref/occ/intfm/UITableViewDelegate/tableView : willDisplayCell: forRowAtIndexPath :

19
Wolfgang Schreurs

UITableView est une sous-classe de UIScrollView et UITableViewDelegate est conforme à UIScrollViewDelegate. Ainsi, le délégué que vous attachez à la vue table obtiendra des événements tels que scrollViewDidScroll: et vous pourrez appeler des méthodes telles que contentOffset sur la vue table pour rechercher la position de défilement.

13
Anomie
NSLog(@"%f / %f",tableView.contentOffset.y, tableView.contentSize.height - tableView.frame.size.height);

if (tableView.contentOffset.y == tableView.contentSize.height - tableView.frame.size.height)
        [self doSomething];

Gentil et simple

8
user1641587

dans Swift vous pouvez faire quelque chose comme ceci. La condition suivante sera vraie chaque fois que vous atteindrez la fin de la tableview

func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
        if indexPath.row+1 == postArray.count {
            println("came to last row")
        }
}
8
Jay Mayu

S'appuyant sur la réponse de @Jay Mayu, que j'ai trouvée être l'une des meilleures solutions

Objectif c

// UITableViewDelegate
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {

// Need to call the service & update the array
if(indexPath.row + 1 == self.sourceArray.count) {
    DLog(@"Displayed the last row!");
  }
}

Swift 2.x

// UITableViewDelegate
func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
    if (indexPath.row + 1) == sourceArray.count {
        print("Displayed the last row!")
    }
}
6
footyapps27

Prendre neoneye d'excellentes réponses mais en Swift, et renommer les variables. 

Fondamentalement, nous savons que nous avons atteint le bas de la vue du tableau si la variable yOffsetAtBottom dépasse la hauteur du contenu du tableau.

func isTableViewScrolledToBottom() -> Bool {
    let tableHeight = tableView.bounds.size.height
    let contentHeight = tableView.contentSize.height
    let insetHeight = tableView.contentInset.bottom

    let yOffset = tableView.contentOffset.y
    let yOffsetAtBottom = yOffset + tableHeight - insetHeight

    return yOffsetAtBottom > contentHeight
}
5
samwize

J'utilise généralement cela pour charger plus de données, lorsque la dernière cellule commence à s'afficher

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
   if (indexPath.row ==  myDataArray.count-1) {
        NSLog(@"load more");
    }
}
5
Shaik Riyaz

Voici le code de version de Swift 3.0.

   func scrollViewDidScroll(_ scrollView: UIScrollView) {

        let offset = scrollView.contentOffset
        let bounds = scrollView.bounds
        let size = scrollView.contentSize
        let inset = scrollView.contentInset
        let y: Float = Float(offset.y) + Float(bounds.size.height) + Float(inset.bottom)
        let height: Float = Float(size.height)
        let distance: Float = 10

        if y > height + distance {
            // load more data
        }
    }
5
Morshed Alam

Ma solution consiste à ajouter des cellules avant que tableview ne décélère en fonction du décalage estimé. C'est prévisible par vélocité.

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)offset {

    NSLog(@"offset: %f", offset->y+scrollView.frame.size.height);
    NSLog(@"Scroll view content size: %f", scrollView.contentSize.height);

    if (offset->y+scrollView.frame.size.height > scrollView.contentSize.height - 300) {
        NSLog(@"Load new rows when reaches 300px before end of content");
        [[DataManager shared] fetchRecordsNextPage];
    }
}
3
Firuz Narzikulov

Mise à jour pour Swift 3

La réponse de Neoneye a fonctionné le mieux pour moi dans l'Objectif C, c'est l'équivalent de la réponse dans Swift 3:

func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
    let offset: CGPoint = scrollView.contentOffset
    let bounds: CGRect = scrollView.bounds
    let size: CGSize = scrollView.contentSize
    let inset: UIEdgeInsets = scrollView.contentInset
    let y: CGFloat = offset.y + bounds.size.height - inset.bottom
    let h: CGFloat = size.height
//        print("offset: %f", offset.y)
//        print("content.height: %f", size.height)
//        print("bounds.height: %f", bounds.size.height)
//        print("inset.top: %f", inset.top)
//        print("inset.bottom: %f", inset.bottom)
//        print("position: %f of %f", y, h)

    let reloadDistance: CGFloat = 10

    if (y > h + reloadDistance) {
            print("load more rows")
    }
}
3
Ibrahim

Je veux effectuer une action sur mon tout 1 tableviewcell complet.

Donc, le code est lié au:

-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    NSArray* cells = self.tableView.visibleCells;
    NSIndexPath *indexPath = nil ;

    for (int aIntCount = 0; aIntCount < [cells count]; aIntCount++)
    {

        UITableViewCell *cell = [cells objectAtIndex:aIntCount];
CGRect cellRect = [self.tableView convertRect:cell.frame toView:self.tableView.superview];

        if (CGRectContainsRect(self.tableView.frame, cellRect))
        {
            indexPath = [self.tableView indexPathForCell:cell];

    //  remain logic
        }
     }
}

Puisse cela aider quelqu'un.

2
Mayuri R Talaviya

La réponse de @ neoneye a fonctionné pour moi. Voici la Swift 4 version

    let offset = scrollView.contentOffset
    let bounds = scrollView.bounds
    let size = scrollView.contentSize
    let insets = scrollView.contentInset
    let y = offset.y + bounds.size.height - insets.bottom
    let h = size.height
    let reloadDistance = CGFloat(10)
    if y > h + reloadDistance {
        //load more rows
    }
0
Anuran Barman