Como faço uma rolagem do UIScrollView para o topo?
Como faço uma rolagem do UIScrollView para o topo?
Respostas:
[self.scrollView setContentOffset:
CGPointMake(0, -self.scrollView.contentInset.top) animated:YES];
[self.scrollView setContentOffset:CGPointZero animated:YES];
ou se você deseja preservar a posição de rolagem horizontal e redefinir a posição vertical:
[self.scrollView setContentOffset:CGPointMake(self.scrollView.contentOffset.x, 0)
animated:YES];
[scrollView setContentOffset:CGPointMake(0, -scrollView.contentInset.top) animated:YES];
Funciona no iOS 6 e 7
[scrollView setContentOffset:CGPointMake(0, scrollView.contentSize.height-scrollView.frame.size.height) animated:YES];
Aqui está uma extensão Swift que facilita:
extension UIScrollView {
func scrollToTop() {
let desiredOffset = CGPoint(x: 0, y: -contentInset.top)
setContentOffset(desiredOffset, animated: true)
}
}
Uso:
myScrollView.scrollToTop()
tente trabalhar com o novo adjustedContentInset
.
Por exemplo (role para o topo):
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)
Mesmo se você usar
prefersLargeTitles
,safe area
etc.
Para Swift 4
scrollView.setContentOffset(.zero, animated: true)
Usar setContentOffset:animated:
[scrollView setContentOffset:CGPointZero animated:YES];
No iOS7, tive problemas para obter uma visualização de rolagem específica para ir ao topo, que funcionava no iOS6, e usei isso para definir a visualização de rolagem para o topo.
[self.myScroller scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:NO];
Versão Swift 3.0.1 da resposta de rob mayoff :
self.scrollView.setContentOffset(
CGPoint(x: 0,y: -self.scrollView.contentInset.top),
animated: true)
Para replicar completamente o comportamento scrollToTop da barra de status, não apenas precisamos definir o contentOffset, mas também queremos garantir que os scrollIndicators sejam exibidos. Caso contrário, o usuário poderá se perder rapidamente.
O único método público para fazer isso é flashScrollIndicators
. Infelizmente, chamá-lo uma vez após definir o contentOffset não tem efeito porque é redefinido imediatamente. Descobri que funciona sempre que o flash é disparado 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;
});
}
No seu UIScrollViewDelegate (ou UITable / UICollectionViewDelegate) implemente isto:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if (scrollView.tag == SCROLLVIEW_IS_SCROLLING_TO_TOP_TAG) {
[scrollView flashScrollIndicators];
}
}
O atraso da ocultação é um pouco menor em comparação com o comportamento scrollToTop da barra de status, mas ainda parece bom.
Observe que estou abusando da tag view para comunicar o estado "isScrollingToTop" porque preciso disso nos controladores de exibição. Se você estiver usando tags para outra coisa, poderá substituí-lo por um iVar ou uma propriedade.
Acho que tenho uma resposta que deve ser totalmente compatível com o iOS 11 e com versões anteriores (para rolagem vertical)
Isso leva em consideração o novo ajustadoContentInset e também considera o deslocamento adicional necessário quando prefereLargeTitles está ativado na navegação, que parece exigir um deslocamento adicional de 52px sobre o valor padrão.
Isso foi um pouco complicado, pois o ajustadoContentInset muda dependendo do estado titleBar (título grande vs título pequeno), então eu precisei verificar e ver qual era a altura do titleBar e não aplicar o deslocamento de 52px se ele já estiver no estado grande. Não foi possível encontrar outro método para verificar o estado da barra de navegação. Se alguém tiver uma opção melhor do que ver se a altura é> 44,0, eu gostaria de ouvi-la
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)
}
}
Inspirado na solução de Jakub
É muito comum quando a barra de navegação se sobrepõe à pequena parte do conteúdo do scrollView e parece que o conteúdo não começa da parte superior. Para corrigi-lo, fiz duas coisas:
Vá até o topo para UITableViewController
, UICollectionViewController
ou qualquer UIViewController
terUIScrollView
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)
}
}
}
}
}
No SWIFT 5, defina o deslocamento do conteúdo como zero.
scrollView.setContentOffset(CGPoint.zero, animated: true)
Eu tentei de todas as maneiras. Mas nada funcionou para mim. Finalmente eu fiz assim.
Eu adicionei self.view .addSubview(self.scroll)
linha de código no viewDidLoad. Após iniciar a configuração do quadro para a visualização de rolagem e adicionar componentes à visualização de rolagem.
Funcionou para mim.
Certifique-se de adicionar uma self.view .addSubview(self.scroll)
linha no começo. então você pode adicionar elementos da interface do usuário.
UIScrollView
contentInset
, infelizmente.[self.scrollView setContentOffset:CGPointMake(self.scrollView.contentOffset.x, -self.scrollView.contentInset.top) animated:YES];
faz o trabalho para mim