Reactividad en Flutter

Este es el segundo tutorial de las serie Fundamentos de Flutter donde aprenderemos sobre el uso de un tipo de widget especial que se vuelve a renderizar después de sufrir un cambio de estado. Luego de este tutorial podrás crear aplicaciones que cambian la información de manera dinámica.

Índice

  1. Creando un StatefulWidget
  2. Botón flotante
  3. Columna y Fila
  4. SisedBox y Expanded
  5. OnPresed
  6. El método setState
  7. Agregar estilos a un texto
  8. Tu turno
  9. El código

1. Creando un StatefulWidget

Lo que necesitamos para que nuestra aplicación muestre widgets que se rendericen con los cambios es un StatefulWidget. Así que al crear nuestro widget tenemos que hacer que su clase extienda de StatefulWidget.

class MiWidget extends StatefulWidget{

    
    State<StatefulWidget> createState() {
    return _ContadorPageState();
  }
}

Al crear un StatefulWidget este necesita sobrescribir un createState que retorna un estado de nuestro StatefulWidget ( State<StatefulWidget> ).

Por este motivo también debemos crear este estado. Esta clase que crearemos extenderá de State<MiWidget>. Dentro de este estado es necesario sobrescribir el build que nos permitirá devolver el Scaffold donde diseñaremos nuestra aplicación.

// Nuestro widget
class MiWidget extends StatefulWidget{

  
  State<StatefulWidget> createState() {
    return _Estado();
  }
}

// El estado de nuestro widget
class _Estado extends State<MiWidget>{

  
  Widget build(BuildContext context) {
    return Scaffold(
        // Creando el Scaffold
    );
  }

}

Ahora para poder actualizar el estado de nuestro widget y hacer que este se renderice cada vez que cambie solo tenemos que llamar al método setState(). Por ejemplo dentro de la función onPressed, que se ejecuta al hacer click en el botón flotante ( FloatingActionButton ), colocamos el método setState(), como en el siguiente ejemplo.

Más adelante en este mismo tutorial aprendermos sobre el funcionamiento de FloatingActionButton.
floatingActionButton: FloatingActionButton(
  onPressed: () {
    // 1. Cambiamos algun dato que se muestra en algun widget
    // Por ejemplo puede ser una variable dentro de un widget Text
    conteo++;

    // 2. Solamente basta con llamar al método setState()
    // para que el widget se redibuje en la ejecucion.
    setState(() {
    });
  },
),

2. Botón flotante

Este es el típico botón redondo que seguramente viste en muchas aplicación. Es muy usado ya que forma parte de los componentes propios de material design.

En Flutter ya tenemos un Widget listo para este botón. Este es el widget es FloatingActionButton y generalmente se utiliza en la propiedad floatingActionButton del widget Scaffold. Como ya lo dijimos en un tutorial anterior Scaffold nos brinda la posibilidad de implementar los componentes de Material Desgin.

FloatingActionButton tiene una propiedad llamada child donde podemos colocar un widget hijo, que incluso podría ser un texto. Pero es conveniente utilizar un icono dentro del botón. Por ese motivo utilizaremos el widget Icon. Además tenemos la propiedad onPressed donde colocaremos la función que se ejecutará al presionar el botón.

FloatingActionButton(
    child: Icon(Icons.add),
    onPressed: (){
        print('Hola')
    }
)

Si queremos cambiar la posición por defecto de este botón tendremos que recurrir a la propiedad floatingActionButtonLocation del Scaffold.

floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
Si creamos multiples botones flotantes en una misma pantalla tendremos que darle a cada botón el parámetro heroTag con un valor en string que le de un nombre único a cada botón.

3. Columna y Fila

Los widgets Column y Row son widgets que nos sirven para ordenar otros widgets en su interior en forma vertical u horizontal respectivamente. Estos widgets tienen una propiedad llamada child el cual recibe un arreglo con los widgets los cuales se colocarán en su interior. Además tienen una propiedad llamada mainAxisAlignment que permite alinear el contenido de su interior.

Column(
    // Nos permite alinear el contenido al centro de la columna
    mainAxisAlignment: MainAxisAlignment.center
    // Son los widgets que estarán dentro de este widget
    children: <Widget>[ Text('Hola'), Text('Mundo')
)

Además al tratarse de un Widget podemos utilizar un Column o Row dentro de una propiedad que acepte un widget como la propiedad child del floatingActionButton.

floatingActionButton: Row(
  children: <Widget>[FloatingActionButton(), FloatingActionButton()],
));

4. SisedBox y Expanded

El widget SisedBox() nos permite crear una caja para un widget en su interior pero podemos usar un SizeBox vacío para separar elementos de una columna o fila dado que tiene propiedades como width y height que nos permiten colocar el ancho y alto de este Widget.

SizedBox(width: 30.0)

Mientras que el widget Expanded() nos permite crear una caja que se expande hasta llenar el ancho necesario para llenar al widget padre. Este widget necesita de un child para funcionar correctamente. Para esto podemos usar un SixedBox sin parámetros.

Expanded(child: SizedBox())

5. OnPresed

Es la propiedad que tienen algunos widgets, la cual nos permite enviar un método para que pueda ser ejecutado cuando se haga click sobre el widget. Este método puede ser declarado ahí mismo usando una función anónima o un arrow function. Pero también podemos declararlo por separado y luego enviar una referencia de la función a la propiedad onPresed.

Tenemos que tener en cuanta que cuando queremos referenciar una función solo debemos enviarle el nombre de la función más no los paréntesis () al final del nombre de la función. Esto, porque al crear el widget solo necesita una referencia hacia la función para que sepa que ejecutar luego. Sin embargo, si colocamos los paréntesis estamos ejecutando la función al momento de referenciarlo.

// Propiedad onPresed
onPresed: ejecutar
...

void ejecutar(){
    // codigo
}

En caso de que nuestra función o clase devuelva un Widget, ahí si es necesario referenciar la función a la propiedad usando los paréntesis al final, porque necesitamos que se ejecute la función para obtener el widget que tiene que retornar.

propiedad: creandoWidget()

6. El método setState

Este método hará que nuestro statefulWidget se vuelva a renderizar, por lo que los cambios en los widgets definidos dentro de él se podrán visualizar. Solo basta con llamar a esta función dentro de alguna parte de nuestro statefulWidget para volver a renderizar este widget. Sin embargo, dentro de esta función se puede enviar una función que se ejecutará justo antes de volver a renderizar el satetfulWidget, por lo que ahí también podemos colocar aquí los cambios que queremos hacer.

setState(() {
    conteo++;
});

7. Agregar estilos a un texto

Para agregar estilos a nuestro texto solo bastan con usar la propiedad style del widget Text. Esta propiedad recibe un widget llamado TextStyle. Este widget tiene una serie de propiedades que nos permiten desde cambiar la fuente del texto hasta el color del mismo.

TextStyle( fontSize: 25 );

Incluso podríamos definir el widget TextStyle de manera separada para poder simplemente llamarlo cuando queramos cambiar el estilo de múltiples textos.

TextStyle estiloTexto = new TextStyle( fontSize: 25 );

Recuerda que en Dart el uso del new es opcional.

8. Tu turno

El código anterior solo nos permitirá crear un botón para aumentar el contador, pero usando los conceptos explicados anteriormente podemos ir agregando botones para lograr una aplicación como se muestra a continuación.

Cuando quieras puedes ver el código del proyecto terminado. Pero ándale inténtalo tu mismo!!

9. El código

El código fuente de la aplicación la podemos encontrar en el siguiente repositorio: github.com/andygeek/click_app