web-dev-qa-db-ger.com

UITableView, beim Neuladen nach unten scrollen?

Ich habe eine UITableView mit cells, die dynamisch aktualisiert wird. Alles funktioniert gut, außer wenn tableview.reload aufgerufen wird (siehe unten), um die cells in der Tabelle zu aktualisieren. 

- (void)reloadTable:(NSNotification *)notification {
    NSLog(@"RELOAD TABLE ...");
    [customTableView reloadData];
    // Scroll to bottom of UITable here ....
}

Ich plante, scrollToRowAtIndexPath:atScrollPosition:animated: zu verwenden, bemerkte dann jedoch, dass ich keinen Zugriff auf eine indexPath habe.

Weiß jemand, wie das geht, oder von einem delegate-Rückruf, den ich verwenden könnte?

58
fuzzygoat

Benutzen:

NSIndexPath* ipath = [NSIndexPath indexPathForRow: cells_count-1 inSection: sections_count-1];
[tableView scrollToRowAtIndexPath: ipath atScrollPosition: UITableViewScrollPositionTop animated: YES];

Oder Sie können den Abschnittsindex manuell angeben (Wenn ein Abschnitt => Index = 0).

120
Max

Eine andere Lösung besteht darin, den Tisch vertikal zu spiegeln und jede Zelle vertikal zu spiegeln:

Wenden Sie die Transformation bei der Initialisierung auf die UITableView an:

tableview.transform = CGAffineTransformMakeScale(1, -1);

und in cellForRowAtIndexPath:

cell.transform = CGAffineTransformMakeScale(1, -1);

Auf diese Weise benötigen Sie keine Problemumgehungen für Bildlaufprobleme, Sie müssen jedoch etwas mehr über contentInsets/contentOffsets und die Kopf-/Fußzeile-Interaktionen nachdenken.

35
Michael Wilson
-(void)scrollToBottom{

        [self.tableView scrollRectToVisible:CGRectMake(0, self.tableView.contentSize.height - self.tableView.bounds.size.height, self.tableView.bounds.size.width, self.tableView.bounds.size.height) animated:YES];

}
33
mkral
//In Swift 

var iPath = NSIndexPath(forRow: self.tableView.numberOfRowsInSection(0)-1, 
                        inSection: self.tableView.numberOfSections()-1)
self.tableView.scrollToRowAtIndexPath(iPath, 
                                      atScrollPosition: UITableViewScrollPosition.Bottom,                     
                                      animated: true)
9
ytbryan

Dies ist eine andere Lösung, die in meinem Fall gut funktioniert hat, wenn die Zellenhöhe groß ist. 

- (void)scrollToBottom
{
    CGPoint bottomOffset = CGPointMake(0, _bubbleTable.contentSize.height - _bubbleTable.bounds.size.height);
    if ( bottomOffset.y > 0 ) {
        [_bubbleTable setContentOffset:bottomOffset animated:YES];
    }
}
4
wzbozon

Da dies etwas ist, das Sie häufig verwenden möchten, sollten Sie eine Klassenerweiterung in UITableView erstellen:

extension UITableView {
    func scrollToBottom(animated: Bool = true) {
        let section = self.numberOfSections
        if section > 0 {
            let row = self.numberOfRowsInSection(section - 1)
            if row > 0 {
                self.scrollToRowAtIndexPath(NSIndexPath(forRow: row - 1, inSection: section - 1), atScrollPosition: .Bottom, animated: animated)
            }
        }
    }
}
4
jfgrang

die Erweiterung ist besser für UIScrollView anstelle von UITableView auszuführen. Auf diese Weise funktioniert sie für ScrollView, TableView, CollectionView (vertikal), UIWebView (innere Scrollansicht) usw.

public extension UIScrollView {

    public func scrollToBottom(animated animated: Bool) {
        let rect = CGRectMake(0, contentSize.height - bounds.size.height, bounds.size.width, bounds.size.height)
        scrollRectToVisible(rect, animated: animated)
    }

}
1
aryaxt

Swift 3

Für alle, die versuchen, herauszufinden, wie dieses Problem gelöst werden kann, müssen Sie die .layoutIfNeeded()-Methode nach .reloadData() aufrufen:

tableView.reloadData()
tableView.layoutIfNeeded()
tableView.setContentOffset(CGPoint(x: 0, y: tableView.contentSize.height - tableView.frame.height), animated: false)

Ich arbeitete mit mehreren Abschnitten in UITableView und es hat gut funktioniert.

0
Chris Tsitsaris

Das ist der beste Weg.

- (void)scrollToBottom
{
    CGFloat yOffset = 0;

    if (self.tableView.contentSize.height > self.tableView.bounds.size.height) {
        yOffset = self.tableView.contentSize.height - self.tableView.bounds.size.height;
    }

    [self.tableView setContentOffset:CGPointMake(0, yOffset) animated:NO];
}
0
Jigar Patel

versuchen Sie diesen Code, es kann Ihnen helfen:

    self.tableView.reloadData()
    DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()+0.1, execute: {
        let indexPath = IndexPath(row: self.dateSource.count-1, section: 0)
        self.tableView.scrollToRow(at: indexPath, at: UITableViewScrollPosition.bottom, animated: true)
    })
0
muhlenXi

Swift 5

    func scrollToBottom() {
        let section = self.tableView.numberOfSections
        let row = self.tableView.numberOfRows(inSection: self.tableView.numberOfSections - 1) - 1;
        guard (section > 0) && (row > 0) else{ // check bounds
            return
        }
        let indexPath = IndexPath(row: row-1, section: section-1)
        self.tableView.scrollToRow(at: indexPath, at: .top, animated: true)
    }

Ich bin nicht einverstanden, dass wir cells_count, sections_count, self.dateSource.count verwenden sollten und so weiter. Stattdessen wird der Delegierte besser sein.

0
mistdon

Fot Swift 5

extension UITableView {
    func scrollToBottom(animated: Bool = true) {
        let section = self.numberOfSections
        if section > 0 {
            let row = self.numberOfRows(inSection: section - 1)
            if row > 0 {

                self.scrollToRow(at: IndexPath(row: row-1, section: section-1), at: .bottom, animated: animated)
            }
        }
    }
}
0
pVaskou