web-dev-qa-db-fra.com

UITableView - défiler vers le haut

Dans ma vue tableau, je dois faire défiler vers le haut. Mais je ne peux pas garantir que le premier objet sera la section 0, ligne 0. Peut-être que la vue de mon tableau commencera à la section 5.

Je reçois donc une exception lorsque j'appelle:

[mainTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO];

Existe-t-il un autre moyen de faire défiler la vue tableau?

355

UITableView est une sous-classe de UIScrollView, vous pouvez donc également utiliser:

[mainTableView scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:YES];

Ou

[mainTableView setContentOffset:CGPointZero animated:YES];

Et à Swift:

mainTableView.setContentOffset(CGPointZero, animated:true)

Et dans Swift 3 et ci-dessus:

mainTableView.setContentOffset(.zero, animated: true)
790
catlan

Je préfère

[mainTableView setContentOffset:CGPointZero animated:YES];

Si vous avez un encart en haut sur votre vue table, vous devez le soustraire:

[mainTableView setContentOffset:CGPointMake(0.0f, -mainTableView.contentInset.top) animated:YES];
241
fabb

Actions possibles:  

func scrollToFirstRow() {
    let indexPath = NSIndexPath(forRow: 0, inSection: 0)
    self.tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Top, animated: true)
}

func scrollToLastRow() {
    let indexPath = NSIndexPath(forRow: objects.count - 1, inSection: 0)
    self.tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Bottom, animated: true)
}

func scrollToSelectedRow() {
    let selectedRows = self.tableView.indexPathsForSelectedRows
    if let selectedRow = selectedRows?[0] as? NSIndexPath {
        self.tableView.scrollToRowAtIndexPath(selectedRow, atScrollPosition: .Middle, animated: true)
    }
}

func scrollToHeader() {
    self.tableView.scrollRectToVisible(CGRect(x: 0, y: 0, width: 1, height: 1), animated: true)
}

func scrollToTop(){
    self.tableView.setContentOffset(CGPointMake(0,  UIApplication.sharedApplication().statusBarFrame.height ), animated: true)
}

Désactiver Défilement vers le haut:

func disableScrollsToTopPropertyOnAllSubviewsOf(view: UIView) {
    for subview in view.subviews {
        if let scrollView = subview as? UIScrollView {
            (scrollView as UIScrollView).scrollsToTop = false
        }
        self.disableScrollsToTopPropertyOnAllSubviewsOf(subview as UIView)
    }
}

Modifiez-le et utilisez-le selon vos besoins.

Swift 4

  func scrollToFirstRow() {
    let indexPath = IndexPath(row: 0, section: 0)
    self.tableView.scrollToRow(at: indexPath, at: .top, animated: true)
  }
58
A.G

Il vaut mieux ne pas utiliser NSIndexPath (table vide), ni supposer que le point le plus élevé est CGPointZero (encarts de contenu), c'est ce que j'utilise -

[tableView setContentOffset:CGPointMake(0.0f, -tableView.contentInset.top) animated:YES];

J'espère que cela t'aides.

26
Kof

Swift 4 :

Cela fonctionne très bien:

//self.tableView.reloadData() if you want to use this line remember to put it before 
let indexPath = IndexPath(row: 0, section: 0)
self.tableView.scrollToRow(at: indexPath, at: .top, animated: true)
16

Pour les tables ayant une contentInset, définir le contenu du décalage sur CGPointZero ne fonctionnera pas. Il fera défiler vers le haut le contenu vs défilement vers le haut de la table.

La prise en compte du contenu produit ceci à la place:

[tableView setContentOffset:CGPointMake(0, -tableView.contentInset.top) animated:NO];
12
Eran Goldin

Sous iOS 11, utilisez adjustedContentInset pour vous déplacer correctement vers le haut dans les deux cas, lorsque la barre d'état en cours d'appel est visible ou non.

if (@available(iOS 11.0, *)) {
    [tableView setContentOffset:CGPointMake(0, -tableView.adjustedContentInset.top) animated:YES];
} else {
    [tableView setContentOffset:CGPointMake(0, -tableView.contentInset.top) animated:YES];
}

Rapide:

if #available(iOS 11.0, *) {
    tableView.setContentOffset(CGPoint(x: 0, y: -tableView.adjustedContentInset.top), animated: true)
} else {
    tableView.setContentOffset(CGPoint(x: 0, y: -tableView.contentInset.top), animated: true)
}
10
Thanh Pham

Ce code vous permet de faire défiler une section spécifique vers le haut

CGRect cellRect = [tableinstance rectForSection:section];
CGPoint Origin = [tableinstacne convertPoint:cellRect.Origin 
                                    fromView:<tableistance>];
[tableinstance setContentOffset:CGPointMake(0, Origin.y)];
10
Ramesh Muthe

Rapide:

tableView.setContentOffset(CGPointZero, animated: true)
8
Esqarrouth

En ajoutant à ce qui a déjà été dit, vous pouvez créer une extension (Swift) ou une catégorie (Objective C) pour faciliter cela à l'avenir:

Rapide:

extension UITableView {
    func scrollToTop(animated: Bool) {
        setContentOffset(CGPointZero, animated: animated)
    }
}

Chaque fois que vous souhaitez faire défiler une tableView donnée vers le haut, vous pouvez appeler le code suivant:

tableView.scrollToTop(animated: true)
8
ocwang

J'ai rencontré un problème lors de l'appel de certaines méthodes sur une tableView vide. Voici une autre option pour Swift 4 qui gère les vues de table vides.

extension UITableView {
  func hasRowAtIndexPath(indexPath: IndexPath) -> Bool {
    return indexPath.section < self.numberOfSections && indexPath.row < self.numberOfRows(inSection: indexPath.section)
  }

  func scrollToTop(animated: Bool) {
    let indexPath = IndexPath(row: 0, section: 0)
    if self.hasRowAtIndexPath(indexPath: indexPath) {
      self.scrollToRow(at: indexPath, at: .top, animated: animated)
    }
  }
}

Usage:

// from yourViewController or yourTableViewController
tableView.scrollToTop(animated: true)//or false
7
Adrian

Swift 3

tableView.setContentOffset(CGPoint.zero, animated: true)

si tableView.setContentOffset ne fonctionne pas.

Utilisation: 

tableView.beginUpdates()
tableView.setContentOffset(CGPoint.zero, animated: true)
tableView.endUpdates()

Rapide : 

si vous n'avez pas d'en-tête tableView:

tableView.setContentOffset(CGPointMake(0,  UIApplication.sharedApplication().statusBarFrame.height ), animated: true)

si c'est le cas :

tableView.setContentOffset(CGPointMake(0, -tableViewheader.frame.height   + UIApplication.sharedApplication().statusBarFrame.height ), animated: true)
6
jmcastel

Je préfère ce qui suit, car il prend en compte un encart. S'il n'y a pas d'encart, il défilera toujours vers le haut car l'encart sera 0.

tableView.setContentOffset(CGPoint(x: 0, y: -tableView.contentInset.top), animated: true)
5
Jacob Caraballo

Puisque ma tableView est pleine de toutes sortes d’encarts, c’est la seule chose qui a bien fonctionné:

Swift 3

if tableView.numberOfSections > 0 && tableView.numberOfRows(inSection: 0) > 0 {
  tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top, animated: true)
}

Swift 2

if tableView.numberOfSections > 0 && tableView.numberOfRowsInSection(0) > 0 {
  tableView.scrollToRowAtIndexPath(NSIndexPath(forRow: 0, inSection: 0), atScrollPosition: .Top, animated: true)
}
4
budidino

Voici ce que j'utilise pour fonctionner correctement sur iOS 11:

extension UIScrollView {
    func scrollToTop(animated: Bool) {
        var offset = contentOffset
        if #available(iOS 11, *) {
            offset.y = -adjustedContentInset.top
        } else {
            offset.y = -contentInset.top
        }
        setContentOffset(offset, animated: animated)
    }
}
3
Hans Brende

NE PAS UTILISER

 tableView.setContentOffset(.zero, animated: true)

Il peut parfois régler le décalage de manière incorrecte. Par exemple, dans mon cas, la cellule se situait légèrement au-dessus de la vue avec des zones de sécurité. Pas bon. 

INSTEAD USE

 tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top, animated: true)
3
ScottyBlades

utiliser contentOffset n'est pas la bonne façon. ce serait mieux car c'est la manière naturelle de table view

tableView.scrollToRow(at: NSIndexPath.init(row: 0, section: 0) as IndexPath, at: .top, animated: true)
2
Gulz

Swift 4 via extension, gère la vue de table vide:

extension UITableView {
    func scrollToTop(animated: Bool) {
        self.setContentOffset(CGPoint.zero, animated: animated);
    }
}
2
Shawn

Je devais ajouter la multiplication par -1 * à la somme de la barre d'état et de la barre de navigation, car la hauteur était dépassée,

self.tableView.setContentOffset(CGPointMake(0 , -1 * 
  (self.navigationController!.navigationBar.height +  
  UIApplication.sharedApplication().statusBarFrame.height) ), animated:true)
1
Carlos.V
func scrollToTop() {
        NSIndexPath *topItem = [NSIndexPath indexPathForItem:0 inSection:0];
        [tableView scrollToRowAtIndexPath:topItem atScrollPosition:UITableViewScrollPositionTop animated:YES];
}

appelez cette fonction où vous voulez UITableView faites défiler vers le haut

1
Sayali Shinde

Ce fut le seul extrait de code qui a fonctionné pour moi

Swift 4:

    tableView.scrollRectToVisible(CGRect(x: 0, y: 0, width: 1, height: 1), animated: true)
    tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top, animated: true)
    tableView.setContentOffset(CGPoint(x: 0, y: -70), animated: true)

P.S. 70 est la hauteur de ma cellule d'en-tête et de table

1
jimmyruby

Dans Swift 5, Merci @ Adrian répond beaucoup

extension UITableView{

    func hasRowAtIndexPath(indexPath: IndexPath) -> Bool {
        return indexPath.section < numberOfSections && indexPath.row < numberOfRows(inSection: indexPath.section)
    }

    func scrollToTop(_ animated: Bool = false) {
        let indexPath = IndexPath(row: 0, section: 0)
        if hasRowAtIndexPath(indexPath: indexPath) {
            scrollToRow(at: indexPath, at: .top, animated: animated)
        }
    }

}

Usage:

tableView.scrollToTop()
1
dengST30

Voici le code pour faire défiler TableView To Top par programme

Rapide:

self.TableView.setContentOffset(CGPointMake(0, 1), animated:true)
1

Dans Swift-3:

self.tableView.setContentOffset(CGPoint.zero, animated: true)
1
Jeni Khant

J'utilise tabBarController et j'ai quelques sections dans ma tableview à chaque onglet, donc c'est la meilleure solution pour moi.

extension UITableView {

    func scrollToTop(){

        for index in 0...numberOfSections - 1 {
            if numberOfSections > 0 && numberOfRows(inSection: index) > 0 {
                scrollToRow(at: IndexPath(row: 0, section: index), at: .top, animated: true)
                break
            }

            if index == numberOfSections - 1 {
                setContentOffset(.zero, animated: true)
                break
            }
        }

    }

}
1
Okan Yücel

Pour avoir une fin lorsque vous avez terminé, ajoutez cette extension

// MARK: - UIScrollView

extension UIScrollView {

    /// Animate scroll to top with completion
    ///
    /// - Parameters:
    ///   - duration:   TimeInterval
    ///   - completion: Completion block
    func animateScrollToTop(withDuration duration:  TimeInterval,
                            completion:             @escaping (()->())) {

        UIView.animate(withDuration: duration, animations: { [weak self] in
                self?.setContentOffset(CGPoint.zero, animated: false)
            }, completion: { finish in
                guard finish else {
                    return
                }
                completion()
        })
    }
}

tableView.animateScrollToTop(withDuration: 0.25) { 
    // Finish
}
0
YannickSteph

Si vous souhaitez déplacer une animation de défilement dans le tableau, utilisez ce code. Le défilement se déplace vers le haut avec animation en 0.5 secondes.

[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];

[_tableContent scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:YES];

[UIView commitAnimations];
0
Matheus Veloza

à Swift 

votre ligne = selectioncellRowNumber votre section si vous avez = selectionNumber si vous n'avez pas défini est à zéro

//UITableViewScrollPosition.Middle ou Bottom ou Top

var lastIndex = NSIndexPath(forRow:  selectioncellRowNumber, inSection: selectionNumber)
self.tableView.scrollToRowAtIndexPath(lastIndex, atScrollPosition: UITableViewScrollPosition.Middle, animated: true)
0
idris yıldız

Avec Swift:

self.scripSearchView.quickListTbl?.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Top, animated: true)
0
Dhananjay Patil