UIScrollView image/photo viewer con paginación habilitada y zoom


OK, creo que es hora de hacer un lugar oficial en Internet para este problema: Cómo hacer un UIScrollView photoviewer con paginación y zoom. Bienvenido a mis compañeros hackers UIScrollView.

Tengo un UIScrollView con paginación habilitada, y estoy mostrando UIImageViews como la aplicación integrada de fotos. (¿ Esto ya te suena familiar?)

Encontré el siguiente proyecto en github:

Http://wiki.github.com/andreyvit/ScrollingMadness

Que muestra cómo implementar el zoom en una vista de desplazamiento mientras la paginación está habilitada. Si alguien más prueba esto, en realidad tuve que eliminar la subclase UIScrollView y usar la clase nativa de lo contrario no funciona. Creo que es debido a los cambios en el SDK 3.0 relacionados con la forma en que la vista de desplazamiento intercepta los eventos táctiles.

Así que la idea es eliminar todas las otras vistas cuando comience a hacer zoom, y mover la vista actual a (0, 0) en el scrollview, actualizando el contentsize etc. Luego, cuando se vuelve a acercar a 1.0 f, agrega las otras vistas y pone las cosas en orden.

De todos modos, ese proyecto funciona perfectamente en el simulador, pero en el dispositivo hay algún movimiento desagradable de la vista que está redimensionando, que parece que es causado por el hecho de que estamos cambiando la contentsize/offset etc. para la vista que se está redimensionando. Tiene que hacer esta vista moviéndose de lo contrario puede desplazarse a la izquierda a través del espacio en blanco dejado por las otras vistas.

Encontré una nota interesante en los" Problemas conocidos " de la versión 3.0 SDK de notas:

UIScrollView: Después del zoom, la inserción de contenido se ignora y el contenido se deja en la posición incorrecta.

Este tipo de sonidos como lo que está sucediendo aquí. Después de hacer zoom, la vista se desplazará fuera de la pantalla porque ha cambiado el desplazamiento, etc.

Ya he pasado horas en esto y estoy desacelerando llegando a la triste realización de que esto simplemente no va a funcionar.

El visor de fotos de Three20 está fuera de discusión: es demasiado pesado y hay demasiada interfaz de usuario innecesaria y otros comportamientos.

La aplicación de fotos integrada parece hacer algo de magia. Si hace zoom en una imagen y se desplaza hacia los bordes lejanos, la foto actual se mueve independientemente de la foto de al lado, lo que no es lo que obtiene al probar esto con un UIScrollView estándar.

He visto discusiones sobre anidar los UIScrollView's pero realmente no quiero ir allí.

¿Alguien ha manejado esto con el estándar UIScrollView (y funciona en el SDK 2.2 y 3.0)? No me apetece rodando mi propio zoom + rebote + pan + código de paginación.

Author: Ajumal, 2009-06-10

8 answers

ACTUALIZAR

Eliminé mi respuesta anterior debido a las noticias a continuación...

Grandes noticias para aquellos que no han escuchado. Apple ha lanzado los videos de la sesión WWDC 2010 a todos los miembros del programa para desarrolladores de iphone. Uno de los temas discutidos es cómo crearon la aplicación fotos!!! Construyen una aplicación muy similar paso a paso y han hecho que todo el código esté disponible de forma gratuita.

Tampoco utiliza api privada. Aquí hay un enlace a la descarga del código de ejemplo. Usted probablemente tendrá que iniciar sesión para obtener acceso.

Compruebe esto

Y, aquí hay un enlace a la página de iTunes WWDC:

Compruebe esto

 43
Author: Jonah,
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
2012-08-09 08:10:48

He escrito un navegador de fotos simple y fácil de usar llamado MWPhotoBrowser. Decidí crearlo ya que Three20 era demasiado pesado / hinchado, ya que todo lo que necesitaba era un visor de fotos.

MWPhotoBrowser puede mostrar una o más imágenes proporcionando objetos UIImage, o URL a archivos, imágenes web o recursos de biblioteca. El navegador de fotos maneja la descarga y el almacenamiento en caché de fotos desde la web sin problemas. Las fotos se pueden ampliar y panear, y los subtítulos opcionales (personalizables) se pueden Visualiza. El navegador también se puede utilizar para permitir al usuario seleccionar una o más fotos utilizando la vista de cuadrícula o imagen principal.

MWPhotoBrowser Capturas de pantalla

 32
Author: Michael Waterfall,
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-01-13 17:58:07

Dices que has visto discusiones sobre anidamiento de UIScrollViews pero no quieres ir allí, ¡pero ese es el camino a seguir! Funciona fácil y bien.

Es esencialmente lo que hace Apple en su ejemplo de PhotoScroller (y la charla de WWDC de 2010 vinculada a la respuesta de Jonah). Solo en esos ejemplos, han agregado un montón de mosaicos complejos y otra gestión de memoria. Si no necesita el mosaico, etc. y si usted no quiere vadear a través de esos ejemplos y tratar de eliminar los bits relacionados para ello, el principio subyacente de anidar UIScrollViews es en realidad bastante simple:

  • Cree un UIScrollView externo y establezca su pagingEnabled = true. Agrégalo a tu vista principal y establece su anchura y altura a la anchura y altura de tu vista principal.

  • Cree tantas UIScrollViews internas como desee. Establezca su anchura y altura en la anchura y altura de la vista principal. Agrégalas como subviews a tu UIScrollView exterior, cada una junto a la otra, a la izquierda derecho.

  • Establezca el tamaño de contenido de la vista UIScrollView externa al total de los anchos de todas las vistas UIScrollViews internas una al lado de la otra (que es igual a [el ancho de la vista principal]*[número de imágenes]).

  • Añade las UIImageViews de tus imágenes a las UIScrollViews internas, una UIImageView a cada UIScrollView interna. Establezca el tamaño de contenido de cada UIScrollView al tamaño de cada UIImageView.

  • Establecer escalas de zoom min y max para cada UIScrollView interior y establecer cada uno de los delegado de UIScrollView interno a su Controlador de vista. En viewForZoomingInScrollView del delegado, devuelve la vista UIImageView apropiada para la vista UIScrollView que se pasa. (Para hacer esto, simplemente mantenga cada una de las UIImageViews en un NSArray y establezca la propiedad de etiqueta de UIScrollView correspondiente en el índice de la UIImageView apropiada. A continuación, puede leer la etiqueta en el UIScrollView pasado a viewForZoomingInScrollView y devolver el UIImageView apropiado desde el NSArray).

Eso es todo. Funciona igual que la aplicación de fotos.

Si tiene muchas fotos, para ahorrar memoria solo puede tener dos UIScrollViews internas y dos UIImagesViews. A continuación, voltea dinámicamente entre ellos, moviendo su posición dentro del UIScrollView externo y cambiando sus imágenes a medida que el usuario se desplaza por el UIScrollView externo. Es un poco más complejo pero el mismo principio.

 19
Author: delany,
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
2012-04-28 06:20:40

Hice algunos juegos con la aplicación nativa de Fotos, y creo que puedo decir con confianza que están utilizando un solo UIScrollView. El sorteo es el siguiente: haz zoom en una imagen y tira hacia la izquierda o hacia la derecha. Verá la foto siguiente o anterior. Si tira lo suficientemente fuerte, incluso la página a la siguiente foto en 1.0 f zoom. Voltear hacia atrás y la foto previamente ampliada volverá a 1.0 f zoom también.

Obivously no escribí Fotos.aplicación, pero voy a tomar una conjetura salvaje en cómo lo hicieron it:

  • Un único UIScrollView y un único UIScrollViewDelegate
  • Rellene el UIScrollView con los hijos de UIImageView
  • Escucha scrollViewDidScroll:
  • Haz algunas matemáticas y averigua en qué página estás actualmente
  • Escucha viewForZoomingInScrollView:
  • Devuelve una vista diferente dependiendo del índice de la página
  • Escuchar scrollViewDidEndZooming:withView:atScale: y opcionalmente hacer algún anti-aliasing, etc basado en el contenido

Si decide probar eso, hágamelo saber funciona para ti. Me encantaría saber cómo finalmente terminas haciendo que esto funcione. Aún mejor, publícalo en github.

 6
Author: slf,
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
2010-02-08 17:54:41

Hice un poco de juego con el aplicación de Fotos nativas, y creo que puedo decir con confianza que están utilizando un UIScrollView simple. El sorteo es esto: hacer zoom en una imagen, y tirar a la izquierda o la derecha. Usted verá el foto siguiente o anterior. Si tira lo suficientemente duro, incluso la página a la siguiente foto en 1.0 f zoom. Voltear hacia atrás y la foto ampliada previamente será volver a zoom 1.0 f también.

Esto está mal. Estoy usando scrollviews anidadas, y obteniendo exactamente el mismo efecto. Si está utilizando algún esquema de gestión de memoria (que tuve que empezar a usar... mi número de página es bastante alto (aproximadamente 50 cada uno en 2 ScrollViews)), entonces puede usar un mecanismo similar a lo que tenga activando las cargas / descargas de su página para activar un restablecimiento de zoom para las páginas -1 y +1 de la página actual.

Sospecho que Apple desencadena esto tan pronto como la foto anterior ha desaparecido.

Lo que no entiendo es cómo lograr suavizar desplazamiento entre páginas-siempre hay una caída muy corta en el momento de la transición. No lo entiendo. Me he metido bastante en arreglarlo-NSInvocationOperations fueron mi primera parada, luego hice una cola de vistas reutilizables para las vistas de página (que conservan sus vistas de imagen)... aún así esta caída durada.

Solo tengo una NSOperationQueue en ejecución, y he intentado jugar con el número máximo de operaciones simultáneas. Mi pensamiento era que el hilo principal se estaba obstruyendo por competir Colas, o tal vez incluso una cola tratando de hacer mucho... aún así, la caída.

Incluso intenté crear versiones súper bajas de mis medios, en caso de que ese fuera el problema. Con cada imagen pesando alrededor de 10k (estos son jpegs, eso sí)... lo adivinaste. El ahorcamiento sigue ahí.

Estoy bastante resuelto a hacer lo que he hecho antes y usar TTPhotoViewController desde Three20. He pasado algunas horas nadando a través de ese código, y siempre es una gran educación. En este punto, sin embargo, realmente me gustaría saber de dónde diablos viene este ahorcamiento, aunque solo sea para poder pasar mis horas sin poder dormir preguntándome sobre algo menos que hierva el cerebro.

 1
Author: beOn,
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
2010-02-14 17:31:34

Seguro que sería bueno si Apple construyera un visor de imágenes como la aplicación fotos en el SDK para que lo usáramos. Actualmente estoy usando three20 y funciona muy bien. Pero es un montón de cosas adicionales para llevar cuando todo lo que realmente quieres es el visor de fotos.

 0
Author: Francois,
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
2010-06-11 21:55:24

Escribo un código para eso, y puede ser como referencia

  1. Cargue la vista actual scrollview y imageview .. y para la pantalla junto a la vista actual , solo imageview

  2. Eliminar toda la vista cuando se carga la página actual para ahorrar memoria, tan bueno para muchos photo project

  3. Use la etiqueta para diferenciar diferentes scrollview

primera página_xxxxdeslizarxxxzoom

El enlace de descarga haga clic aquí

 0
Author: chings228,
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
2012-02-07 09:11:45

Echa un vistazo a https://github.com/facebook/three20/blob/master/src/Three20UI/Headers/TTPhotoViewController.h No estoy seguro de si eso es lo que estás buscando

 -1
Author: Rafael Vega,
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-05-17 18:55:57