Wie kann ich einen UIScrollView-Bildlauf nach oben ausführen?
[self.scrollView setContentOffset:
CGPointMake(0, -self.scrollView.contentInset.top) animated:YES];
[self.scrollView setContentOffset:CGPointZero animated:YES];
oder wenn Sie die horizontale Bildlaufposition beibehalten und einfach die vertikale Position zurücksetzen möchten:
[self.scrollView setContentOffset:CGPointMake(self.scrollView.contentOffset.x, 0)
animated:YES];
Hier ist eine Swift Erweiterung, die es einfach macht:
extension UIScrollView {
func scrollToTop() {
let desiredOffset = CGPoint(x: 0, y: -contentInset.top)
setContentOffset(desiredOffset, animated: true)
}
}
Verwendung:
myScrollView.scrollToTop()
versuchen Sie, mit dem neuen adjustedContentInset
zu arbeiten.
Zum Beispiel (nach oben scrollen):
var offset = CGPoint(
x: -scrollView.contentInset.left,
y: -scrollView.contentInset.top)
if #available(iOS 11.0, *) {
offset = CGPoint(
x: -scrollView.adjustedContentInset.left,
y: -scrollView.adjustedContentInset.top)
}
scrollView.setContentOffset(offset, animated: true)
Auch wenn Sie
prefersLargeTitles
,safe area
etc.
Für Swift 4
scrollView.setContentOffset(.zero, animated: true)
Verwenden setContentOffset:animated:
[scrollView setContentOffset:CGPointZero animated:YES];
Antwort für Swift 2.0/3.0/4.0 und iOS 7+:
let desiredOffset = CGPoint(x: 0, y: -self.scrollView.contentInset.top)
self.scrollView.setContentOffset(desiredOffset, animated: true)
In iOS7 hatte ich Probleme damit, eine bestimmte Bildlaufansicht nach oben zu verschieben, was in iOS6 funktioniert hat, und habe diese verwendet, um die Bildlaufansicht nach oben zu verschieben.
[self.myScroller scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:NO];
Swift 3.0.1 Version von Rob Mayoffs Antwort :
self.scrollView.setContentOffset(
CGPoint(x: 0,y: -self.scrollView.contentInset.top),
animated: true)
Um das Verhalten von scrollToTop in der Statusleiste vollständig zu replizieren, müssen Sie nicht nur contentOffset festlegen, sondern auch sicherstellen, dass die scrollIndicators angezeigt werden. Andernfalls kann der Benutzer schnell verloren gehen.
Die einzige öffentliche Methode, um dies zu erreichen, ist flashScrollIndicators
. Leider hat ein einmaliger Aufruf nach dem Setzen des contentOffset keine Auswirkung, da dieser sofort zurückgesetzt wird. Ich fand es funktioniert, wenn ich den Blitz jedes Mal in scrollViewDidScroll:
.
// define arbitrary tag number in a global constants or in the .pch file
#define SCROLLVIEW_IS_SCROLLING_TO_TOP_TAG 19291
- (void)scrollContentToTop {
[self.scrollView setContentOffset:CGPointMake(self.scrollView.contentOffset.x, -self.scrollView.contentInset.top) animated:YES];
self.scrollView.tag = SCROLLVIEW_IS_SCROLLING_TO_TOP_TAG;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
self.scrollView.tag = 0;
});
}
Implementieren Sie in Ihrem UIScrollViewDelegate (oder UITable/UICollectionViewDelegate) Folgendes:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if (scrollView.tag == SCROLLVIEW_IS_SCROLLING_TO_TOP_TAG) {
[scrollView flashScrollIndicators];
}
}
Die Ausblendverzögerung ist im Vergleich zum scrollToTop-Verhalten in der Statusleiste etwas kürzer, sieht aber trotzdem gut aus.
Beachten Sie, dass ich das View-Tag missbrauche, um den Status "isScrollingToTop" zu übermitteln, da ich dies für mehrere View-Controller benötige. Wenn Sie Tags für etwas anderes verwenden, möchten Sie diese möglicherweise durch eine iVar oder eine Eigenschaft ersetzen.
Ich denke, ich habe eine Antwort, die mit iOS 11 sowie früheren Versionen (für vertikales Scrollen) vollständig kompatibel sein sollte.
Dies berücksichtigt das neue adjustedContentInset und berücksichtigt auch den zusätzlichen Offset, der erforderlich ist, wenn prefersLargeTitles in der Navigationsleiste aktiviert ist, was einen zusätzlichen 52px-Offset über den Standardwert hinaus zu erfordern scheint ist
Dies war etwas schwierig, da sich das adjustierte Inhalts-Set in Abhängigkeit vom Status der Titelleiste ändert (großer Titel vs. kleiner Titel). Ich musste also überprüfen, wie hoch die Titelleiste war, und den 52-Pixel-Versatz nicht anwenden, wenn er bereits groß ist. Es konnte keine andere Methode gefunden werden, um den Status der Navigationsleiste zu überprüfen. Wenn also jemand eine bessere Option hat als zu sehen, ob die Höhe> 44,0 ist, würde ich sie gerne hören
func scrollToTop(_ scrollView: UIScrollView, animated: Bool = true) {
if #available(iOS 11.0, *) {
let expandedBar = (navigationController?.navigationBar.frame.height ?? 64.0 > 44.0)
let largeTitles = (navigationController?.navigationBar.prefersLargeTitles) ?? false
let offset: CGFloat = (largeTitles && !expandedBar) ? 52: 0
scrollView.setContentOffset(CGPoint(x: 0, y: -(scrollView.adjustedContentInset.top + offset)), animated: animated)
} else {
scrollView.setContentOffset(CGPoint(x: 0, y: -scrollView.contentInset.top), animated: animated)
}
}
Inspiriert von Jakubs Lösung
Scrolle nach oben für UITableViewController
, UICollectionViewController
oder ein beliebiges UIViewController
mit UIScrollView
extension UIViewController {
func scrollToTop(animated: Bool) {
if let tv = self as? UITableViewController {
tv.tableView.setContentOffset(CGPoint.zero, animated: animated)
} else if let cv = self as? UICollectionViewController{
cv.collectionView?.setContentOffset(CGPoint.zero, animated: animated)
} else {
for v in view.subviews {
if let sv = v as? UIScrollView {
sv.setContentOffset(CGPoint.zero, animated: animated)
}
}
}
}
}
Es kommt sehr häufig vor, dass Ihre Navigationsleiste den kleinen Teil des scrollView-Inhalts überlappt und der Inhalt nicht von oben beginnt. Um das Problem zu beheben, habe ich zwei Dinge getan: