Comment puis-je faire un UIScrollView
faire défiler vers le bas dans mon code? Ou d'une manière plus générique, à n'importe quel point d'une sous-vue?
Vous pouvez utiliser la fonction setContentOffset:animated:
de UIScrollView pour accéder à n’importe quelle partie de la vue Contenu. Voici un code qui défilerait vers le bas, en supposant que votre scrollView est self.scrollView
:
CGPoint bottomOffset = CGPointMake(0, self.scrollView.contentSize.height - self.scrollView.bounds.size.height + self.scrollView.contentInset.bottom);
[self.scrollView setContentOffset:bottomOffset animated:YES];
J'espère que cela pourra aider!
Version rapide de la réponse acceptée pour un collage facile:
let bottomOffset = CGPoint(x: 0, y: scrollView.contentSize.height - scrollView.bounds.size.height)
scrollView.setContentOffset(bottomOffset, animated: true)
La solution la plus simple:
[scrollview scrollRectToVisible:CGRectMake(scrollview.contentSize.width - 1,scrollview.contentSize.height - 1, 1, 1) animated:YES];
Juste une amélioration de la réponse existante.
CGPoint bottomOffset = CGPointMake(0, self.scrollView.contentSize.height - self.scrollView.bounds.size.height + self.scrollView.contentInset.bottom);
[self.scrollView setContentOffset:bottomOffset animated:YES];
Il s’occupe également de l’encart du bas (si vous l’utilisez pour ajuster votre vue de défilement lorsque le clavier est visible)
Régler le contenu du contenu à la hauteur de la taille du contenu est incorrect: cela fait défiler le bas du contenu jusqu'au top de la vue de défilement, et donc hors de vue.
La solution correcte consiste à faire défiler le bas du contenu jusqu'au bottom de la vue de défilement, comme ceci (sv
est le UIScrollView):
CGSize csz = sv.contentSize;
CGSize bsz = sv.bounds.size;
if (sv.contentOffset.y + bsz.height > csz.height) {
[sv setContentOffset:CGPointMake(sv.contentOffset.x,
csz.height - bsz.height)
animated:YES];
}
Une solution Swift 2.2, en tenant compte de contentInset
let bottomOffset = CGPoint(x: 0, y: scrollView.contentSize.height - scrollView.bounds.size.height + scrollView.contentInset.bottom)
scrollView.setContentOffset(bottomOffset, animated: true)
Cela devrait être dans une extension
extension UIScrollView {
func scrollToBottom() {
let bottomOffset = CGPoint(x: 0, y: contentSize.height - bounds.size.height + contentInset.bottom)
setContentOffset(bottomOffset, animated: true)
}
}
Notez que vous voudrez peut-être vérifier si bottomOffset.y > 0
avant de faire défiler
Faites défiler vers le haut
- CGPoint topOffset = CGPointMake(0, 0);
- [scrollView setContentOffset:topOffset animated:YES];
Défiler vers le bas
- CGPoint bottomOffset = CGPointMake(0, scrollView.contentSize.height - self.scrollView.bounds.size.height);
- [scrollView setContentOffset:bottomOffset animated:YES];
Une implémentation rapide:
extension UIScrollView {
func scrollToBottom(animated: Bool) {
if self.contentSize.height < self.bounds.size.height { return }
let bottomOffset = CGPoint(x: 0, y: self.contentSize.height - self.bounds.size.height)
self.setContentOffset(bottomOffset, animated: animated)
}
}
Vous appelez l'extension comme ceci:
yourScrollview.scrollToBottom(animated: true)
Et si contentSize
est inférieur à bounds
?
Pour Swift c'est:
scrollView.setContentOffset(CGPointMake(0, max(scrollView.contentSize.height - scrollView.bounds.size.height, 0) ), animated: true)
J'ai également trouvé un autre moyen utile de le faire dans le cas où vous utilisez une UITableview (qui est une sous-classe de UIScrollView):
[(UITableView *)self.view scrollToRowAtIndexPath:scrollIndexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
Utilisez la fonction setContentOffset:animated:
de UIScrollView pour faire défiler l'écran vers le bas dans Swift.
let bottomOffset : CGPoint = CGPointMake(0, scrollView.contentSize.height - scrollView.bounds.size.height + scrollView.contentInset.bottom)
scrollView.setContentOffset(bottomOffset, animated: true)
Avec footerView (facultatif) et contentInset, la solution est la suivante:
CGPoint bottomOffset = CGPointMake(0, _tableView.contentSize.height - tableView.frame.size.height + _tableView.contentInset.bottom);
if (bottomOffset.y > 0) [_tableView setContentOffset: bottomOffset animated: YES];
valdyr, espérons que cela vous aidera:
CGPoint bottomOffset = CGPointMake(0, [textView contentSize].height - textView.frame.size.height);
if (bottomOffset.y > 0)
[textView setContentOffset: bottomOffset animated: YES];
Catégorie à la rescousse!
Ajoutez ceci à un en-tête d'utilitaire partagé quelque part:
@interface UIScrollView (ScrollToBottom)
- (void)scrollToBottomAnimated:(BOOL)animated;
@end
Et puis à cette implémentation utilitaire:
@implementation UIScrollView(ScrollToBottom)
- (void)scrollToBottomAnimated:(BOOL)animated
{
CGPoint bottomOffset = CGPointMake(0, self.contentSize.height - self.bounds.size.height);
[self setContentOffset:bottomOffset animated:animated];
}
@end
Puis implémentez-le où vous voulez, par exemple:
[[myWebView scrollView] scrollToBottomAnimated:YES];
Si vous n'avez pas besoin d'animation, cela fonctionne:
[self.scrollView setContentOffset:CGPointMake(0, CGFLOAT_MAX) animated:NO];
Bien que la solution Matt
me semble correcte, vous devez également prendre en compte l’encadré de la vue Collection, s’il en existe une qui a été configurée.
Le code adapté sera:
CGSize csz = sv.contentSize;
CGSize bsz = sv.bounds.size;
NSInteger bottomInset = sv.contentInset.bottom;
if (sv.contentOffset.y + bsz.height + bottomInset > csz.height) {
[sv setContentOffset:CGPointMake(sv.contentOffset.x,
csz.height - bsz.height + bottomInset)
animated:YES];
}
Pour vous assurer que le fond de votre contenu est visible, utilisez la formule suivante:
contentOffsetY = MIN(0, contentHeight - boundsHeight)
Cela garantit que le bord inférieur de votre contenu est toujours égal ou supérieur au bord inférieur de la vue. MIN(0, ...)
est requis car UITableView
(et probablement UIScrollView
) garantit contentOffsetY >= 0
lorsque l'utilisateur essaie de faire défiler visuellement contentOffsetY = 0
. Cela semble assez étrange pour l'utilisateur.
Le code pour implémenter ceci est:
UIScrollView scrollView = ...;
CGSize contentSize = scrollView.contentSize;
CGSize boundsSize = scrollView.bounds.size;
if (contentSize.height > boundsSize.height)
{
CGPoint contentOffset = scrollView.contentOffset;
contentOffset.y = contentSize.height - boundsSize.height;
[scrollView setContentOffset:contentOffset animated:YES];
}
Solution pour faire défiler jusqu'au dernier élément d'un tableau
Swift 3:
if self.items.count > 0 {
self.tableView.scrollToRow(at: IndexPath.init(row: self.items.count - 1, section: 0), at: UITableViewScrollPosition.bottom, animated: true)
}
J'ai trouvé que contentSize
ne correspond pas vraiment à la taille réelle du texte. Par conséquent, lorsque vous essayez de faire défiler l'écran jusqu'en bas, le texte sera un peu désactivé Le meilleur moyen de déterminer la taille réelle du contenu consiste à utiliser la méthode NSLayoutManager
's usedRectForTextContainer:
:
UITextView *textView;
CGSize textSize = [textView.layoutManager usedRectForTextContainer:textView.textContainer].size;
Pour déterminer la quantité de texte réellement affichée dans la UITextView
, vous pouvez le calculer en soustrayant les encarts du conteneur de texte de la hauteur du cadre.
UITextView *textView;
UIEdgeInsets textInsets = textView.textContainerInset;
CGFloat textViewHeight = textView.frame.size.height - textInsets.top - textInsets.bottom;
Ensuite, il devient facile de faire défiler:
// if you want scroll animation, use contentOffset
UITextView *textView;
textView.contentOffset = CGPointMake(textView.contentOffset.x, textSize - textViewHeight);
// if you don't want scroll animation
CGRect scrollBounds = textView.bounds;
scrollBounds.Origin = CGPointMake(textView.contentOffset.x, textSize - textViewHeight);
textView.bounds = scrollBounds;
Quelques chiffres à titre de référence sur ce que les différentes tailles représentent pour un UITextView
vide.
textView.frame.size = (width=246, height=50)
textSize = (width=10, height=16.701999999999998)
textView.contentSize = (width=246, height=33)
textView.textContainerInset = (top=8, left=0, bottom=8, right=0)
CGFloat yOffset = scrollView.contentOffset.y;
CGFloat height = scrollView.frame.size.height;
CGFloat contentHeight = scrollView.contentSize.height;
CGFloat distance = (contentHeight - height) - yOffset;
if(distance < 0)
{
return ;
}
CGPoint offset = scrollView.contentOffset;
offset.y += distance;
[scrollView setContentOffset:offset animated:YES];
Xamarin.iOS version de la réponse acceptée
var bottomOffset = new CGPoint (0,
scrollView.ContentSize.Height - scrollView.Frame.Size.Height
+ scrollView.ContentInset.Bottom);
scrollView.SetContentOffset (bottomOffset, false);
Il semble que toutes les réponses ne tiennent pas compte de la zone de sécurité. Depuis iOS 11, l'iPhone X dispose d'une zone de sécurité introduite. Cela peut affecter le contentInset
du scrollView.
Pour iOS 11 et les versions ultérieures, faites défiler correctement jusqu'au bas avec l'encadré de contenu inclus. Vous devez utiliser adjustedContentInset
au lieu de contentInset
. Vérifiez ce code:
let bottomOffset = CGPoint(x: 0, y: scrollView.contentSize.height - scrollView.bounds.height + scrollView.adjustedContentInset.bottom)
scrollView.setContentOffset(bottomOffset, animated: true)
CGPoint bottomOffset = CGPointMake(0, self.scrollView.contentSize.height - self.scrollView.bounds.size.height + self.scrollView.adjustedContentInset.bottom);
[self.scrollView setContentOffset:bottomOffset animated:YES];
contentOffset.x
):extension UIScrollView {
func scrollsToBottom(animated: Bool) {
let bottomOffset = CGPoint(x: contentOffset.x,
y: contentSize.height - bounds.height + adjustedContentInset.bottom)
setContentOffset(bottomOffset, animated: animated)
}
}
Références:
Xamarin.iOS version pour UICollectionView
de la réponse acceptée pour faciliter le copier-coller
var bottomOffset = new CGPoint (0, CollectionView.ContentSize.Height - CollectionView.Frame.Size.Height + CollectionView.ContentInset.Bottom);
CollectionView.SetContentOffset (bottomOffset, false);
Cela n'a pas fonctionné pour moi lorsque j'ai essayé de l'utiliser dans UITableViewController
sur self.tableView
(iOS 4.1)
, après avoir ajouté footerView
. Il fait défiler les frontières, montrant un écran noir.
Solution alternative:
CGFloat height = self.tableView.contentSize.height;
[self.tableView setTableFooterView: myFooterView];
[self.tableView reloadData];
CGFloat delta = self.tableView.contentSize.height - height;
CGPoint offset = [self.tableView contentOffset];
offset.y += delta;
[self.tableView setContentOffset: offset animated: YES];
Pour ScrollView Horizontal
Si vous aimez moi qui a une vue de défilement horizontale et que vous souhaitez faire défiler l'écran jusqu'à la fin (dans mon cas, le plus à droite), vous devez modifier certaines parties de la réponse acceptée:
Objective-C
CGPoint rightOffset = CGPointMake(self.scrollView.contentSize.width - self.scrollView.bounds.size.width + self.scrollView.contentInset.right, 0 );
[self.scrollView setContentOffset:rightOffset animated:YES];
rapide
let rightOffset: CGPoint = CGPoint(x: self.scrollView.contentSize.width - self.scrollView.bounds.size.width + self.scrollView.contentInset.right, y: 0)
self.scrollView.setContentOffset(rightOffset, animated: true)
En rapide:
if self.mainScroll.contentSize.height > self.mainScroll.bounds.size.height {
let bottomOffset = CGPointMake(0, self.mainScroll.contentSize.height - self.mainScroll.bounds.size.height);
self.mainScroll.setContentOffset(bottomOffset, animated: true)
}