¿Cómo deshabilitar el desplazamiento horizontal de UIScrollView?

92

Tengo un UIViewtrampolín como el del iPhone. Lo he creado usando un UIScrollViewy UIButtons. Quiero deshabilitar el desplazamiento horizontal en dicha vista de desplazamiento. Solo quiero desplazamiento vertical. ¿Cómo logro esto?

Rahul Vyas
fuente
5
Deberías cambiar tu título: pides horizontal en la pregunta y vertical en el título. La gente encuentra tus preguntas más tarde en los motores de búsqueda, por lo que sigue siendo importante 2 años después :)
Julien
@RahulVyas El hombre de arriba tiene razón. Cambiar el título disminuirá cualquier confusión para los principiantes que llegan aquí a través de un motor de búsqueda (como yo;)).
SpacyRicochet
Haber editado el título en nombre del cartel. (Aunque actualmente está esperando la revisión por pares antes de que la edición sea visible).
Duncan Babbage

Respuestas:

125

Tienes que establecer la contentSizepropiedad del UIScrollView. Por ejemplo, si UIScrollViewtiene 320 píxeles de ancho (el ancho de la pantalla), puede hacer esto:

CGSize scrollableSize = CGSizeMake(320, myScrollableHeight);
[myScrollView setContentSize:scrollableSize];

La UIScrollViewcontinuación, sólo desplazarse verticalmente, debido a que ya puede mostrar todo horizontalmente.

Dave DeLong
fuente
6
Hola. ¡Esta solución funciona muy bien! Gracias por eso. Intenté establecer el ancho estático en 0. Para mí, esto también funciona. No sé si podría haber algunos efectos secundarios más adelante. Pero si uno no conoce el tamaño (es decir, el código universal para iPhone y iPad), ¡esto funciona muy bien!
JackPearse
5
Creo que es mejor hacer CGSizeMake (0, myScrollableHeight), por lo que el desplazamiento horizontal está desactivado incluso si no se muestran todas las subvistas.
LightNight
Nota: si se configura una de las dimensiones en 0 cuando se usa la paginación, VoiceOver anunciará el número de página como "página 1 de 1" independientemente del valor correcto
josef
1
En lugar de pasar el ancho como 320 codificado, podemos pasar como: CGSize scrollableSize = CGSizeMake (self.scrollview.frame.size.width, myScrollableHeight); [myScrollView setContentSize: scrollableSize];
Mohit kumar
90

ACTUALIZADO: (Después de que @EranMarom señaló en su comentario)

Puede detener el desplazamiento horizontal o vertical en el ScrollViewDelegateMétodo. Aquí es como

Detiene el desplazamiento horizontal:

Si desea desplazarse horizontalmente, debe aumentar el contentOffset.x. Evitar eso detiene el desplazamiento de la vista de desplazamiento en dirección horizontal.

- (void)scrollViewDidScroll:(UIScrollView *)sender {
    sender.contentOffset.x = 0.0
}

Detiene el desplazamiento vertical:

Si desea desplazarse verticalmente, debe aumentar el contentOffset.y. Evitar eso detiene el desplazamiento de la vista de desplazamiento en dirección vertical.

- (void)scrollViewDidScroll:(UIScrollView *)sender {
    sender.contentOffset.y = 0.0
}

El código anterior evita los cambios en xy yde a scrollview contentOffsety conduce a detener el scrollViewDidScroll:método de desplazamiento .

Dinesh Raja
fuente
1
Estoy considerando votar a la baja porque esta respuesta no explica en sí misma, acaba de dar el código y eso es todo. Respuestas así no son muy buenas. La buena respuesta se explica a sí mismos, mientras que los desarrolladores experimentados pueden entender que los desarrolladores más nuevos pueden no entender lo que está sucediendo aquí. Aún no se ha votado en contra por dar la oportunidad de mejorar.
Popeye
13
Esto es una especie de truco, pero funcionó cuando todo lo demás fallaba. Entonces +1, pero utilícelo solo como último recurso.
i_am_jorf
5
También utilizo este método de delegado, pero reemplazo el cuerpo con una línea, por ejemplo: scrollView.contentOffset = CGPointMake(0, scrollView.contentOffset.y);para deshabilitar el desplazamiento horizontal. Lo encuentro más legible, es más pequeño y no tiene sentido hacer la prueba para cero porque prácticamente no hay sobrecarga con el código que se ejecuta con esta poca frecuencia (es decir, unas pocas decenas de veces por segundo como máximo).
Echelon
porque estás cambiando el contentOffset después de "didscroll", no como antes de 'willscroll', y esta es una solución de martillo, pero yo no voté negativamente, porque 18 votos a favor y la respuesta es 75, por lo que no es digno de votar en contra
LolaRun
2
Aún más fácil, utilícelo scrollView.contentOffset.y = 0.0para detener el desplazamiento vertical y scrollView.contentOffset.x = 0.0para detener el desplazamiento horizontal, en la scrollViewDidScroll()función de delegado. Sin embargo, creo que asegurarse de que sea scrollView.contentSizeigual a scrollView.frame.sizees una solución mejor (correcta). Vea la respuesta de @danbeaulieu.
emem
11

desde el uso de iOS7

self.automaticallyAdjustsScrollViewInsets = NO;

// y crea tu desplazamiento de página con 3 páginas

    self.pageView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
    [self.pageView setContentSize:CGSizeMake(self.view.frame.size.width*3, self.view.frame.size.height)];
    [self.pageView setShowsVerticalScrollIndicator:NO];
    [self.pageView setPagingEnabled:YES];
    [self.view addSubview:self.pageView];
Mirko Brunner
fuente
No creo que esto deshabilite el comportamiento de desplazamiento de una vista de desplazamiento. ¿¿Lo es??
Dinesh Raja
self.collectionView.pagingEnabled = YES;me ayudó a resolver el problema con el desplazamiento suave (sin arrastrar). El problema estaba en el método scrollViewWillEndDragging:: targetContentOffset era el mismo que scrollView.contentOffset y la lógica de detección de página no funciona correctamente.
sig
11

Solución rápida

Cree dos salidas, una para su vista y otra para su vista de desplazamiento:

@IBOutlet weak var myView: UIView!
@IBOutlet weak var scrollView: UIScrollView!

Luego, en su viewDidLayoutSubviews puede agregar el siguiente código:

let scrollSize = CGSize(width: myView.frame.size.width, 
                        height: myView.frame.size.height)
scrollView.contentSize = scrollSize

Lo que hemos hecho es recopilar la altura y el ancho de la vista y configurar el tamaño del contenido de scrollViews para que coincida. Esto evitará que la vista de desplazamiento se desplace horizontalmente.


Más pensamientos:

CGSizeMake toma un ancho y un alto usando CGFloats. Es posible que deba usar la altura existente de UIScrollViews para el segundo parámetro. Que se vería así:

let scrollSize = CGSize(width: myView.frame.size.width, 
                        height: scrollView.contentSize.height)
Dan Beaulieu
fuente
¿Qué pasa si no conoce la altura o el ancho (dispositivo universal)? @danbeaulieu
Lukesivi
@lukesIvi "myView.frame.width" está sacando dinámicamente el ancho de la IBOutlet "myView".
Dan Beaulieu
4

En mi caso, con Swift 4.2 puedes usar:

Deshabilitar el desplazamiento vertical:

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    scrollView.contentOffset.y = 0.0
}

Deshabilitar el desplazamiento horizontal:

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    scrollView.contentOffset.x = 0.0
}
Ricardo
fuente
3

Puede seleccionar la vista y luego Attributes Inspectordesmarcar User Interaction Enabled.

Codificador221
fuente
3

En mi caso, el ancho de contentView era mayor que el ancho de UIScrollView y esa fue la razón del desplazamiento horizontal no deseado. Lo resolví estableciendo el ancho de contentView igual al ancho de UIScrollView.

Espero que ayude a alguien

Gulfam Khan
fuente
@Nostradamus feliz de ayudar
Gulfam Khan
0

Tenía el tableview contentInset establecido en viewDidLoad (como se muestra a continuación) que es lo que causa el desplazamiento horizontal

self.tableView.contentInset = UIEdgeInsetsMake(0, 30, 0, 0);

Compruebe si hay algún contenido de vista de tabla establecido por diferentes razones y desactívelo

Naishta
fuente
0

Luché con esto durante algún tiempo intentando sin éxito las diversas sugerencias en este y otros hilos.

Sin embargo, en otro hilo (no estoy seguro de dónde) alguien sugirió que usar una restricción negativa en el UIScrollView funcionó para él.

Entonces probé varias combinaciones de restricciones con resultados inconsistentes. Lo que finalmente funcionó para mí fue agregar restricciones iniciales y finales de -32 a la vista de desplazamiento y agregar una vista de texto (invisible) con un ancho de 320 (y centrada).

PatriciaW
fuente
0

Prueba esto:

CGSize scrollSize = CGSizeMake([UIScreen mainScreen].bounds.size.width, scrollHeight);
[scrollView setContentSize: scrollSize];
Torongo
fuente
0

Deshabilite el desplazamiento horizontal anulando la contentOffsetpropiedad en la subclase.

override var contentOffset: CGPoint {
  get {
    return super.contentOffset
  }
  set {
    super.contentOffset = CGPoint(x: 0, y: newValue.y)
  }
}
iWheelBuy
fuente
0

Introducida en iOS 11 es una nueva propiedad en UIScrollView

var contentLayoutGuide: UILayoutGuide

La documentación indica que usted:

Utilice esta guía de diseño cuando desee crear restricciones de diseño automático relacionadas con el área de contenido de una vista de desplazamiento.

Junto con cualquier otra limitación de diseño automático que usted podría estar agregando que se desea limitar la widthAnchorde los UIScrollView's contentLayoutGuideque ser del mismo tamaño que el 'marco'. Puede usar el frameLayoutGuide(también introducido en iOS 11) o cualquier ancho externo (como susuperView ).

ejemplo:

NSLayoutConstraint.activate([
  scrollView.contentLayoutGuide.widthAnchor.constraint(equalTo: self.widthAnchor)
])

Documentación: https://developer.apple.com/documentation/uikit/uiscrollview/2865870-contentlayoutguide

JMFR
fuente
-1

Una vez que lo hice reemplazando el UIScrollView con un UITableView con solo 1 celda, funcionó bien.

Hola Soy Edu Feliz Navidad
fuente
1
Lo siento, esto no responde a la pregunta.
David
-1

Utilice esta única línea.

self.automaticallyAdjustsScrollViewInsets = NO;

Karthickkck
fuente