Si quieres programar tu propia apli­ca­ción, no te faltarán opciones. Los kits de co­m­po­ne­n­tes listos para usar son muy populares por su facilidad de uso, pero los marcos de trabajo son una gran al­te­r­na­ti­va y facilitan el proceso de de­sa­rro­llo cada vez más. Una de las opciones más modernas es el kit de de­sa­rro­llo de software o SDK, por su sigla del inglés “software de­ve­lo­p­me­nt kit”, Flutter, de­sa­rro­lla­do por Google. Este marco de trabajo de código abierto permite de­sa­rro­llar apli­ca­cio­nes móviles de alto re­n­di­mie­n­to para iOS y Android, así como apli­ca­cio­nes web y de es­cri­to­rio en el lenguaje de Google Dart.

En este tutorial de Flutter en español, te enseñamos los pasos más im­po­r­ta­n­tes para empezar a utilizar el SDK de Google.

Aprender Flutter: ¿cuáles son los re­qui­si­tos?

Si quieres aprender a programar con Flutter, no necesitas co­no­ci­mie­n­tos previos de de­sa­rro­llo de apli­ca­cio­nes o de la web. Ni siquiera es im­pre­s­ci­n­di­ble que estés fa­mi­lia­ri­za­do con Dart, el lenguaje de Google. Si conoces la pro­gra­ma­ción orientada a objetos y conceptos básicos de pro­gra­ma­ción como variables, bucles y co­n­di­cio­nes, ya tienes una base su­fi­cie­n­te para trabajar con este marco.

En este tutorial de Flutter en español, te in­tro­du­ci­re­mos a la pro­gra­ma­ción con este kit de de­sa­rro­llo de software. Para ello, es­cri­bi­re­mos una apli­ca­ción sencilla que combina palabras de forma aleatoria y presenta estas co­m­bi­na­cio­nes al usuario. Ne­ce­si­ta­rás las he­rra­mie­n­tas básicas para programar con Flutter: el SDK Flutter y un editor. El primero está di­s­po­ni­ble para Windows, macOS y Linux, y puedes de­s­ca­r­gar­lo en la página web oficial de Flutter.

En lo que respecta al editor, puedes elegir el que quieras. Sin embargo, para una ex­pe­rie­n­cia óptima de usuario con co­m­ple­ción au­to­má­ti­ca de código, resaltado de sintaxis y co­m­pa­ti­bi­li­dad con la de­pu­ra­ción y la edición de widgets, Google re­co­mie­n­da utilizar el editor de código Android Studio, para el que la empresa también ofrece un plugin oficial de Flutter. Por esto, en nuestro tutorial sobre Flutter uti­li­za­mos Android Studio. Después de instalar este entorno de de­sa­rro­llo op­ti­mi­za­do para el de­sa­rro­llo de apli­ca­cio­nes de Android, configura el plugin de Flutter:

  1. En la barra del menú, ve a “File”.
  2. Haz clic en “Settings” y, luego, se­le­c­cio­na “Plugins”.
  3. Escribe “Dart” en la línea de búsqueda y haz clic en “Install” en el resultado sugerido para instalar la extensión para el lenguaje de pro­gra­ma­ción Dart.
  4. Confirma el uso de la extensión a terceros con “Accept”.
  5. Repite el pro­ce­di­mie­n­to con el término “Flutter” y pulsa “Restart IDE” después de la in­s­ta­la­ción para aplicar los cambios.
Nota

Como al­te­r­na­ti­va a Android Studio, Google re­co­mie­n­da las apli­ca­cio­nes GNU Emacs, Visual Studio Code y IntelliJ IDEA, para las que también hay un plugin de Flutter oficial.

Paso 1: crea tu primera apli­ca­ción con Flutter

Después de instalar Flutter y el entorno de de­sa­rro­llo (o editor) deseado, puedes crear tu primera apli­ca­ción en Flutter. Como ya hemos me­n­cio­na­do, en este tutorial de Flutter uti­li­za­mos Android Studio, por lo que ahora la­n­za­re­mos el IDE para este propósito. Abre la pestaña “File”, se­le­c­cio­na “New” y, luego, “New Flutter Project” para iniciar un nuevo proyecto basado en el marco.

Se­le­c­cio­na “Flutter Ap­pli­ca­tion” como tipo de proyecto deseado y pulsa “Next”. En el menú de co­n­fi­gu­ra­ción, define ahora un título de trabajo y la ubicación local donde se guardará la apli­ca­ción. También puedes añadir una de­s­cri­p­ción del proyecto. En la línea “Flutter SDK path”, indica la ruta al marco de Flutter instalado.

Cuando termines, haz clic en Finalizar” para crear la nueva apli­ca­ción en Flutter. En el archivo main.dart, el archivo de trabajo básico de proyectos, que también usamos en este tutorial de Flutter, escribe el siguiente código para que la apli­ca­ción presente un simple mensaje de “Hello World” (puedes borrar el código existente en el archivo main.dart):

// Copyright 2018 The Flutter team. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:Flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
	@override
	Widget build(BuildContext context) {
		return MaterialApp(
			title: 'Welcome to Flutter',
			home: Scaffold(
				appBar: AppBar(
					title: Text('Welcome to Flutter'),
				),
				body: Center(
					child: Text('Hello World'),
				),
			),
		);
	  }
}

Una vez hayas insertado el fragmento, puedes ejecutar esta primera versión de tu propia apli­ca­ción. En Android Studio, se­le­c­cio­na la máquina virtual co­rre­s­po­n­die­n­te (en “Flutter Device Selection”) y, luego, pulsa el botón de ejecución (“Run main.dart”):

Nota

Para pre­vi­sua­li­zar una apli­ca­ción en Android Studio, se debe instalar una instancia de la pla­ta­fo­r­ma de destino deseada. De lo contrario, no podrás se­le­c­cio­nar un di­s­po­si­ti­vo de prueba virtual para probar la apli­ca­ción en “Flutter Device Selection”. Para añadir una apli­ca­ción, se­le­c­cio­na los elementos de menú “Tools” y “AVD Manager”. Fi­na­l­me­n­te, se­le­c­cio­na “Create virtual device” e instala el di­s­po­si­ti­vo virtual de tu elección. Puedes encontrar in­s­tru­c­cio­nes de­ta­lla­das para crear y ad­mi­ni­s­trar di­s­po­si­ti­vos virtuales en Android Studio en el foro de de­sa­rro­lla­do­res de Android.

El primer arranque o de­pu­ra­ción de la apli­ca­ción llevará algún tiempo, por lo que debes tener paciencia, antes de ver el mensaje de bie­n­ve­ni­da en la pantalla del entorno de prueba.

Paso 2: integrar un paquete externo

Después de crear una apli­ca­ción simple en el primer paso del tutorial de Flutter, ahora la am­plia­re­mos con un paquete externo. Para ser más precisos, in­clui­re­mos un paquete de palabras en nuestro proyecto, con el objetivo de diseñar una apli­ca­ción que combine palabras de forma aleatoria. Como ejemplo, uti­li­za­mos el paquete de código abierto “english_words” (con licencia del MIT), que puedes encontrar, al igual que muchos otros paquetes de código abierto, en la pla­ta­fo­r­ma pub.dev. Este paquete contiene más de 5000 de las palabras más comunes en inglés, lo que lo hace ideal para los pro­pó­si­tos de este tutorial sobre Flutter.

Las apli­ca­cio­nes de Flutter utilizan el archivo pubspec.yaml para gestionar paquetes y de­pe­n­de­n­cias. Accede a este archivo y añade una entrada para el paquete de idiomas a la lista de de­pe­n­de­n­cias (asegúrate de tener la más ac­tua­li­za­da, en este caso, 3.1.5):

dependencies:
	Flutter:
		sdk: Flutter
	cupertino_icons: ^0.1.2
english_words: ^3.1.5

A co­n­ti­nua­ción, ejecuta el comando “Flutter pub get”. Android Studio dispone incluso de un botón llamado “Pub get” para ello.

Vuelve al archivo de trabajo principal main.dart e importa el paquete de idioma:

import 'package:Flutter/material.dart';
import 'package:english_words/english_words.dart';

Escribe también la siguiente línea en el código de la apli­ca­ción:

final wordPair = WordPair.random();

Para terminar, sustituye la entrada child, que es re­s­po­n­sa­ble de la salida del texto “Hello World”, por la siguiente entrada:

child: Text(wordPair.asPascalCase),

Con cada ejecución del nuevo código de la apli­ca­ción, obtendrás un par de palabras en inglés generadas al azar.

Paso 3: añadir un widget de estado

Los widgets sin estado (stateless widgets), tal y como se han utilizado hasta ahora en este tutorial de Flutter de Google, no se pueden modificar. Este tipo de widget no puede cambiarse de estado mientras se ejecuta la apli­ca­ción, por lo que no es posible re­es­cri­bi­r­lo si la apli­ca­ción está en marcha. En cambio, los widgets de estado (stateful widgets) sí que pueden cambiar de estado incluso mientras la apli­ca­ción se está eje­cu­ta­n­do, por lo que no es necesario haberlo de­te­r­mi­na­do al ejecutar la apli­ca­ción. Si quieres añadir in­ter­ac­ti­vi­dad a los elementos de tu apli­ca­ción en Flutter, ne­ce­si­ta­rás widgets de estado.

Nota

Los widgets de Flutter siempre son de o sin estado. Entre los ejemplos típicos para co­m­po­ne­n­tes sin estado, están los iconos, los botones o los módulos de texto. Entre los ejemplos típicos de widgets de estado simple, están las casillas de ve­ri­fi­ca­ción, los fo­r­mu­la­rios o los re­gu­la­do­res de­s­li­za­n­tes.

Ahora vamos a integrar un widget in­ter­ac­ti­vo en nuestra apli­ca­ción. Se requieren al menos dos clases para im­ple­me­n­tar­lo: por una parte, una clase Sta­te­fu­l­Wi­d­get, que a su vez genera una instancia de la clase State.

En primer lugar, creamos una clase de estado mi­ni­ma­li­s­ta llamada “Ra­n­do­m­Wo­r­d­s­S­ta­te” añadiendo el siguiente código al final de main.dart:

class RandomWordsState extends State<randomwords> {</randomwords>
	// TODO Add build() method
}

En este caso, la clase genérica de estado se asigna ex­pre­sa­me­n­te para su uso con el widget “Ra­n­do­m­Wo­r­ds”. El propio widget de estado se escribe en el archivo main.dart en el siguiente paso mediante la siguiente entrada (en el código, antes de la clase “Ra­n­do­m­Wo­r­d­s­S­ta­te”):

class RandomWords extends StatefulWidget {
	@override
	RandomWordsState createState() => RandomWordsState();
}

Al ejecutar este nuevo código de la apli­ca­ción, Flutter te indicará que ac­tua­l­me­n­te no hay ninguna función build() definida para “Ra­n­do­m­Wo­r­d­s­S­ta­te”.

En el fragmento insertado de la clase State, sigue cubriendo una posición decisiva el co­me­n­ta­rio del marcador de posición “//TODO Add build() method”, que ahora se sustituye por el código de la función build():

class RandomWordsState extends State<randomwords> {</randomwords>
	@override
	Widget build(BuildContext context) {
		final wordPair = WordPair.random();
		return Text(wordPair.asPascalCase);
	}
}

Para terminar, elimina la línea “final wordPair = WordPair.random();” de la clase MyApp y sustituye la entrada child “child: Text(wordPair.as­Pa­s­ca­l­Ca­se),” por “child: Ra­n­do­m­Wo­r­ds(),”.

Al ejecutar este nuevo código, el di­s­po­si­ti­vo de prueba virtual debe re­pro­du­cir un par de palabras como antes, pero ahora se basa en un widget de estado que permite la in­ter­ac­ción del usuario.

Paso 4: crear una lista de de­s­pla­zaie­n­to sin fin

Para ofrecer un primer ejemplo de un widget de Flutter in­ter­ac­ti­vo, am­plia­re­mos un poco nuestra apli­ca­ción en la última parte de este tutorial de Flutter de Google: en concreto, se adaptará la clase “Ra­n­do­m­Wo­r­d­s­S­ta­te” para que re­pre­se­n­te no solo pares de palabras in­di­vi­dua­les, sino una lista in­te­r­mi­na­ble de pares de palabras que el usuario pueda consultar. Además, se deberán guardar los pares de palabras ya sugeridos (para evitar entradas du­pli­ca­das) y se aumentará el tamaño de fuente de los re­su­l­ta­dos.

Empieza por los dos últimos puntos (guardar los re­su­l­ta­dos pre­se­n­ta­dos y pe­r­so­na­li­zar la fuente) in­clu­ye­n­do una lista de _su­g­ge­s­tio­ns y una variable _bi­g­ge­r­Fo­nt:

class RandomWordsState extends State<randomwords> {</randomwords>
	final _suggestions = <wordpair>[];</wordpair>
	final _biggerFont = const TextStyle(fontSize: 18.0);
}

Luego, en la misma clase "Ra­n­do­m­Wo­r­d­s­S­ta­te", añade la co­rre­s­po­n­die­n­te función _bui­l­d­Su­g­ge­s­tio­ns():

Widget _buildSuggestions() {
	return ListView.builder(
		padding: const EdgeInsets.all(16.0),
		itemBuilder: (context, i) {
			if (i.isOdd) return Divider();
			final index = i ~/ 2;
			if (index >= _suggestions.length) {
			_suggestions.addAll(generateWordPairs().take(10));
			}
			return _buildRow(_suggestions[index]);
		});
}

La función mostrada añade varias ca­ra­c­te­rí­s­ti­cas a la apli­ca­ción: entre otras cosas, se integra la lista de pares de palabras (List.View), que también se vuelve más clara mediante una línea divisoria de un píxel. Además, se indica que se muestren otras diez su­ge­re­n­cias (línea: _su­g­ge­s­tio­ns.addAll) cuando el usuario llegue al final de la lista.

Un co­m­po­ne­n­te básico del widget ampliado es también la función _buildRow(), que se llama una vez por cada par de palabras y presenta los pares como ListTitle. Por lo tanto, im­ple­me­n­ta­re­mos esta función en el próximo paso:

Widget _buildRow(WordPair pair) {
	return ListTile(
		title: Text(
			pair.asPascalCase,
			style: _biggerFont,
		),
	);
}

Se debe indicar al método build() ,que im­ple­me­n­ta­mos cuando generamos el widget de estado (paso 3), que debe usar la función bui­l­d­Su­g­ge­s­tio­ns(). Por lo tanto, hay que sustituir el contenido anterior del método por el siguiente código:

@override
Widget build(BuildContext context) {
	return Scaffold(
		appBar: AppBar(
			title: Text('Word Generator'),
		),
		body: _buildSuggestions(),
	);
}

Por último, actualiza el método build() también en la clase MyApp cambiando el title y de­fi­nie­n­do en la entrada de inicio que es un widget de Ra­n­do­m­Wo­r­ds:

title: 'Word Generator',
home: RandomWords(),

Cuando vuelvas a ejecutar el código, la apli­ca­ción se ejecutará con el nuevo nombre “Word Generator”. Además, se pre­se­n­ta­rá toda una lista de co­m­bi­na­cio­nes de palabras y podrás ir bajando para ver más re­su­l­ta­dos.

Tutorial de Flutter: resumen

En este tutorial de Flutter de Google, has aprendido los conceptos básicos más im­po­r­ta­n­tes para trabajar con Flutter y has podido apli­car­los en una sencilla apli­ca­ción de ejemplo. Por supuesto, puedes de­sa­rro­llar apli­ca­cio­nes mucho más de­ta­lla­das y complejas en Flutter, así como puedes pe­r­so­na­li­zar el diseño una vez te hayas fa­mi­lia­ri­za­do con el marco.

Para terminar, te pre­se­n­ta­mos el código completo de la apli­ca­ción de ejemplo de­sa­rro­lla­da para Android en el archivo main.dart:

import 'package:english_words/english_words.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
	@override
	Widget build(BuildContext context) {
		return MaterialApp(
			title: 'Word Generator',
			home: RandomWords(),
		);
	}
}
class RandomWords extends StatefulWidget {
	@override
	RandomWordsState createState() => RandomWordsState();
}
class RandomWordsState extends State<randomwords> {</randomwords>
	final _suggestions = <wordpair>[];</wordpair>
	final _biggerFont = const TextStyle(fontSize: 18.0);
	@override
	Widget build(BuildContext context) {
		return Scaffold(
			appBar: AppBar(
				title: Text('Word Generator'),
			),
			body: _buildSuggestions(),
		);
}
Widget _buildSuggestions() {
		return ListView.builder(
			padding: const EdgeInsets.all(16.0),
			itemBuilder: (context, i) {
				if (i.isOdd) return Divider();
				final index = i ~/ 2;
				if (index >= _suggestions.length) {
				_suggestions.addAll(generateWordPairs().take(10));
				}
				return _buildRow(_suggestions[index]);
			});
}
Widget _buildRow(WordPair pair) {
		return ListTile(
			title: Text(
				pair.asPascalCase,
				style: _biggerFont,
			),
		);
	}
}
Ir al menú principal