Comment faire défiler un UIScrollView vers le haut?
Comment faire défiler un UIScrollView vers le haut?
Réponses:
[self.scrollView setContentOffset:
CGPointMake(0, -self.scrollView.contentInset.top) animated:YES];
[self.scrollView setContentOffset:CGPointZero animated:YES];
ou si vous souhaitez conserver la position de défilement horizontal et simplement réinitialiser la position verticale:
[self.scrollView setContentOffset:CGPointMake(self.scrollView.contentOffset.x, 0)
animated:YES];
[scrollView setContentOffset:CGPointMake(0, -scrollView.contentInset.top) animated:YES];
Cela fonctionne sous iOS 6 & 7
[scrollView setContentOffset:CGPointMake(0, scrollView.contentSize.height-scrollView.frame.size.height) animated:YES];
Voici une extension Swift qui facilite les choses:
extension UIScrollView {
func scrollToTop() {
let desiredOffset = CGPoint(x: 0, y: -contentInset.top)
setContentOffset(desiredOffset, animated: true)
}
}
Usage:
myScrollView.scrollToTop()
essayez de travailler avec le nouveau adjustedContentInset
.
Par exemple (faites défiler vers le haut):
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)
Même si vous utilisez
prefersLargeTitles
,safe area
etc.
Pour Swift 4
scrollView.setContentOffset(.zero, animated: true)
Utilisation setContentOffset:animated:
[scrollView setContentOffset:CGPointZero animated:YES];
Dans iOS7, j'ai eu du mal à obtenir une vue de défilement particulière pour aller en haut, ce qui fonctionnait dans iOS6, et je l'ai utilisée pour définir la vue de défilement pour aller en haut.
[self.myScroller scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:NO];
Version Swift 3.0.1 de la réponse de Rob Mayoff :
self.scrollView.setContentOffset(
CGPoint(x: 0,y: -self.scrollView.contentInset.top),
animated: true)
Pour répliquer complètement le comportement scrollToTop de la barre d'état, nous devons non seulement définir le contentOffset, mais également nous assurer que les scrollIndicators sont affichés. Sinon, l'utilisateur peut se perdre rapidement.
La seule méthode publique pour y parvenir est flashScrollIndicators
. Malheureusement, l'appeler une fois après avoir défini contentOffset n'a aucun effet car il est réinitialisé immédiatement. J'ai trouvé que cela fonctionnait lorsque je faisais le flash à chaque fois 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;
});
}
Dans votre UIScrollViewDelegate (ou UITable / UICollectionViewDelegate) implémentez ceci:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if (scrollView.tag == SCROLLVIEW_IS_SCROLLING_TO_TOP_TAG) {
[scrollView flashScrollIndicators];
}
}
Le délai de masquage est un peu plus court par rapport au comportement scrollToTop de la barre d'état, mais il a toujours l'air agréable.
Notez que j'abuse de la balise de vue pour communiquer l'état "isScrollingToTop" parce que j'en ai besoin à travers les contrôleurs de vue. Si vous utilisez des balises pour autre chose, vous voudrez peut-être les remplacer par une iVar ou une propriété.
Je pense avoir une réponse qui devrait être entièrement compatible avec iOS 11 ainsi que les versions antérieures (pour le défilement vertical)
Cela prend en compte le nouvel ajustéContentInset et tient également compte du décalage supplémentaire requis lorsque prefersLargeTitles est activé sur la barre de navigation, ce qui semble nécessiter un décalage supplémentaire de 52px en plus de la valeur par défaut.
C'était un peu délicat car l'ajustéContentInset change en fonction de l'état de titleBar (grand titre vs petit titre), je devais donc vérifier et voir quelle était la hauteur de titleBar et ne pas appliquer le décalage de 52px s'il était déjà dans le grand état. Impossible de trouver une autre méthode pour vérifier l'état de la barre de navigation, donc si quelqu'un a une meilleure option que de voir si la hauteur est> 44,0, j'aimerais l'entendre
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)
}
}
Inspiré de la solution de Jakub
Il est très courant que votre barre de navigation chevauche la petite partie du contenu scrollView et qu'il semble que le contenu ne commence pas par le haut. Pour le réparer, j'ai fait 2 choses:
Défilement vers le haut pour UITableViewController
, UICollectionViewController
ou tout UIViewController
ayantUIScrollView
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)
}
}
}
}
}
Dans SWIFT 5, réglez simplement le décalage de contenu à zéro
scrollView.setContentOffset(CGPoint.zero, animated: true)
J'ai essayé toutes les manières. Mais rien n'a fonctionné pour moi. Finalement, j'ai aimé ça.
J'ai ajouté une self.view .addSubview(self.scroll)
ligne de code dans le viewDidLoad. Après avoir commencé à configurer le cadre pour la vue de défilement et ajouté des composants pour la vue de défilement.
Cela a fonctionné pour moi.
Assurez-vous d'avoir ajouté une self.view .addSubview(self.scroll)
ligne au début. alors vous pouvez ajouter des éléments d'interface utilisateur.
UIScrollView
contentInset
, malheureusement.[self.scrollView setContentOffset:CGPointMake(self.scrollView.contentOffset.x, -self.scrollView.contentInset.top) animated:YES];
fait le travail pour moi