Buenas Prácticas Flutter: De una idea a un MVP 💡📲 — Parte V (Splash)

Christian Llansola
5 min readDec 6, 2020

--

Splash Screen personalizada, Animando widgets.

En el capĂ­tulo anterior ya dejamos preparada la base para nuestra Splash Screen.

La idea principal es que la imagen del logotipo vaya aumentando en el centro de la pantalla. AsĂ­ que antes de animar vamos a estructurar los widgets.

Podríamos animar la página de diferentes maneras. En este caso lo animaremos con AnimatedContainer.

AsĂ­ que vamos a ver cĂłmo podemos estructura esta pantalla.

Para animar el logo vamos a usar un AnimatedContainer, que es el que nos va a permitir que se anime todo su contenido.

Como podemos ver, hemos definido un AnimatedContainer con las mismas propiedades que usaríamos en un Container, a diferencia de que usaremos una duration para indicar cuánto tiempo queremos que dure la animación y curve para indicar el tipo de animación (más suave, lineal, etc).

De momento vamos a comprobar que todo se ve correctamente sin animar y no tenemos ningún error. El resultado sería una pantalla estática como esta:

Ahora que ya tenemos todo preparado, hemos de decidir qué queremos animar y cómo.

La idea que tengo es que el icono tenga transparencia 0 y un tamaño muy pequeño.

Así que pensé en animar la opacity, width y height del logo. La opacity de la imagen pasará de un valor 0 (transparente) a 1 (totalmente opaco) así como su width/height que pasaremos de 0 a 200 (estos valores los modificaremos según la imagen incrustada)

opacity: 0 a 1 | widht: 0 a 200 | height: 0 a 200

Para ello iremos a nuestro controlador y definiremos las variables que queremos controlar.

Si recordamos en los StatefulWidgets siempre solemos declarar nuestros valores como : String, int, double, List … Nosotros a partir de ahora los integraremos como valores reactivos que van a ir cambiando según nuestras necesidades o lógica implementada.

En este caso vamos a necesitar 3 valores que iremos modificando:

  • Opacity que en nuestro controlador la llamarĂ© opacityAnim
  • Width de la imagen que llamarĂ© widthAnim
  • Height de la imagen que llamarĂ© heightAnim
RxDouble widthAnim = 0.0.obs;
RxDouble heightAnim = 0.0.obs;
RxDouble opacityAnim = 0.0.obs;

Como vemos, los tres valores los definimos con un valor por defecto 0.0.obs, ya que a partir de ahora van a ser valores observables y podremos reaccionar a sus cambios como un stream.

Es por eso que definimos el tipo de variable con un Rx como prefijo y tenemos muchĂ­simas clases de ellas como por ejemplo:

  • RxInt
  • RxDouble
  • RxString
  • RxBool
  • RxList
  • RxInterface
  • RxStatus
  • RxMap
  • …

Ya hemos definido el valor inicial de cada observable pero no le hemos dicho en ningĂşn momento que aumente su valor segĂşn nuestras necesidades.

Para ello, añadiremos el método onReady() en nuestro controlador y le diremos qué valor queremos que actualice cada una de nuestras variables, una vez el componente esté listo.

TeĂłricamente, solo deberĂ­amos cambiar el valor fijo de nuestra screen y sustituirlo por cada una de las variables del SplashController.

Como la página la habíamos definido como un:

class SplashScreen extends GetWidget<SplashController> {}

Y ya vemos que tenemos su controlador referenciado, podemos acceder a Ă©l simplemente llamando a controller.

AsĂ­ que, en el AnimatedController vamos a suplir los valores por nuestra variables y para acceder a esos valores es tan simple como escribir:

controller.widthAnim.value
controller.heightAnim.value
controller.opacityAnim.value

Ahora solo nos queda reiniciar la aplicación. Y vemos que el resultado es la pantalla en blanco, no aparece y no se anima nada… ¿Qué puede ser?

Para que los widgets modifiquen su estado, los hemos de envolver en algún tipo de widget para que haga que la reactividad tenga su magia. Podréis observar que suelo usar mucho el Obx(), ya que es la manera de que solo repinte el Widget que cambia su estado.

Y nos beneficiará el momento que queramos trabajar con más de un Controller en la misma página.

Lo Ăşnico que debemos hacer es envolver al AnimatedContainer dentro de un Obx() tal y como os muestro a continuaciĂłn:

Obx(
() => AnimatedContainer(
// Use the properties stored in the State class.
width: controller.widthAnim.value,
height: controller.widthAnim.value,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
),
// Define how long the animation should take.
duration: Duration(seconds: 1),
// Provide an optional curve to make the animation feel smoother.
curve: Curves.fastOutSlowIn,
child: Opacity(
child: Hero(
child: Image.asset('assets/images/ecommerce.png'),
tag: 'imageHero',
),
opacity: controller.opacityAnim.value,
),
),
)

Ya lo tenemos todo listo, hacemos un Restart y voilá!!!

GetBuilder, GetX, Obx, ¿Cuál elegir?

GetBuilder

  • Al mantener estado por un breve tiempo. Lo que básicamente significa Ăşsalo donde quiera que uses setState.
  • Si el rendimiento es la máxima prioridad. El estado se comparte entre los constructores y no se consume mucha RAM.
  • Si no deseas trabajar con streams.

GetX

  • Cuando quieras todo el pontencial de la programaciĂłn reactiva.
  • Vuelve a dibujar el widget solo cuando el valor de la variable se cambia. Si el valor de una variable se cambia de “Flutter” a “Flutter”, entonces los widgets no se volverán a dibujar.
  • Si no deseas crear una instancia de controladores.

Obx

  • Si prefieres una sintaxis más simple.
  • Si vas a usar varios controladores en el mismo widget. Obx no necesita un tipo, por lo que se puede usar con cualquier nĂşmero de controladores.
  • Cuando uses Bindings , yo siempre prefiero Obx.

Ahora nos tocará preparar nuestro Login y Register Page

Github repo: https://github.com/luiggibcn/bpf/tree/splash-animation

Nos vemos pronto!!!!

--

--

Christian Llansola
Christian Llansola

Written by Christian Llansola

Flutter developer, NodeJS, MongoDB, Laravel, Angular, UX/UI Designer and more interesting things like IoT, Elastic Stack…

No responses yet