Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. Mobile Development

Componentes animados con UIKit Dynamics: Parte 1

Difficulty:IntermediateLength:LongLanguages:

Spanish (Español) translation by CYC (you can also view the original English article)

Introducción

En este tutorial, voy a mostrarte una nueva adición al iOS SDK que se introdujo en iOS 7, UIKit Dynamics, y te mostraré cómo se puede usar para crear efectos de animación atractivos y llamativos.

El propósito de la interfaz es permitir a los desarrolladores agregar realismo a tus aplicaciones de una manera fácil y directa. En este tutorial, veremos una serie de ejemplos que ilustran esto.

En la primera parte de este tutorial, demostraré cómo crear un menú animado y en la segunda parte nos enfocaremos en crear una vista de alerta animada personalizada. Crearemos el menú y la vista de alerta como componentes independientes para maximizar la reutilización.

1. UIKit Dynamics Essentials

Antes de comenzar a escribir código, es necesario echar un vistazo a los elementos esenciales de UIKit Dynamics. UIKit Dynamics es parte del framework UIKit, lo que significa que no necesitas agregar frameworks adicionales a tus proyectos para usarlo.

Proporciona a los desarrolladores una interfaz para agregar efectos realistas a la capa de visualización de sus aplicaciones. Es importante mencionar que UIKit Dynamics hace uso de un motor de física para hacer su trabajo. Esto permite a los desarrolladores centrarse en la funcionalidad que les gustaría agregar a su aplicación en lugar de la implementación. Un conocimiento básico de matemáticas y física es todo lo que necesitas para comenzar con UIKit Dynamics.

El componente principal de la interfaz de UIKit Dynamics es la clase UIDynamicAnimator, que también se conoce como el animador dinámico. Esta clase es responsable de realizar las animaciones usando un motor de física debajo del capó. Aunque el animador dinámico es el corazón de la interfaz de UIKit Dynamics, no se puede usar solo.

Para poder trabajar, se deben agregar comportamientos específicos al animador dinámico. Estos comportamientos son una colección de fuerzas físicas que definen la animación que resulta de agregar uno o más comportamientos. Programáticamente hablando, estos comportamientos dinámicos son clases de la interfaz de UIKit Dynamics y cada comportamiento tiene atributos específicos que se pueden modificar para influir en la animación.

La clase base de estos comportamientos es la clase UIDynamicBehavior. Aunque puedes crear tus propios comportamientos personalizados, UIKit Dynamics incluye varias subclases fáciles de usar que imitan comportamientos comunes, como la gravedad y las colisiones.

  • UIGravityBehavior: Esta subclase UIDynamicBehavior agrega gravedad a un elemento. Como resultado, el elemento se mueve a una determinada dirección definida por el comportamiento de la gravedad.
  • UICollisionBehavior: Esta clase define cómo dos elementos colisionan entre sí o cómo colisiona un elemento con un límite predefinido, visible o invisible.
  • UIPushBehavior: Como su nombre indica, este comportamiento le da un empujón a un elemento, lo acelera. El empuje puede ser continuo o instantáneo. Un comportamiento de empuje continuo aplica gradualmente la fuerza del empuje mientras que un comportamiento de empuje instantáneo aplica la fuerza en el momento en que se agrega el comportamiento.
  • UISnapBehavior: Un comportamiento rápido define cómo un elemento se ajusta a otro elemento o un punto en el espacio. El comportamiento de ajuste se puede personalizar de varias maneras. Por ejemplo, el elemento puede ajustarse a un punto sin rebote o agitarse durante unos momentos antes de detenerse.
  • UIAttachmentBehavior: Un comportamiento de archivo adjunto define cómo dos elementos dinámicos están conectados entre sí o cómo un elemento dinámico está conectado a un punto de anclaje.

Estos son los comportamientos dinámicos más importantes que brinda actualmente la interfaz de UIKit Dynamics. Para que estos comportamientos hagan su trabajo, deben inicializarse, configurarse y agregarse a un objeto animador dinámico, que cubrimos anteriormente.

La combinación de comportamientos es posible siempre que no causen ningún conflicto. También ten en cuenta que algunos comportamientos solo se pueden agregar una vez al objeto animador dinámico. Por ejemplo, agregar dos instancias de la clase UIGravityBehavior al animador dinámico dará como resultado una excepción.

Los comportamientos siempre se aplican a elementos dinámicos. Un elemento dinámico es cualquier objeto que se ajuste al protocolo UIDynamicItem. Lo bueno es que las clases UIView y UICollectionViewLayoutAttributes ya se ajustan a este protocolo. Esto significa que cada vista en tu aplicación puede aprovechar UIKit Dynamics.

Hay una subclase UIDynamicBehavior más que vale la pena mencionar, UIDynamicItemBehavior. En lugar de definir un comportamiento específico, ofrece una configuración de animación dinámica básica que se puede aplicar a elementos dinámicos. Tiene una serie de propiedades para definir el comportamiento:

  1. elasticity: Esta propiedad define la elasticidad de una colisión entre elementos dinámicos o un elemento dinámico y un límite. El valor varía de 0.0 a 1.0, siendo este último una colisión muy elástica.
  2. density: Esta propiedad define la masa de un elemento dinámico con un valor alto que da como resultado un objeto pesado. Esto puede ser útil si no deseas que se mueva un elemento dinámico cuando otro artículo colisiona con él.
  3. resistance: El nombre de la propiedad habla por sí mismo. La propiedad define la amortiguación de velocidad de un elemento dinámico.
  4. angularResistance: Esta es similar a la propiedad de resistencia llamada resistance, pero la propiedad angularResistance define la amortiguación angular de la velocidad.
  5. friction: Esta propiedad define la fricción o resistencia de dos elementos dinámicos que se deslizan uno contra el otro.
  6. allowsRotation: Este simplemente especifica si un elemento dinámico puede rotar o no.

La combinación de comportamientos dinámicos puede dar resultados espectaculares. En este tutorial, usaremos la mayoría de los comportamientos enumerados anteriormente.

Te recomiendo que visites la documentación oficial de Apple y leas más sobre las clases clave de UIKit Dynamics. Además, después de terminar este tutorial, es útil jugar con el resultado para comprender mejor los conceptos y los diversos comportamientos definidos por UIKit Dynamics.

2. Descripción general de la aplicación

Ya he mencionado en la introducción que vamos a crear dos componentes reutilizables que aprovecharán UIKit Dynamics. En este tutorial, crearemos un menú animado personalizado. Echa un vistazo al resultado final a continuación.

Este componente es un objeto UIView que se desliza dentro y fuera de la pantalla. Para hacer que el menú aparezca y desaparezca, se usa un simple gesto de deslizar. Los elementos del menú se enumeran en una vista de tabla simple. La animación que ves en la captura de pantalla anterior se logra al combinar varios comportamientos dinámicos.

3. Creando el proyecto

Comienza ejecutando Xcode y crea un nuevo proyecto. Selecciona la plantilla de aplicación de vista única en la categoría Aplicación de la sección de iOS. Haz clic en Siguiente para continuar.

Nombra el proyecto como DynamicsDemo y asegúrate de que Dispositivos esté configurado para iPhone. Para este tutorial, he dejado el campo Prefijo de clase vacío, pero no dudes en ingresar tu propio prefijo de clase. Haz clic en Siguiente, indica a Xcode dónde deseas almacenar el proyecto y presiona en Crear.

Descarga los archivos fuente de este tutorial y agrega las imágenes del proyecto Xcode a tu proyecto en la carpeta Images.xcassets en Project Navigator.

(Imagen Copyright: icons8)

4. Comprender el menú

Antes de comenzar a implementar el componente de menú, es importante observar de cerca cómo debería funcionar. Como ya mencioné, el menú debe mostrarse deslizándose hacia la vista desde la derecha hacia la izquierda y ocultarse deslizándose fuera de la vista de izquierda a derecha.

Mostrar y ocultar el menú se activa con un gesto de deslizamiento. UIKit Dynamics será responsable del comportamiento o la animación del menú. Los comportamientos que usaremos son:

  1. Comportamiento de gravedad: El comportamiento de gravedad hará que el menú se mueva en la dirección correcta, hacia la izquierda o hacia la derecha. Sin el comportamiento de la gravedad, el menú no hará mucho.
  2. Comportamiento de colisión: El comportamiento de colisión es igualmente importante. Sin él, el menú no pararía de moverse una vez que se le aplicara la gravedad. Un límite invisible activará una colisión y hará que el menú se detenga donde queremos que pare.
  3. Comportamiento de empuje: A pesar de que los comportamientos de gravedad y colisión pueden animar el menú hacia adentro y hacia afuera, le daremos un empuje o aceleración adicional usando un comportamiento de empuje. Esto hará que la animación sea más ágil.
  4. Comportamiento dinámico de los elementos: También agregaremos un comportamiento de elemento dinámico para definir la elasticidad del menú. Esto dará lugar a una colisión hinchable.

En lugar de ejemplificar los comportamientos anteriores cada vez que necesitan surtir efecto, los inicializaremos una vez. Aplicamos y configuramos los comportamientos cuando los necesitamos, lo que dependerá de la posición del menú y la dirección en la que se necesita mover.

5. Propiedades, estructuras e inicialización

Paso 1: Crear la clase

Comencemos agregando una nueva clase al proyecto. Presiona Command-N, selecciona la clase Objective-C de la lista de plantillas en la sección iOS > Cocoa Touch. Haz clic en Siguiente para continuar.

Nombra la nueva clase MenuComponent y asegúrate de que la clase herede de NSObject. Haz clic en Siguiente, indica a Xcode dónde deseas guardar los archivos de clase y presiona Crear.

Paso 2: Declarar propiedades

Abre MenuComponent.h y define una enumeración que representará la dirección del menú. La dirección puede ser de izquierda a derecha o de derecha a izquierda. Agrega el siguiente fragmento de código debajo de la declaración de importación.

Abre MenuComponent.m, agrega una extensión de clase y declara las siguientes propiedades:

  • menuView: Este es el objeto de vista del menú que será animado dentro y fuera de la vista. La vista de tabla será una subvista de esta vista.
  • backgroundView: La vista de fondo es una vista semitransparente que evitará que el usuario toque nada más que la vista de menú.
  • targetView: Esta es la supervista a la que se agregarán las vistas de menú y de fondo.
  • optionsTableView: Esta es la vista de tabla que listará las opciones del menú.
  • menuOptions: Esta matriz contendrá las opciones del menú que se mostrará en la vista de tabla.
  • menuOptionImages: Esta matriz contendrá los nombres de archivo de las imágenes que se encuentran a la izquierda de cada celda de vista de tabla.
  • animator: Esta es la instancia de UIDynamicAnimator que animará el menú.
  • menuDirection: Esta propiedad es de tipo MenuDirectionOptions y determina la dirección en la que se moverá el menú.
  • menuFrame: Este es el marco del menú.
  • menuInitialFrame: Y este es el marco inicial del menú.
  • isMenuShown: Un indicador que marca si el menú se muestra o no.

Además de estas propiedades privadas, también debemos declarar algunas propiedades públicas. Revisa MenuComponent.h y agrega el siguiente fragmento de código:

  • menuBackgroundColor: Esta propiedad se usa para configurar el color de fondo del menú.
  • tableSettings: Este es el diccionario que mencioné en la sección anterior. Nos permitirá configurar la vista de tabla estableciendo una cantidad de opciones.
  • optionCellHeight: Este es el único atributo de vista de tabla que no se puede establecer utilizando el diccionario tableSettings. Especifica la altura de fila de las celdas de la vista de tabla.
  • acceleration: Esta propiedad especifica la magnitud del comportamiento de empuje, en otras palabras, la cantidad de fuerza aplicada a la vista de menú cuando se desliza dentro y fuera de la vista.

Paso 3: Implementando el método de inicialización

En este paso, declaramos un inicializador personalizado en el que establecemos:

  • El fotograma final de la vista de menú, es decir, el fotograma cuando se completa la animación y el menú es visible
  • La vista de destino a la que se agregará la vista de menú como una subvista
  • La matriz de opciones e imágenes mostradas por la vista de tabla
  • La dirección de la animación cuando se muestra el menú

La interfaz del inicializador personalizado se muestra a continuación. Agrégalo a la interfaz pública de la clase MenuComponent.

Echemos un vistazo a la implementación del inicializador personalizado. Agrega el siguiente fragmento de código al archivo de implementación de la clase MenuComponent. La implementación es bastante sencilla, como puedes ver a continuación.

6. Configurar todo

Hay una serie de propiedades que deben inicializarse y creo que, por lo tanto, es una buena idea agruparlas en unos pocos métodos privados. Navega a la extensión de clase de la clase MenuComponent y declara el siguiente método:

setupMenuView

En setupMenuView, configuramos la vista del menú. Debido a que el menú inicialmente necesita estar fuera del área visible de la pantalla, comenzamos por calcular el marco inicial del menú. A continuación, inicializamos la vista de menú con su fotograma inicial, establecemos su color de fondo y lo agregamos como una subvista al objetivo o vista principal.

setupBackgroundView

En setupBackgroundView, configuramos la vista de fondo. Ten en cuenta que el valor alpha de la vista de fondo se establece inicialmente en 0.0. Actualizamos este valor en el momento en que aparece el menú.

setupOptionsTableView

En setupOptionsTableView, comenzamos por inicializar la tabla invocando initWithFrame: en la cual el tamaño de la vista de menú se usa para el tamaño de la vista de tabla. La instancia de MenuComponent se establece como fuente de datos y delegado de la vista de tabla.

Al configurar la instancia de MenuComponent como fuente de datos de la vista de tabla y delegar, el compilador nos dice que la clase MenuComponent no se ajusta a los protocolos UITableViewDataSource y UITableViewDelegate. Arreglemos esto actualizando el archivo de encabezado de la clase MenuComponent como se muestra a continuación.

setupInitialTableViewSettings

En setupInitialTableViewSettings, inicializamos y completamos el diccionario tableSettings que declaramos anteriormente en la interfaz pública de la clase.

setupSwipGestureRecognizer

En setupSwipeGestureRecognizer, inicializamos y configuramos el reconocedor de gestos de barrido que se utiliza para ocultar la vista del menú.

Dos cosas valen la pena señalar. En primer lugar, la dirección del gesto de deslizamiento depende del valor de la propiedad menuDirection. En segundo lugar, el método hideMenuWithGesture: es un método privado que se invoca cada vez que el reconocedor de gestos detecta un gesto de deslizamiento. Implementaremos este método más adelante, pero, para deshacernos de la advertencia del compilador, declara el método en la extensión de clase privada de la clase MenuComponent como se muestra a continuación.

Aprovechemos el trabajo que acabamos de hacer invocando los métodos auxiliares en el método de inicialización como se muestra a continuación.

Ten en cuenta que la vista de fondo está configurada antes de la vista de menú para asegurarte de que la vista de fondo se encuentre debajo de la vista de menú.

Finalmente, inicializa las propiedades restantes después de invocar los métodos auxiliares como se muestra a continuación.

7. Comportamientos dinámicos

Cada vez que aparece o desaparece la vista de menú, utilizamos los mismos comportamientos dinámicos. Por lo tanto, reutilizaremos esos comportamientos dinámicos. Lo único que difiere es la dirección del menú durante la animación.

Vamos a crear un método en el cual inicializaremos y aplicaremos los comportamientos dinámicos necesarios y llamaremos a este método cada vez que el estado del menú necesite cambiar. Comienza por actualizar la extensión de clase privada de la clase con el método toggleMenu.

Ya mencioné que los comportamientos dinámicos que se utilizarán para animar el menú son gravedad, colisión y empuje. Cada uno de estos comportamientos tiene una o más propiedades que, cuando se modifican, determinan la dirección de la animación.

  • El comportamiento de gravedad tiene una propiedad direction, una estructura CGVector que especifica la dirección de la gravedad. Por ejemplo, al establecer la propiedad de dirección en {1.0, 0.0}, el comportamiento de la gravedad se desplaza hacia la derecha, mientras que un valor de {0.0, 1.0} da como resultado una fuerza que tira hacia la parte inferior.
  • El comportamiento de colisión funciona entre dos elementos dinámicos o entre un elemento dinámico y un límite. En nuestro ejemplo, necesitamos un límite invisible definido por dos puntos que detenga la vista del menú.
  • El comportamiento de inserción tiene una propiedad de magnitud llamada magnitude que define la aceleración aplicada a un elemento dinámico. El valor también determina la dirección del impulso.

En el método toggleMenu, primero calculamos los valores de las propiedades antes mencionadas. Luego creamos y configuramos los comportamientos dinámicos, y los agregamos al objeto animador dinámico.

Es importante destacar que los valores de isMenuShown, que indican si el menú se muestra actualmente o no, y menuDirection, que especifica la dirección de la animación, determinan los valores de las propiedades antes mencionadas.

El objeto animator tiene una matriz que contiene todos los comportamientos dinámicos que se le han agregado. Cada vez que se llama al método toggleMenu, los comportamientos dinámicos existentes deben eliminarse borrando la matriz, porque algunos comportamientos dinámicos no se pueden agregar dos veces al comportamiento dinámico, como el comportamiento de la gravedad.

Comencemos implementando el método toggleMenu.

Las variables gravityDirectionX, collisionPointFrom, collisionPointTo y pushMagnitude contendrán los valores que asignaremos a los comportamientos dinámicos más adelante. Establezcamos sus valores, dependiendo del estado del menú y la dirección de la animación.

El fragmento de código anterior es bastante simple de entender, a pesar de su tamaño. Los comentarios en el código te ayudarán a comprender lo que está sucediendo. Ten en cuenta que el valor alpha de la vista de fondo está determinado por si el menú está a punto de mostrarse u ocultarse.

Es hora de agregar los comportamientos dinámicos. Comencemos con el comportamiento de la gravedad.

Usamos la variable gravityDirectionX para establecer la propiedad gravityDirection de gravedad.

Puedes haber notado que los métodos de inicialización de los comportamientos de gravedad y colisión aceptan una matriz que contiene los elementos dinámicos a los que se aplicará el comportamiento. En nuestro ejemplo, solo está la vista de menú.

Antes de agregar el comportamiento de empuje al animador dinámico, primero creemos un comportamiento de elemento dinámico, que es, simplemente, un comportamiento de propósito general que usaremos para establecer la elasticidad de la colisión. Cuanto mayor es el valor de elasticidad elasticity, mayor es el rebote de la colisión entre la vista y el límite invisible. Los valores aceptados van de 0.0 a 1.0.

Podríamos haber establecido más atributos de comportamiento utilizando el objeto itemBehavior, como la resistencia o la fricción. Puedes jugar con estas propiedades más adelante si lo deseas.

Vamos a añadir ahora el comportamiento de empuje que acelerará el menú.

Al establecer el modo en UIPushBehaviorModeInstantaneous, la fuerza del comportamiento de inserción se aplica de una sola vez en lugar de gradualmente. Los comportamientos dinámicos ahora se han agregado al animador dinámico, lo que significa que es hora de hacer que la vista del menú aparezca y desaparezca.

8. Mostrar y ocultar el menú

Paso 1: showMenu

Para mostrar y ocultar el menú, necesitamos invocar el método privado toggleMenu. El menú debería aparecer cuando la vista de destino detecta un gesto de deslizamiento en la dirección del deslizamiento. Comencemos por declarar un método público que podamos invocar para mostrar el menú. Abre ViewController.h y declara el método showMenu como se muestra a continuación.

La implementación es muy simple, porque todo lo que hacemos es invocar el método toggleMenu. Ten en cuenta que actualizamos isMenuShown para reflejar el nuevo estado del menú.

Paso 2: Mostrando el menú

Comencemos a usar la clase MenuComponent en nuestro controlador de vista. Abre ViewController.m y agrega una declaración de importación en la parte superior.

En la extensión de clase privada de ViewController, declara una propiedad menuComponent de tipo MenuComponent para el menú.

Antes de inicializar el menú, creemos el reconocedor de gestos que detectará los gestos de barrido para mostrar y ocultar el menú. Hacemos esto en el método viewDidLoad del controlador de vista.

El método showMenu: activado por el reconocedor de gestos es un método de ayuda privada que implementaremos en breve. Ten en cuenta que la dirección del gesto se establece en UISwipeGestureRecognizerDirectionLeft, lo que significa que queremos que el menú se active desde la derecha hacia la izquierda.

Con el reconocedor de gestos inicializado, es hora de crear el menú utilizando el inicializador que implementamos anteriormente en la clase MenuComponent. Agrega el siguiente fragmento de código al método viewDidLoad del controlador de vista.

Asegúrate de que la dirección que pase en el método de inicialización coincida con la del reconocedor de gestos.

A continuación, declara el método showMenu: en la extensión de clase del controlador de vista.

La implementación del método showMenu: no podría ser más fácil.

Antes de ejecutar la aplicación por primera vez, visita MenuComponent.m y cometa la invocación del método setupOptionsTableView en el método de inicialización. Esto es necesario si queremos evitar que nuestra aplicación falle, porque aún no hemos implementado los protocolos de vista de tabla.

Ejecuta la aplicación y desliza de derecha a izquierda. En este punto, el menú debería aparecer, pero no podemos hacer que desaparezca y el menú aún no muestra ninguna opción.

Paso 3: Ocultar el menú

Aunque el gesto de deslizamiento para mostrar el menú se realiza en la vista a la que se agrega el menú, el menú para detectar el gesto para ocultar el menú debe ser detectado. ¿Recuerdas que creamos un reconocedor de gestos en la clase MenuComponent y lo declaramos hideMenuWithGesture:? El último método se invocará cuando el menú deba ocultarse.

Implementemos hideMenuWithGesture: en MenuComponent.m. Su implementación es bastante simple, como puedes ver a continuación.

Si ejecutas la aplicación ahora, deberías poder mostrar y ocultar el menú con un gesto deslizante.

9. Opciones de menú

La vista del menú ahora puede aparecer y desaparecer. Es hora de centrar nuestra atención en configurar la vista de la tabla de opciones y mostrar las opciones del menú. Ya hemos declarado algunas opciones durante la inicialización del menú en el método viewDidLoad del controlador de vista. Veamos qué tenemos que hacer para mostrarlos.

Lo primero que debemos hacer es implementar el método requerido de los protocolos UITableViewDataSource y UITableViewDelegate. Ten en cuenta que la altura de la celda se especifica mediante la propiedad optionCellHeight.

En tableView:cellForRowAtIndexPath:, configuramos las celdas para mostrar las opciones e imágenes del menú. Ten en cuenta que usamos el objeto tableSettings para configurar las celdas de la vista de tabla.

Antes de ejecutar la aplicación, asegúrate de descomentar la llamada a setupOptionsTableView.

Eso es. Ejecuta la aplicación y desliza de derecha a izquierda para mostrar el menú y sus opciones.

10. Manejo de selección de usuario

Como mencioné anteriormente, no implementaremos un protocolo de delegado para el menú de opciones. En cambio, haremos uso de bloques. Sin embargo, no agregaremos ningún método nuevo. En cambio, vamos a modificar ligeramente el método showMenu. Comienza por actualizar tu declaración en MenuComponent.h como se muestra a continuación.

El método showMenu: ahora acepta un argumento, un bloque. El bloque también acepta un argumento, la selección del usuario.

Esto también significa que necesitamos almacenar el bloque, porque necesitamos invocarlo cuando el usuario selecciona una opción del menú. En MenuComponent.m, declara una propiedad privada para almacenar el bloque.

Entonces necesitamos actualizar el método showMenu: como se muestra a continuación.

Comenzamos por almacenar el controlador handler en la propiedad selectionHandler. Cada vez que el usuario selecciona un elemento de la vista de tabla, invocamos el manejador de selección. Echa un vistazo a la implementación de tableView:didSelectRowAtIndexPath: para aclaración.

Finalmente, necesitamos actualizar el controlador de vista para usar el nuevo método showMenu:. Actualiza el método showMenu: del controlador de vista, que se invoca cuando se detecta un gesto de deslizamiento, con el que se muestra a continuación. Para asegurarnos de que todo funciona, mostramos una vista de alerta que muestra la selección del usuario.

Ejecuta la aplicación una vez más para asegurarte de que todo funcione como se espera. La clase de componente de menú está lista.

Conclusión

En este tutorial, hemos creado un componente reutilizable para mostrar un menú usando UIKit Dynamics. Si UIKit Dynamics era nuevo para ti, entonces espero que este tutorial te haya dado una idea de lo que puedes hacer con él. Siéntete libre de jugar con la aplicación de demostración para familiarizarte con UIKit Dynamics.

Estén atentos para el próximo tutorial en el que crearemos otro componente reutilizable, una vista de alerta personalizada.

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.