web-dev-qa-db-ja.com

リロード時にUITableviewを取得してページの上部に移動するにはどうすればよいですか?

以下を呼び出すときにテーブルデータを再ロードすると、UITableviewをページの上部に移動しようとしています

- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {

    // A bunch of code...

    [TableView reloadData];
}

同じ行に沿って、テーブルデータを再読み込みするときに、特定のセクションに移動できるようにもしたいと思います。

次のものを配置しようとしましたが、これはリロードの前後に行にのみ当てはまるようですが、何も起こりません。

[TableView scrollToRowAtIndexPath:0 atScrollPosition:UITableViewScrollPositionTop  animated:YES];
34
AppsToKnow

これを行う別の方法を次に示します。

Objective-C

[tableView setContentOffset:CGPointZero animated:YES];

Swift 3以降

tableView.setContentOffset(.zero, animated: true)

おそらくそれを行うための最も簡単で簡単な方法です。

65
Erik B

ここや他の場所ですべての答えを読んだ後、最終的に、確実に機能し、データのロード後にスクロールが表示されないソリューションを見つけました。私の答えはこれに基づいています post およびコンテンツインセットを使用している場合は負のオフセットが必要であるという私の観察:

func reloadAndScrollToTop() {
    tableView.reloadData()
    tableView.layoutIfNeeded()
    tableView.contentOffset = CGPoint(x: 0, y: -tableView.contentInset.top)
}
30
phatmann

これは私のために働いています。

tableView.scrollToRow(at: IndexPath.init(row: 0, section: 0), at: .top, animated: true)
20
Vetuka

特定のセクションにスクロールするには、そのセクションへのインデックスパスを指定する必要があります。

NSIndexPath *topPath = [NSIndexPath indexPathForRow:0 inSection:0];
[TableView scrollToRowAtIndexPath:topPath
                 atScrollPosition:UITableViewScrollPositionTop
                         animated:YES];

TableViewの行数が不明な場合。以下を使用します。

NSIndexPath *topPath = [NSIndexPath indexPathForRow:NSNotFound inSection:0];
[TableView scrollToRowAtIndexPath:topPath
                 atScrollPosition:UITableViewScrollPositionTop
                         animated:YES];
19
ragamufin

アニメーションなし

私はiOS11を使用していて、粘着性のあるヘッダーを含むプレーンなテーブルビュースタイルを使用しています。リロード後、奇妙なちらつきやアニメーションの動作なしにテーブルビューが本当に上に来るようにするには、これらのメソッドをこの順序で使用するしかありませんでしたこれらすべてが必要な場合:

[self.tableView setContentOffset:CGPointZero animated:NO];
[self.tableView reloadData];
[self.tableView layoutIfNeeded];
[self.tableView setContentOffset:CGPointZero animated:NO];

最初の行はまったく関係がないように見えますが、これらすべてが必要であることは深刻です。そうそう、また非常に重要、これを使用しないでください:

self.tableView.contentOffset = CGPointZero;

「setContentOffset animated:FALSE」と同じだと思うかもしれませんが、明らかに違います! Appleはこのメソッドを別の方法で扱います。私の場合、これはanimated:FALSEで完全なメソッドを使用した場合にのみ機能しました。

WITH ANIMATION

私はまた、上に素敵なスクロールアニメーションでこれを試したかったです。そこでは、コンテンツオフセットメソッドがまだいくつかの奇妙なアニメーション動作を引き起こすように見えました。試行錯誤を繰り返した後、ニースアニメーションでこれを機能させる唯一の方法は、これらの方法をこの順序で実行することでした。

[self.tableView reloadData];
[self.tableView layoutIfNeeded];
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:TRUE];

警告:コードの最後の行を実行する前に、クラッシュを回避するために少なくとも1行あることを確認してください:)

これが誰かの役に立つことを願っています!

16
Bob de Graaf

UITableViewはUIScrollViewのサブクラスなので、次のものも使用できます。

[mainTableView scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:YES];
4
D.Enchev

Swift 3.1

DispatchQueue.main.async(execute: {

        self.TableView.reloadData()
        self.TableView.contentOffset = .zero

    })
2
Mahipalsinh

これに対する解決策がまだ見つかっている場合は、UITableViewの次の拡張子を使用できます。

最初のセクションに行があるかどうかのチェックを含みます。行のあるセクションが表示されるまで表示され、そのセクションまでスクロールします。

extension UITableView {

    func scrollToFirst() {

        self.reloadData() // if you don't want to reload data, remove this one.
        for i in 0..<self.numberOfSections {

            if self.numberOfRows(inSection: i) != 0 {

                self.scrollToRow(at: IndexPath(row: 0, section: i), at: .top, animated: true) 
                break 
            }
        }
    }
}

お役に立てば幸いです。

2
viral

次のコード行を使用して、テーブルビューの最初の行でUITableViewをスクロールする必要があります。

self.yourTableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top, animated: true)
1
Rahul Panzade

再ロードする前にスクロールして行数が減少すると、奇妙なアニメーション動作が発生する可能性があります。リロード後に確実にスクロールするようにするには、次のような方法を使用します。

- (void)reloadTableViewAndScrollToTop:(BOOL)scrollToTop {
    [self.tableView reloadData];
    if (scrollToTop) {
        [self.tableView setContentOffset:CGPointZero animated:YES];
    }
}
1
skensell

説明が不完全だったため、この質問に対するいくつかの回答に少し戸惑いました。私が集めたものから、OPが要求したものを達成するための2つのルートがあり、それらは次のとおりです。

  1. アニメーションが必要ない場合は、オフセットメソッドの1つを使用してデータをロードする前にスクロール位置をリセットすることをお勧めします。 reloadDataの前にオフセットを実行する必要があるのは、reloadDataが非同期で実行されるためです。リロード後にオフセットを実行すると、スクロール位置はおそらく上から数行下になります。

    tableView.setContentOffset(.zero, animated: false)
    tableView.reloadData()
    
  2. アニメーションが必要な場合は、scrollToRowを使用してreloadDataを実行した後、スクロールを一番上の行に配置します。ここでscrollToRowが機能するのは、既にロードされているデータに対して相対的に配置するオフセットメソッドではなく、テーブルの最上部に配置するためです。

    tableView.reloadData()
    tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top, animated: true)
    
1
Braden Holt

2回の再読み込みにより、再読み込み時にページの上部に完全に

dataForSource = nil
tableView.reloadData()

DispatchQueue.main.asyncAfter(deadline: .now() + 0.4) {
    self.dataForSource = realData
    self.tableView.reloadData()
}
0
black_pearl

上記のオプションを検討した後、私のバージョンのソリューションは次のとおりです。 UICollectionViewとUITableViewの両方でiOS 11と12で一貫して動作します。

UICollectionView:

DispatchQueue.main.async { [weak self] in
    guard self?.<your model object>.first != nil else { return }

    self?.collectionView.scrollToItem(at: IndexPath(row: 0, section: 0),
                               at: .top,
                                     animated: false)
}

UITableView:

DispatchQueue.main.async { [weak self] in
    guard self?.<your model object>.first != nil else { return }

    self?.collectionView.scrollToRow(at: IndexPath(row: 0, section: 0),
                               at: .top,
                                     animated: false)
}
0
DCDC