UIScrollView no se desplaza


128

Tengo una UIScrollViewque contiene muchos UIImageViews, UILabels, etc ... las etiquetas son mucho más largas que la UIScrollView, pero cuando ejecuto la aplicación, no puedo hacer clic y desplazarme hacia abajo ...

¿Por qué podría ser esto?

Gracias


Nuevo 26/03/2013 Me topé con una forma más fácil de hacer esto sin código (configuración de contenido Tamaño
Dickey Singh

Respuestas:


169

Siempre es bueno mostrar un fragmento de código de trabajo completo:

// in viewDidLoad (if using Autolayout check note below):

UIScrollView *myScrollView;
UIView *contentView;
// scrollview won't scroll unless content size explicitly set

[myScrollView addSubview:contentView];//if the contentView is not already inside your scrollview in your xib/StoryBoard doc

myScrollView.contentSize = contentView.frame.size; //sets ScrollView content size

Swift 4.0

let myScrollView
let contentView

// scrollview won't scroll unless content size explicitly set

myScrollView.addSubview(contentView)//if the contentView is not already inside your scrollview in your xib/StoryBoard doc

myScrollView.contentSize = contentView.frame.size //sets ScrollView content size

No he encontrado una manera de configurar contentSize en IB (a partir de Xcode 5.0) .

Nota: Si está utilizando Autolayout, el mejor lugar para colocar este código es dentro del -(void)viewDidLayoutSubviewsmétodo.


12
No olvide configurar myScrollView.delegate = selfTAMBIÉN, si esto todavía no funciona, la respuesta a continuación tiene un GRAN consejo (vaya a su xib / StoryBoard y asegúrese de que "AutoLayout" esté desactivado). Pro-Tip: También puede incluir <UIScrollViewDelegate>en su archivo .h si desea hacer cosas como desplazar programáticamente su UIScrollView.
Albert Renshaw

1
@AlbertRenshaw deberías haber agregado una respuesta para poder darte un +1 :) AutoLayout fue el problema conmigo ... me volvió loco durante unas 4 horas.
logixologist

2
Poner código lo viewDidLayoutSubviewshizo funcionar para mí.
Amr Lotfy

Para mí, el problema era que no necesitaba desplazarse, ya que todo cabía en la pantalla.
Daniel Springer

122

Si no puede desplazar la vista incluso después de configurar contentSize correctamente, asegúrese de desmarcar "Usar AutoLayout" en Interface Builder -> File Inspector.


164
Como alternativa, se puede establecer contentSize en viewDidLayoutSubviews: y éste se aplicará después de completarse autolayout.
Chris Vasselli

2
@ "Chris Vasselli" resolvió mi problema .. GR8 .. :-)
Ayaz

3
¡El comentario de Chris debería ser una respuesta separada!
ninjaneer

1
Muchas gracias Chris Vasselli! Con el diseño automático habilitado, no funcionará en viewDidLoad pero sí con viewDidLayoutSubviews.
Romain

1
Woah, ¡nunca antes había notado todos estos comentarios! ¡Me alegro de poder ayudar a tantos de ustedes! Acabo de publicar una respuesta por separado, así que espero que sea más fácil de encontrar.
Chris Vasselli

68

Debe establecer la contentSizepropiedad de la vista de desplazamiento para que se desplace correctamente.

Si está utilizando el diseño automático, es necesario conjunto contentSizeen viewDidLayoutSubviewsel fin de que sea aplicada después de que se complete el autolayout.

El código podría verse así:

-(void)viewDidLayoutSubviews
{
    // The scrollview needs to know the content size for it to work correctly
    self.scrollView.contentSize = CGSizeMake(
        self.scrollContent.frame.size.width,
        self.scrollContent.frame.size.height + 300
    );
}

Gracias una tonelada ... Esto funcionó porque, por alguna razón, incluso cuando configuré el valor del contentSizetamaño de contentView, el tamaño de scrollView y contentView parece establecerse de la misma manera. Pero establecer la altura de la contentSizea un valor mayor que la altura de contentView, funcionó.
Skywalker

viewDidLayoutSubviewspuede llamarse varias veces durante un ciclo de vida para que corra el riesgo de aumentar la altura más de lo esperado
anon_nerd

@anon_nerd solo verifica si ya se llamó y solo agrega altura si no es así
Daniel Springer

45

La respuesta anterior es correcta: para que el desplazamiento sea posible, es necesario establecer el tamaño del contenido.

Si está utilizando el generador de interfaces, una buena manera de hacerlo es con los atributos de tiempo de ejecución definidos por el usuario. P.ej:

ingrese la descripción de la imagen aquí


Esto no hizo nada por mí.
coolcool1994

44
Vaya, la imagen muestra {0, 0}, pero, por supuesto, tienes que poner números lo suficientemente grandes. . este enfoque solo funcionará para vistas simples donde conozca el tamaño del contenido por adelantado. . . (de hecho, para vistas complejas recomiendo código puro, de todos modos).
Jasper Blues

Mucho menos hacky que hacerlo programáticamente. ¡Gracias!
Jake Stoeffler

1
@JakeStoeffler bienvenido! :) Cuando uso IB, me gusta mantener toda la configuración allí (no fragmentada). Pero cuando las cosas se vuelven complejas (widgets de vista reutilizables; adaptadores de modelos, manipulaciones de capas; animaciones CA, etc.) entonces prefiero vistas completamente programáticas. . . Más fluido.
Jasper Blues

Intenté esto, funciona cuando aparece la vista, pero al cambiar la orientación, se ignora el contentSize definido en la pantalla de arriba y mi registro dice que contentSize se ha retrasado 0,0. ¿Alguna idea de como arreglarlo?
Shoogle

40

Intenta cambiar el tamaño del contenido a grandes cantidades. No podía entender por qué mi vista de desplazamiento no se desplaza incluso cuando su tamaño de contenido parece ser mayor que el tamaño de control. Descubrí que si el tamaño del contenido es más pequeño de lo necesario, tampoco funciona.

self.scrollView.contentSize = CGSizeMake(2000, 2000);

En lugar de 2000 puedes poner tus propios números grandes. Y si funciona, significa que el tamaño de su contenido no es lo suficientemente grande cuando cambia el tamaño.

El delegado no es necesario para que la vista de desplazamiento funcione.


2
Genio: una forma tan simple de comprobar lo que está sucediendo. ¡Gracias un montón!
The Crazy Chimp

13

Asegúrese de tener la propiedad contentSize de la vista de desplazamiento establecida en el tamaño correcto (es decir, una lo suficientemente grande como para abarcar todo su contenido).


1
¿Tengo que hacer esto programáticamente? o puedo hacerlo en IB?
Marque

Si está utilizando IB, puede configurarlo desde allí; consulte a continuación. . (Respuesta separada, así puedo incluir fotos).
Jasper Blues

7

Desmarcar 'Usar Autolayout' me sirvió.

Entorno: xCode 5.0.2 Storyboards ios7


5

En mi caso, tuve que establecerlo delaysContentTouchesen verdadero porque los objetos dentro del scrollView capturaban los eventos táctiles y se manejaban a sí mismos en lugar de dejar que el propio scrollView lo manejara.


Tengo el mismo problema El problema para mí es que al convertir retrasysContentTouches en verdadero, terminarás con dibujos de menor calidad con un lápiz de manzana. Pero este es un caso extremo :) en la mayoría de los casos resuelve el problema
RomOne

4

Establecer contentSizepropiedad de UIScrollviewen ViewDidLayoutSubviewsmétodo. Algo como esto

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    scrollView.contentSize = CGSizeMake(view.frame.size.width, view.frame.size.height)
}

3

La idea de por qué la vista de desplazamiento no se desplaza porque configura el tamaño del contenido para desplazarse menos que el tamaño de la vista de desplazamiento, lo cual es incorrecto. Debe establecer el tamaño del contenido más grande que el tamaño de su vista de desplazamiento para navegar a través de él mientras se desplaza.

La misma idea con el zoom, establece el valor mínimo y máximo para el zoom que se aplicará mediante la acción de zoom.

bienvenidos :)


3

Una pequeña adición, todo lo anterior son las razones reales por las que su vista de desplazamiento puede no estar desplazándose, pero a veces sin pensar, esta podría ser la razón especialmente cuando la vista de desplazamiento se agrega a través del código y no IB, es posible que haya agregado sus subvistas a la vista principal y no a la vista de desplazamiento hace que la subvista no se desplace

y mantenga el tamaño del contenido establecido y más grande que el marco de vista principal (¡duhh!)


3

Lo hice funcionar en mi primer intento. Con diseño automático y todo, sin código adicional. Luego, una vista de colección se convirtió en banana, se bloqueó en el tiempo de ejecución, no pude encontrar lo que estaba mal, así que lo eliminé y lo recreé (estoy usando Xcode 10 Beta 4. Se sintió como un error) y luego el desplazamiento desapareció. ¡Sin embargo, la vista Colección volvió a funcionar!

Muchas horas después ... esto es lo que me arregló. Tenía el siguiente diseño:

UIView

  • Area segura
  • Vista de desplazamiento
    • Vista de contenido

Todo está en las limitaciones. El área segura se define automáticamente por el sistema. En el peor de los casos, elimine todas las restricciones para las vistas de desplazamiento y contenido y no haga que IB las restablezca / cree por usted. Hazlos manualmente, funciona.

  • Para la vista de desplazamiento, hice: Alinear Trailing / Top al área segura. Ancho / Altura igual al área segura .
  • Para la vista de Contenido que hice: Alinear Trailing / Leading / Top / Bottom to Superview (la vista de desplazamiento)

Básicamente, el concepto es tener una vista de contenido que se ajuste a Scrollview, que se ajusta al área segura.

Pero como tal no funcionó. La vista de contenido perdió la altura. Intenté todo lo que pude y el único que hizo el truco fue una vista de contenido que creó la vista de contenido arrastrando el control . Eso definió una altura fija, cuyo valor se calculó a partir del Tamaño del controlador de vista (definido como forma libre, más largo que la pantalla real, hasta contener todas mis subvistas) y finalmente funcionó nuevamente.


¡Eres muy bienvenido! Sé exactamente cómo te sentiste ... ;-)
Michele Dall'Agata

Thaaaaks, pasé muchas horas y esto resolvió mi problema
Andoni Da Silva

3

si recibe un mensaje (IOS8 / swift) que viewDidLayoutSubviewsno existe, utilice lo siguiente

override func viewDidAppear(animated: Bool)

Esto me lo arregló


2

¡Algo que no se mencionó antes!

¡Asegúrese de que su toma de corriente esté conectada correctamente al scrollView! Debería tener un círculo lleno, pero incluso si tiene un círculo lleno, scrollView puede no estar conectado, ¡así que vuelva a verificar! Pase el cursor sobre el círculo y vea si la vista de desplazamiento real se resalta. (Este fue un caso para mí)

//Connect below well to the scrollView in the storyBoard
@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;

2

Muchas veces el código es correcto si ha seguido un tutorial, pero lo que muchos principiantes no saben es que scrollView NO se desplazará normalmente por el simulador. Se supone que debe desplazarse solo cuando presiona el mousepad y se desplaza simultáneamente. Muchos usuarios experimentados de XCode / Swift / Obj-C están tan acostumbrados a hacer esto y no saben cómo los principiantes podrían pasarlo por alto. Ciao :-)

@IBOutlet weak var scrollView: UIScrollView!
override func viewDidLoad() {
    super.viewDidLoad()
    view.addSubview(scrollView)
    // Do any additional setup after the view
}

override func viewWillLayoutSubviews(){
    super.viewWillLayoutSubviews()
    scrollView.contentSize = CGSize(width: 375, height: 800)
}

Este código funcionará perfectamente bien siempre y cuando hagas lo que dije arriba


1

Si ninguna de las otras soluciones funciona para usted, verifique que su vista de desplazamiento esté UIScrollViewen Interface Builder.

En algún momento en los últimos días, mi UIScrollView tipo cambió espontáneamente a un UIView, a pesar de que su clase lo dijo UIScrollViewen el inspector. Estoy usando Xcode 5.1 (5B130a).

Puede crear una nueva vista de desplazamiento y copiar las medidas, configuraciones y restricciones de la vista anterior, o puede cambiar manualmente su vista a a UIScrollViewen el xibarchivo. Hice una comparación y encontré las siguientes diferencias:

Original:

<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" directionalLockEnabled="YES" bounces="NO" pagingEnabled="YES" showsHorizontalScrollIndicator="NO" showsVerticalScrollIndicator="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Wsk-WB-LMH">
...
</scrollView>

Después del tipo cambiado espontáneamente:

<view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" customClass="UIScrollView" id="qRn-TP-cXd">
...
</view>

Así que reemplacé la <view>línea con mi <scrollView>línea original .

También reemplacé la etiqueta de cierre de la vista </view>con </scrollView>.

Asegúrese de mantener la identificación igual que la vista actual, en este caso: id = "qRn-TP-cXd".

También tuve que eliminar el xib del caché de Xcode eliminando los datos derivados de la aplicación:

  • Xcode->Window->Organizer->Projects, elija su proyecto, en la línea Datos derivados, haga clic en Eliminar ...

O si usa un dispositivo:

  • Xcode->Window->Organizer->Device, elija su dispositivo-> Aplicaciones, elija su aplicación, haga clic en (-)

Ahora limpie el proyecto y elimine la aplicación del simulador / dispositivo:

  • Xcode->Product->Clean
  • iOS Simulator/device->pressy mantenga presionada la app->click(X) para eliminarlo

Entonces debería poder compilar y ejecutar su aplicación y tener la funcionalidad de desplazamiento nuevamente.

PD: No tuve que configurar el tamaño del contenido de la vista de desplazamiento viewDidLayoutSubviewsni desactivar el diseño automático, pero YMMV.


1

Si su scrollViewes una subvista de containerViewalgún tipo, entonces asegúrese de que scrollViewesté dentro del marco o los límites de containerView. Tenía lo containerView.clipsToBounds = NOque todavía me permitía ver el scrollView, pero porque scrollViewno estaba dentro de los límites containerView, no detectaría eventos táctiles.

Por ejemplo:

containerView.frame = CGRectMake(0, 0, 200, 200);
scrollView.frame = CGRectMake(0, 200, 200, 200);
[containerView addSubview:scrollView];
scrollView.userInteractionEnabled = YES;

Podrá ver el scrollView pero no recibirá interacciones del usuario.


1

agregar el siguiente código viewDidLayoutSubviewsfuncionó para mí con Autolayout. Después de probar todas las respuestas:

- (void)viewDidLayoutSubviews
{
    self.activationScrollView.contentSize = CGSizeMake(IPHONE_SCREEN_WIDTH, 620);

}

//set the height of content size as required

1

Agregar UIScrollViewDelegatey agregar el siguiente código al viewDidAppearmétodo lo arregló para mí.

@interface testScrollViewController () <UIScrollViewDelegate>

-(void)viewDidAppear:(BOOL)animated {
    self.scrollView.delegate = self;
    self.scrollView.scrollEnabled = YES;
    self.scrollView.contentSize = CGSizeMake(375, 800);
}

1

Mi problema fue resuelto por:

  1. establecer el contentSize en scrollView a una altura grande
  2. PERO también tuve que corregir las restricciones superiores y / o inferiores en las vistas dentro de scrollView, lo que significaba que los indicadores de desplazamiento se mostraban en la pantalla pero el contenido no se desplazaba

Una vez que eliminé las restricciones superiores y / o inferiores vinculadas al área segura y / o la supervista, ¡las vistas dentro de scrollView podrían desplazarse nuevamente y no quedaron fijas en la parte superior inferior de la pantalla!

Espero que esto detenga a alguien más de horas de dolor con este problema en particular.


1

otro caso divertido más:

scrollview.superview.userInteractionEnabled debe ser verdadero

Perdí más de 2 horas persiguiendo esto solo para descubrir que el padre es UIImageView que, naturalmente, tiene userInteractionEnabled == false


0

Después de fallar con las respuestas proporcionadas en este hilo, me topé con este artículo con la solución.

Hay dos cosas no intuitivas sobre la configuración de la vista de desplazamiento con autolayout:

  1. Las restricciones que configura como margen entre la vista de contenido y la vista de desplazamiento no influyen en el tamaño de la vista de contenido. Realmente son márgenes. Y para que funcione, la vista de contenido debe tener un tamaño fijo.
  2. El truco para el tamaño fijo es que puede establecer el ancho de la vista de contenido igual al del padre de la vista de desplazamiento. Simplemente seleccione ambas vistas en el árbol de la izquierda y agregue la restricción de anchos iguales.

Esta es la esencia de ese artículo. Para una explicación completa, incluyendo ilustraciones, échale un vistazo.


@PredragManojlovic ¿Cómo puede ser más general que esto? Esta es la única forma en que podría hacer que la vista de desplazamiento funcione correctamente, utilizando el diseño automático.
H. de Jonge

0

Descubrí que con este problema de AutoLayout ... si solo hago el ViewControlleruso en UIViewlugar de UIScrollViewpara la clase ... entonces solo agrego un UIScrollViewyo ... que funciona.


0

Tuve el mismo problema en el IB.

Después de establecer el inicio, el final, la parte superior e inferior de scrollView en su superView. Hice los siguientes cambios para hacer que containerView se desplazara, lo que funcionó.

Para hacer que scrollView solo se desplace en dirección horizontal, haga la restricción con scrollView's centerY = ContainerView's centerY

y para que se pueda desplazar verticalmente, haga que centerView de scrollView = centerX de ContainerView

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.