Flutter Widgets — qué es, árbol de widgets y build

Autor: IT Sectr Publicado: 2026-02-21 Tiempo de lectura: 8 min

Flutter Widgets — los componentes básicos de la interfaz de usuario en el framework Google Flutter, lanzado en la versión estable 1.0 en diciembre de 2018. En Flutter, todo es un widget: desde pantallas y botones hasta márgenes y alineación. Los widgets forman un árbol (widget tree) que Flutter renderiza en su propio motor Skia/Impeller, sin usar componentes nativos de la plataforma. Según Google I/O (2025), Flutter se utiliza en más de 500 000 aplicaciones en Google Play y App Store. La arquitectura de Flutter divide los widgets en StatelessWidget (inmutables) y StatefulWidget (con estado mutable mediante un objeto State).

Puntos Clave

  • Flutter Widgets — todos los elementos de UI en Flutter: desde pantallas y botones hasta márgenes y alineación; el framework no utiliza componentes nativos de la plataforma.
  • StatelessWidget — un widget sin estado mutable; muestra datos pasados a través del constructor y no cambia después del build.
  • StatefulWidget — un widget con estado mutable almacenado en un objeto State separado que sobrevive a los rebuilds.
  • Árbol de widgets (widget tree) — una jerarquía de widgets que describe la UI; Flutter lo transforma en Element Tree y Render Tree para el renderizado.
  • BuildContext — el contexto de construcción que proporciona acceso a la posición del widget en el árbol, el tema, MediaQuery e InheritedWidget.

¿Qué son los Flutter Widgets?

Flutter Widgets — todos los elementos de UI en el framework Flutter, implementados como clases Dart inmutables. Un widget es la configuración de un elemento de UI: su tamaño, color, posición y manejadores de eventos. A diferencia de Android (XML + View) o iOS (Storyboard + UIView), Flutter no usa componentes nativos — todo se dibuja con el motor Skia (Android/iOS/Linux) o Impeller (iOS/macOS) en un Canvas. Esto garantiza una apariencia consistente en todas las plataformas sin diferencias de plataforma. Flutter incluye dos conjuntos de widgets: Material Widgets (Google Material Design 3 para Android/web) y Cupertino Widgets (Apple HIG para iOS/macOS). El desarrollador puede combinar ambos conjuntos en una misma aplicación. Cada widget tiene un método build() que devuelve un widget hijo o una composición de ellos — así se construye el árbol de widgets.

Los tres árboles de Flutter

Flutter opera con tres árboles: Widget Tree (configuración, creado por el desarrollador), Element Tree (asignación del widget a su posición en el árbol, gestionado por el framework) y Render Tree (objetos que calculan el layout y realizan el pintado). Un Widget crea un Element, que crea un RenderObject. El Element se reutiliza cuando cambia la configuración (rebuild) — este es el mecanismo de optimización de Flutter: si el tipo de widget y la key coinciden, el Element no se recrea, sino que se actualiza con la nueva configuración. Comprender los tres árboles es clave para optimizar el rendimiento de las aplicaciones Flutter.

StatelessWidget: widgets inmutables

StatelessWidget — un widget que no almacena estado interno. Recibe parámetros a través del constructor y los muestra sin posibilidad de cambio después del build. StatelessWidget es ideal para elementos estáticos: encabezados, iconos, avatares, listas con datos fijos. El método build() se llama una vez al crearse y cuando cambia el widget padre. Como StatelessWidget no tiene estado, no requiere un objeto State separado — build() se define directamente en la clase del widget.

dart
import 'package:flutter/material.dart';

class ProfileHeader extends StatelessWidget {
  final String name;
  final String avatarUrl;

  const ProfileHeader({super.key, required this.name, required this.avatarUrl});

  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        CircleAvatar(
          radius: 24,
          backgroundImage: NetworkImage(avatarUrl),
        ),
        const SizedBox(width: 12),
        Text(
          name,
          style: const TextStyle(
            fontSize: 18,
            fontWeight: FontWeight.bold,
          ),
        ),
      ],
    );
  }
}

ProfileHeader — un StatelessWidget que recibe name y avatarUrl a través del constructor. CircleAvatar muestra el avatar, Text muestra el nombre. El widget no puede cambiar estos valores después de crearse. Usar un constructor const (const ProfileHeader) permite a Flutter reutilizar la instancia del widget durante el rebuild del padre — una microoptimización recomendada para todos los StatelessWidget.

StatefulWidget: widgets con estado

StatefulWidget — un widget con estado mutable almacenado en un objeto State separado. El StatefulWidget en sí es inmutable, como StatelessWidget. La parte mutable se delega a State: State es un objeto que se crea una vez y sobrevive a múltiples rebuilds del widget. Cuando el estado cambia (setState()), Flutter llama a build() en el State, actualizando la UI. StatefulWidget se usa para elementos interactivos: contadores, campos de texto, casillas de verificación, animaciones, temporizadores.

dart
import 'package:flutter/material.dart';

class LikeButton extends StatefulWidget {
  const LikeButton({super.key});

  @override
  State<LikeButton> createState() => _LikeButtonState();
}

class _LikeButtonState extends State<LikeButton> {
  bool liked = false;
  int count = 42;

  void _toggleLike() {
    setState(() {
      liked = !liked;
      count += liked ? 1 : -1;
    });
  }

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: _toggleLike,
      child: Text(liked ? '♥ $count' : '♡ $count'),
    );
  }
}

LikeButton — un StatefulWidget con la clase State _LikeButtonState. Los campos liked y count son estado almacenado en State y no se reinician en el rebuild. setState() notifica a Flutter que la UI necesita reconstruirse. Flutter no recrea State en cada rebuild del padre — solo cuando cambia la configuración (key o tipo de widget). En IT Sectr, usamos StatelessWidget para la visualización y StatefulWidget para componentes interactivos, siguiendo el principio de minimizar StatefulWidget hasta los límites de la mutación.

Árbol de widgets: de Widget a RenderObject

Widget Tree — una estructura jerárquica de widgets que describe la UI de la aplicación. Flutter convierte el Widget Tree en un Element Tree: cada Widget crea un Element, que rastrea su posición en el árbol y su conexión con un RenderObject. El Render Tree realiza el layout (determinación de tamaños y posiciones) y el paint (renderizado). El Element es una capa de optimización clave: si el tipo de widget y la key no han cambiado durante un rebuild, el Element se reutiliza, actualizando la configuración sin recrear el RenderObject. Esto garantiza el rendimiento de Flutter a altas tasas de fotogramas (60/120 FPS).

dart
import 'package:flutter/material.dart';

class HomeScreen extends StatelessWidget {
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Widgets de Flutter')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const Icon(Icons.flutter_dash, size: 80),
            const SizedBox(height: 16),
            const Text(
              '¡Hola, Flutter!',
              style: TextStyle(fontSize: 24),
            ),
          ],
        ),
      ),
    );
  }
}

Árbol de widgets de HomeScreen: Scaffold → AppBar + Center → Column → [Icon, SizedBox, Text]. Scaffold es el widget raíz de layout de Material Design. Center centra su Column hijo. Column organiza los hijos verticalmente con alineación centrada (mainAxisAlignment.center). Flutter calcula el layout de arriba abajo (las constraints se pasan del padre) y los tamaños de abajo arriba (sizedByParent o sizing from children).

BuildContext: contexto de construcción y acceso al árbol

BuildContext — un descriptor de la posición del widget en el Element Tree. Cada método build() recibe un BuildContext, a través del cual el widget puede acceder a: MediaQuery (tamaño de pantalla, orientación, densidad de píxeles, safe area), Theme (MaterialThemeData o CupertinoThemeData), Navigator (pila de navegación), ScaffoldMessenger (SnackBar), InheritedWidget (paso de datos hacia abajo en el árbol). BuildContext no debe guardarse después de que build() termine ni usarse fuera de un contexto síncrono — esto provoca errores como “Scaffold.of() called with a context that does not contain a Scaffold”. En lugar de guardar el context, usa el widget Builder o el patrón InheritedWidget para acceder a los datos.

Key: identificación del widget en el árbol

Key — un parámetro opcional del constructor de cada widget (super.key). Key ayuda a Flutter a identificar un widget cuando cambia el orden o la cantidad de elementos en una lista. Sin key, Flutter compara los widgets por tipo y posición; al añadir un elemento en medio de una lista sin key, Flutter reutiliza el Element para el widget incorrecto, causando errores de estado (StatefulWidget) y problemas de animación. Usa ValueKey (identificador único) para listas, ObjectKey (basado en el objeto de datos), UniqueKey (garantizado único en cada rebuild — para recreación forzada).

Catálogo de widgets de Flutter: Material, Cupertino, Layout

Flutter SDK (versión estable 3.3+, Dart 3+) incluye más de 200 widgets integrados divididos en categorías: Layout (Row, Column, Stack, Container, Expanded, Flexible, Wrap, GridView, ListView, CustomScrollView), Material Design (Scaffold, AppBar, Card, Drawer, BottomNavigationBar, FloatingActionButton, TabBar, Chip, DataTable), Cupertino (CupertinoPageScaffold, CupertinoNavigationBar, CupertinoButton, CupertinoTabBar), Painting & Effects (Opacity, DecoratedBox, ClipRect, Transform, BackdropFilter, ShaderMask), Async (FutureBuilder, StreamBuilder) y Accessibility (Semantics, MergeSemantics, ExcludeSemantics). Los widgets de layout son la base de cualquier UI de Flutter: Row para secuencias horizontales, Column para verticales, Stack para elementos superpuestos, Container con BoxDecoration para decoración.

CategoríaWidgets clavePropósito
LayoutRow, Column, Stack, Container, Expanded, FlexiblePosicionamiento y dimensionamiento de hijos
MaterialScaffold, AppBar, Card, Drawer, FAB, TabBarComponentes UI de Material Design 3
CupertinoCupertinoPageScaffold, CupertinoNavigationBar, CupertinoButtonComponentes con estilo iOS
PaintingOpacity, ClipRect, Transform, DecoratedBox, BackdropFilterEfectos visuales y recorte
AsyncFutureBuilder, StreamBuilderCarga de datos asíncrona con estados de UI
AccessibilitySemantics, MergeSemanticsMarcado semántico para lectores de pantalla

Preguntas Frecuentes

¿En qué se diferencia StatelessWidget de StatefulWidget?

StatelessWidget no tiene estado interno — todos los datos se pasan a través del constructor y no cambian. StatefulWidget almacena el estado mutable en un objeto State separado que sobrevive a los rebuilds. El cambio de estado llama a setState(), y Flutter reconstruye la UI. Usa StatelessWidget para elementos inmutables; usa StatefulWidget para elementos interactivos.

¿Qué es BuildContext en Flutter?

BuildContext es un descriptor de la posición del widget en el Element Tree, pasado al método build(). A través del context, un widget accede a MediaQuery, Theme, Navigator, ScaffoldMessenger e InheritedWidget. BuildContext no debe guardarse después de que build() termine. Para acceder a datos, usa el widget Builder o InheritedWidget.

¿Necesito saber Dart para trabajar con Flutter?

Sí, Flutter usa Dart como su único lenguaje de programación. Dart es un lenguaje de tipado estático con null safety, sound null safety, extension methods y pattern matching. Para empezar, basta con conocimientos básicos de Dart: clases, funciones, async/await, colecciones. Dart se compila a código nativo (AOT) mediante Dart Native y a JavaScript (para web) mediante Dart2JS.

¿Flutter es solo para plataformas móviles?

No, Flutter soporta seis plataformas: iOS, Android, Web, macOS, Windows, Linux. Más del 90% del código es compartido entre todas las plataformas. Las adaptaciones de plataforma (cámara, sistema de archivos) se implementan mediante plugins o platform channels. Para escritorio, Flutter usa el shell de ventanas Flutter Desktop; para web, usa el motor CanvasKit (WebGL) o el renderizador HTML.

¿Cómo logra Flutter un rendimiento de 60 FPS?

Flutter logra 60/120 FPS mediante: su propio motor 2D (Skia/Impeller), la ausencia de un bridge nativo (a diferencia de React Native), tres árboles (Widget → Element → Render) con reutilización de Element cuando el tipo/key no cambian, un algoritmo de layout con un solo paso (constraints hacia abajo, sizes hacia arriba) y RepaintBoundary para aislar el repintado de áreas individuales de la pantalla.

Resumen

  • Flutter Widgets — todos los elementos de UI: desde Scaffold hasta SizedBox; Flutter los renderiza por sí mismo en Skia/Impeller, sin usar componentes nativos.
  • StatelessWidget — un widget sin estado; build() devuelve la UI basada en parámetros inmutables del constructor.
  • StatefulWidget — un widget con estado mutable en State; setState() desencadena el rebuild de la UI.
  • Tres árboles de Flutter: Widget (configuración) → Element (posición) → Render (layout + paint); Element se reutiliza por rendimiento.
  • BuildContext — la posición del widget en el árbol; acceso a MediaQuery, Theme, Navigator, InheritedWidget.
  • Material y Cupertino — dos conjuntos de widgets para Google Material Design 3 y Apple HIG respectivamente.
  • Key (ValueKey, ObjectKey, UniqueKey) — identificación del widget al cambiar el orden o la cantidad en una lista.

Desarrollaremos una aplicación móvil llave en mano

IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.

Discutir el proyecto

Lea también