¿Alguien puede decirme cómo puedo imitar la hoja inferior en la nueva aplicación Maps en iOS 10?
En Android, puede usar uno BottomSheet
que imite este comportamiento, pero no pude encontrar algo así para iOS.
¿Es una simple vista de desplazamiento con un contenido insertado, de modo que la barra de búsqueda está en la parte inferior?
Soy bastante nuevo en la programación de iOS, por lo que si alguien pudiera ayudarme a crear este diseño, sería muy apreciado.
Esto es lo que quiero decir con "hoja inferior":
Respuestas:
No sé cómo responde exactamente la hoja inferior de la nueva aplicación Maps a las interacciones de los usuarios. Pero puede crear una vista personalizada que se parezca a la de las capturas de pantalla y agregarla a la vista principal.
Supongo que sabes cómo:
1- crea controladores de vista ya sea por guiones gráficos o usando archivos xib.
2- usa googleMaps o el MapKit de Apple.
Ejemplo
1- Cree 2 controladores de vista, por ejemplo, MapViewController y BottomSheetViewController . El primer controlador alojará el mapa y el segundo es la hoja inferior.
Configurar MapViewController
Cree un método para agregar la vista de la hoja inferior.
Y llámelo en el método viewDidAppear:
Configurar BottomSheetViewController
1) Preparar el fondo
Cree un método para agregar efectos de desenfoque y vitalidad
llame a este método en su vista
Asegúrese de que el color de fondo de la vista de su controlador sea clearColor.
2) Animar la apariencia de la hoja inferior
3) Modifica tu xib como quieras.
4) Agregue el Reconocimiento de gestos panorámicos a su vista.
En su método viewDidLoad, agregue UIPanGestureRecognizer.
E implemente su comportamiento gestual:
Hoja inferior desplazable:
Si su vista personalizada es una vista de desplazamiento o cualquier otra vista que herede, entonces tiene dos opciones:
Primero:
Diseñe la vista con una vista de encabezado y agregue panGesture al encabezado. (mala experiencia del usuario) .
Segundo:
1 - Agregue panGesture a la vista de la hoja inferior.
2 - Implemente el UIGestureRecognizerDelegate y configure el delegado panGesture en el controlador.
3- Implemente shouldRecognizeSim simultáneamente con la función delegar y deshabilite la propiedad scrollView isScrollEnabled en dos casos:
De lo contrario, habilite el desplazamiento.
NOTA
En caso de que establezca .allowUserInteraction como una opción de animación, como en el proyecto de muestra, debe habilitar el desplazamiento en el cierre de finalización de la animación si el usuario se desplaza hacia arriba.
Proyecto de muestra
Creé un proyecto de muestra con más opciones en este repositorio que puede brindarle una mejor perspectiva sobre cómo personalizar el flujo.
En la demostración, la función addBottomSheetView () controla qué vista debe usarse como una hoja inferior.
Ejemplos de capturas de pantalla del proyecto
- Vista parcial
- Vista completa
- Vista desplazable
fuente
Lancé una biblioteca basada en mi respuesta a continuación.
Imita la superposición de la aplicación Atajos. Vea este artículo para más detalles.
El componente principal de la biblioteca es el
OverlayContainerViewController
. Define un área donde se puede arrastrar un controlador de vista hacia arriba y hacia abajo, ocultando o revelando el contenido debajo de él.Implemente
OverlayContainerViewControllerDelegate
para especificar el número de muescas deseadas:Respuesta anterior
Creo que hay un punto significativo que no se trata en las soluciones sugeridas: la transición entre el desplazamiento y la traducción.
En Maps, como habrás notado, cuando alcanza TableView
contentOffset.y == 0
, la hoja inferior se desliza hacia arriba o hacia abajo.El punto es complicado porque no podemos simplemente habilitar / deshabilitar el desplazamiento cuando nuestro gesto panorámico comienza la traducción. Pararía el desplazamiento hasta que comience un nuevo toque. Este es el caso en la mayoría de las soluciones propuestas aquí.
Aquí está mi intento de implementar esta moción.
Punto de partida: aplicación de mapas
Para iniciar nuestra investigación, vamos a visualizar la vista de jerarquía de Mapas (iniciar Mapas en un simulador y seleccione
Debug
>Attach to process by PID or Name
>Maps
en Xcode 9).No dice cómo funciona el movimiento, pero me ayudó a entender la lógica del mismo. Puedes jugar con el lldb y el depurador de jerarquía de vistas.
Nuestras pilas de controladores de vista
Creemos una versión básica de la arquitectura Maps ViewController.
Comenzamos con un
BackgroundViewController
(nuestra vista de mapa):Ponemos el tableView en un dedicado
UIViewController
:Ahora, necesitamos un VC para incrustar la superposición y administrar su traducción. Para simplificar el problema, consideramos que puede traducir la superposición de un punto estático
OverlayPosition.maximum
a otroOverlayPosition.minimum
.Por ahora solo tiene un método público para animar el cambio de posición y tiene una vista transparente:
Finalmente necesitamos un ViewController para incrustar todo:
En nuestro AppDelegate, nuestra secuencia de inicio se ve así:
La dificultad detrás de la traducción superpuesta
Ahora, ¿cómo traducir nuestra superposición?
La mayoría de las soluciones propuestas utilizan un reconocedor de gestos panorámicos dedicado, pero en realidad ya tenemos uno: el gesto panorámico de la vista de tabla. Además, necesitamos mantener sincronizados el desplazamiento y la traducción, ¡y
UIScrollViewDelegate
tiene todos los eventos que necesitamos!Una implementación ingenua usaría un segundo gesto panorámico e intentaría restablecer la
contentOffset
vista de la tabla cuando se produzca la traducción:Pero no funciona. TableView actualiza
contentOffset
cuando se activa su propia acción de reconocimiento de gestos panorámicos o cuando se llama a su devolución de llamada displayLink. No hay posibilidad de que nuestro reconocedor se active inmediatamente después de aquellos para anular con éxito elcontentOffset
. Nuestra única posibilidad es participar en la fase de diseño (anulandolayoutSubviews
las llamadas de la vista de desplazamiento en cada cuadro de la vista de desplazamiento) o responder aldidScroll
método del delegado llamado cada vez quecontentOffset
se modifica. Probemos con este.La implementación de la traducción
OverlayVC
Agregamos un delegado a nuestro para enviar los eventos de la vista de desplazamiento a nuestro controlador de traducción, elOverlayContainerViewController
:En nuestro contenedor, hacemos un seguimiento de la traducción usando una enumeración:
El cálculo de la posición actual se ve así:
Necesitamos 3 métodos para manejar la traducción:
El primero nos dice si necesitamos comenzar la traducción.
El segundo realiza la traducción. Utiliza el
translation(in:)
método del gesto panorámico de scrollView.El tercero anima el final de la traducción cuando el usuario suelta su dedo. Calculamos la posición usando la velocidad y la posición actual de la vista.
La implementación de delegado de nuestra superposición simplemente se ve así:
Problema final: despachar los toques del contenedor de superposición
La traducción ahora es bastante eficiente. Pero todavía hay un problema final: los toques no se entregan a nuestra vista de fondo. Todos son interceptados por la vista del contenedor de superposición. No podemos establecer
isUserInteractionEnabled
quefalse
, ya que también podría desactivar la interacción en nuestra opinión mesa. La solución es la que se usa masivamente en la aplicación MapasPassThroughView
:Se elimina de la cadena de respuesta.
En
OverlayContainerViewController
:Resultado
Aquí está el resultado:
Puedes encontrar el código aquí .
Por favor, si ve algún error, ¡avíseme! Tenga en cuenta que su implementación puede, por supuesto, usar un segundo gesto de desplazamiento, especialmente si agrega un encabezado en su superposición.
Actualización 23/08/18
Podemos reemplazar
scrollViewDidEndDragging
con enwillEndScrollingWithVelocity
lugar deenabling
/disabling
el desplazamiento cuando el usuario termina de arrastrar:Podemos usar una animación de primavera y permitir la interacción del usuario mientras animamos para que el movimiento fluya mejor:
fuente
UIViewPropertyAnimator
(que tiene la capacidad de pausar), luego use lafractionComplete
propiedad para realizar la limpieza.translateView(following:)
método, calcula la altura en función de la traducción, pero eso podría comenzar desde un valor diferente a 0.0 (por ejemplo, la vista de tabla se desplaza un poco y la superposición se maximiza cuando comienza a arrastrar) . Eso resultaría en el salto inicial. Puede resolver esto mediante lascrollViewWillBeginDragging
devolución de llamada donde recordaría la inicialcontentOffset
de la vista de tabla y la usaría en eltranslateView(following:)
cálculo de.csrutil disable && reboot
. Entonces tendrá todos los poderes que la raíz debería darle normalmente, incluida la posibilidad de conectarse a un proceso de Apple.Prueba la polea :
https://github.com/52inc/Pulley
fuente
Puedes probar mi respuesta https://github.com/SCENEE/FloatingPanel . Proporciona un controlador de vista de contenedor para mostrar una interfaz de "hoja inferior".
¡Es fácil de usar y no le importa el manejo del reconocedor de gestos! También puede rastrear una vista de desplazamiento (o la vista de hermanos) en una hoja inferior si es necesario.
Este es un ejemplo simple. Tenga en cuenta que debe preparar un controlador de vista para mostrar su contenido en una hoja inferior.
Aquí hay otro código de ejemplo para mostrar una hoja inferior para buscar una ubicación como Apple Maps.
fuente
Escribí mi propia biblioteca para lograr el comportamiento deseado en la aplicación ios Maps. Es una solución orientada al protocolo. Por lo tanto, no necesita heredar ninguna clase base, sino crear un controlador de hoja y configurarlo como desee. También es compatible con la navegación / presentación interna con o sin UINavigationController.
Vea el siguiente enlace para más detalles.
https://github.com/OfTheWolf/UBottomSheet
fuente
Recientemente creé un componente llamado
SwipeableView
como subclase deUIView
, escrito en Swift 5.1. Admite las 4 direcciones, tiene varias opciones de personalización y puede animar e interpolar diferentes atributos y elementos (como restricciones de diseño, color de fondo / tinte, transformación afín, canal alfa y centro de visualización, todos demostrados con el caso de exhibición respectivo). También admite la coordinación de deslizamiento con la vista de desplazamiento interno si está configurado o se detecta automáticamente. Debería ser bastante fácil y sencillo de usar (espero 🙂)Enlace en https://github.com/LucaIaco/SwipeableView
prueba de concepto:
Espero eso ayude
fuente
Quizás puedas probar mi respuesta https://github.com/AnYuan/AYPannel , inspirada en Pulley. Transición suave de mover el cajón a desplazarse por la lista. Agregué un gesto de desplazamiento en la vista de desplazamiento del contenedor y configuré shouldRecognizeSim simultáneamenteWithGestureRecognizer para que devuelva SÍ. Más detalles en mi enlace de github arriba. Deseo ayudar
fuente