Obtener UIScrollView para desplazarse a la parte superior


¿Cómo puedo hacer que UIScrollView se desplace hacia arriba?

Author: Ortwin Gentz, 2012-02-26

13 answers

ACTUALIZACIÓN PARA iOS 7

[self.scrollView setContentOffset:
    CGPointMake(0, -self.scrollView.contentInset.top) animated:YES];

ORIGINAL

[self.scrollView setContentOffset:CGPointZero animated:YES];

O si desea conservar la posición de desplazamiento horizontal y simplemente restablecer la posición vertical:

[self.scrollView setContentOffset:CGPointMake(self.scrollView.contentOffset.x, 0)
    animated:YES];
 292
Author: rob mayoff,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-08 21:23:22

Aquí hay una extensión Rápida que lo hace fácil:

extension UIScrollView {
    func scrollToTop() {
        let desiredOffset = CGPoint(x: 0, y: -contentInset.top)
        setContentOffset(desiredOffset, animated: true)
   }
}

Uso:

myScrollView.scrollToTop()
 44
Author: Andrew Schreiber,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-14 16:29:24

Use setContentOffset:animated:

[scrollView setContentOffset:CGPointZero animated:YES];
 22
Author: Bryan Chen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-08-27 06:43:22

IOS 11 y superiores

Intenta trabajar con el nuevo adjustedContentInset.

Por ejemplo (desplácese hasta la parte superior):

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)

Incluso si usa prefersLargeTitles, safe area etc.

 19
Author: Jakub Truhlář,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-17 13:32:12

Respuesta para Swift 2.0/3.0/4.0 y iOS 7+:

let desiredOffset = CGPoint(x: 0, y: -self.scrollView.contentInset.top)
self.scrollView.setContentOffset(desiredOffset, animated: true)
 15
Author: worthbak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-31 16:16:17

Para Swift 4

ScrollView.setContentOffset(.cero, animado: verdadero)

 12
Author: Rajasekhar Pasupuleti,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-12 10:55:41

En iOS7 tuve problemas para conseguir que un scrollview en particular fuera a la parte superior, lo que funcionó en iOS6, y lo usé para establecer que el scrollview fuera a la parte superior.

[self.myScroller scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:NO];
 8
Author: hoak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-31 16:08:35

Swift 3.0.1 versión de respuesta de rob mayoff :

self.scrollView.setContentOffset(
CGPoint(x: 0,y: -self.scrollView.contentInset.top),
animated: true)
 4
Author: Roni Leshes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 10:31:28

Para replicar completamente el comportamiento de scrollToTop de la barra de estado no solo tenemos que establecer el contentOffset sino que también queremos asegurarnos de que se muestren los scrollIndicators. De lo contrario, el usuario puede perderse rápidamente.

El único método público para lograr esto es flashScrollIndicators. Desafortunadamente, llamarlo una vez después de configurar el contentOffset no tiene efecto porque se restablece inmediatamente. Encontré que funciona al hacer el flash cada vez en 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;
    });
}

En su UIScrollViewDelegate (o UITable/UICollectionViewDelegate) implementar esto:

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    if (scrollView.tag == SCROLLVIEW_IS_SCROLLING_TO_TOP_TAG) {
        [scrollView flashScrollIndicators];
    }
}

El retraso de ocultar es un poco más corto en comparación con el comportamiento de scrollToTop de la barra de estado, pero todavía se ve bien.

Tenga en cuenta que estoy abusando de la etiqueta de vista para comunicar el estado "isScrollingToTop" porque lo necesito entre los controladores de vista. Si está utilizando etiquetas para otra cosa, es posible que desee reemplazar esto con un iVar o una propiedad.

 2
Author: Ortwin Gentz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-20 18:36:23

Desplácese hacia arriba para UITableViewController, UICollectionViewController o cualquier UIViewController que tenga 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)
            }
        }
    }
  }
}
 1
Author: Shoaib,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-06 12:03:54

Creo que tengo una respuesta que debería ser totalmente compatible con iOS 11, así como las versiones anteriores (para el desplazamiento vertical)

Esto tiene en cuenta el nuevo adjustedContentInset y también tiene en cuenta el desplazamiento adicional requerido cuando prefersLargeTitles está habilitado en la barra de navegación que parece requerir un desplazamiento adicional de 52px en la parte superior de lo que]}

Esto fue un poco complicado porque el adjustedContentInset cambia dependiendo de la Estado de la barra de título (título grande vs título pequeño) así que necesitaba comprobar y ver cuál era la altura de la barra de título y no aplicar el desplazamiento de 52px si ya estaba en el estado grande. No pude encontrar ningún otro método para verificar el estado de la barra de navegación, así que si alguien tiene una mejor opción que ver si la altura es > 44.0 Me gustaría escucharlo

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 en la solución de Jakub

 0
Author: user2898617,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-08 15:40:04

Es muy común cuando su barra de navegación se superpone la pequeña porción del contenido de ScrollView y parece que el contenido no comienza desde la parte superior. Para arreglarlo hice 2 cosas:

  • Inspector de tamaño - Vista de desplazamiento - Inserciones de contenido Change> Cambiar de Automático a Nunca.
  • Size Inspector - Constraints- "Align Top to" (Top Alignment Constraints)- Second item {> Change from Superview.Arriba al Área Segura.Top y el valor (campo constante) establecido en 0

Inserciones de contenido-Nunca Alinee ScrolView.Arriba al Área Segura.Superior

 0
Author: Vitya Shurapov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-25 11:05:17

Probé todas las formas. Pero nada funcionó para mí. Finalmente me gustó esto.

Agregué self.view .addSubview(self.scroll) una línea de código en viewDidLoad. Después de comenzar a configurar el marco para la vista de desplazamiento y agregar componentes a la vista de desplazamiento.

Funcionó para mí.

Asegúrese de haber agregado la línea self.view .addSubview(self.scroll) al principio. luego puede agregar elementos de interfaz de usuario.

 -4
Author: Narasimha Nallamsetty,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-11 08:03:30