Después de haber creado nuestra app de ejemplo en la segunda parte, vamos a ver la estructura del proyecto que se ha generado y explicar los conceptos básicos que debemos saber antes de empezar a desarrollar nuestra app.
Estructura del proyecto
.dart_tool: El directorio .dart_tool, que es nuevo en Dart 2, es utilizado por pub y otras herramientas. Reemplaza el directorio .pub a partir de la versión 2.0.0-dev.32.0 SDK.
También contiene el archivo package_config.json que especifica las ubicaciones y versiones de los paquetes , así como cachés de compilación.
.idea: almacena un conjunto de archivos xml con configuración específica de cada proyecto.
android, ios, linux, macos & windows: contienen una aplicación completa respectivamente con todos los archivos correspondientes de cada plataforma. Siempre que se quiera implementar cualquier característica específica como por ejemplo, los permisos, debemos implementarla en estos directorios.
lib: es el directorio donde trabajaremos ya que contiene todo el código de la aplicación que estemos desarrollando.
test: directorio donde se escribirán las pruebas unitarias de nuestra app.
.gitignore: este fichero le dice a Git que archivos ignorar al enviar nuestro proyecto al repositorio.
.metadata, .packages & pubspec.lock: son ficheros generados por Flutter al crear el proyecto. Son utilizados por el framework para usos internos y normalmente no tendremos que editarlos.
analysis_options.yaml: este fichero contiene las opciones análisis del código
README.md: es un archivo markdown usa principalmente en el control de versiones para representar la información del proyecto en si.
Conceptos básicos
Como se dijo en el post previo, todo en Flutter, es un widget. No contiene HTML, CSS ni JavaScript.
Los widgets son solo pequeños fragmentos de interfaz de usuario que puede combinar para crear una aplicación completa.
Los widgets están anidados unos dentro de otros para crear la aplicación. Incluso la raíz de la aplicación es solo un widget.
Un widget puede mostrar algo, puede ayudar a definir el diseño, puede ayudar con el diseño o puede manejar la interacción.
En Flutter, todos los widgets extienden de 2 widgets básicos: Stateless y Statefull widget.
Stateless y Statefull widget
Stateless widget: como su nombre indica, es un widget sin estado. Usaremos este tipo de widget cuando tengamos que mostrar información que nunca cambiará.
Statefull widget: es un widget que maneja su propio estado y que puede ser modificado en cualquier momento. Para ello, este widget contiene su método setState() que usaremos para dicho fin.
Sabiendo esto, una buena práctica en Flutter es usar siempre que se pueda los widgets sin estados ya que al usar Statefull widget, cada vez que cambia el estado, se reconstruye dicho widget por lo que la carga de la aplicación es mayor.
Un claro ejemplo, lo tenemos en la aplicación que hemos generado.
Lo primero que nos encontramos en el fichero main.dart, es la función main() que es la encargada de ejecutar nuestra aplicación con el método runApp().
Seguidamente nos encontramos un Stateless widget que contiene información que no va a cambiar (no tiene estado). En este tipo de widget, debemos sobrescribir el método build() que toma un contexto (BuildContext) como parámetro y devuelve un widget donde diseñaremos la interfaz de nuestra pantalla.
Dentro de este widget, vemos que la home de nuestra aplicación será MyHomePage el cual vamos a ver que es un Statefull widget.
En esta página (widget) vemos un ejemplo básico de un contador que cambia, mediante el método setState() cada vez que presionamos sobre el Floating Action Button. En este tipo de widget, se sobreescribe el método createState() y devuelve una instancia del mismo widget que a su vez extenderá de State que toma como entrada el widget inicial. Es aquí donde se sobreescribe el método build() y nos devuelve el widget donde diseñaremos la interfaz de nuestra pantalla.
Diseño
A continuación vamos a ver cuales son los widgets principales que usaremos para maquetar nuestra aplicación. Existen multitud de ellos pero vamos a centrarnos en los más usados.
Por lo general, cada pantalla de nuestra aplicación partirá de un widget llamado Scaffold.
Scaffold: proporciona un marco que implementa la estructura de diseño visual de la propia pantalla. Nos proporciona una API para mostrar modales, snackbars y bottom sheets. El constructor de este widget nos proporciona las siguientes propiedades:
De todas ellas, nos centraremos en el body.
body es la propiedad mínima requerida por el Scaffold ya que contendrá todo el diseño de la pantalla. Cualquier widget que se muestre en el body, por defecto, estará alienado en la esquina superior izquierda.
Que todo esté alineado en ese punto, nos da una pista que necesitaremos de otros widgets para poder modificar la posición de los mismos. En este caso, hablaremos de Columns y Rows (Columnas y filas)
Columns: este widget organiza a sus elementos hijos en dirección vertical en la pantalla. En otras palabras, esperará un array de widgets secundarios. Si los widgets secundarios necesitan llenar el espacio vertical disponible, debemos envolver los widgets secundarios en un widget llamado Expanded().
Este widget no es desplazable y por lo tanto, los elementos secundarios que no se puedan mostrar en la pantalla no lo harán y se mostrará un error de layout. Si queremos evitar esto, deberemos usar el widget ListView().
Rows: este widget organiza a sus elementos hijos dirección horizontal en la pantalla. Al igual que el widget Columns, espera un array de widgets secundarios. Si los widgets secundarios necesitan llenar el espacio horizontal disponible, debemos envolver los widgets secundarios en widget llamado Expanded().
Podemos alinear los widgets secundarios tanto de Columns como Rows con ayuda de las propiedades que nos ofrece respectivamente y que veremos posteriormente cuando tengamos que usarlos.
Expanded: es un widget que, como su nombre indica, expande un hijo de Columns o Rows para que ocupe todo el espacio disponible en la pantalla.
ListView: es el widget mas usado para hacer que la pantalla sea desplazable. Al igual que con Columns, recibe un array de widgets secundarios que se irán mostrando uno detrás de otro.
Conclusiones
Esta parte ha sido la mas corta por ahora pero era necesaria para poder empezar, ahora sí, a desarrollar nuestra app.