- 1

Desarrollo de Apps Multiplataforma con Flutter y Firebase
01:46 - 2

Instalación y configuración de XCode y simuladores iOS para Flutter
12:01 - 3

Personalización de Temas Claros y Oscuros en Aplicaciones iOS
11:01 - 4

Configuración de Splash Screen en iOS con XCode y Flutter
06:06 - 5

Registro y membresía en Apple Developer para publicar apps
02:20 quiz de Preparación del entorno iOS
Creación de Listados Dinámicos en Aplicaciones Flutter
Clase 25 de 30 • Curso de Flutter con Firebase
Contenido del curso
- 10

Implementación de Provider y Bloc en Flutter para Aplicaciones Financieras
06:24 - 11

Creación de Pantalla de Inicio de Sesión con Firebase y Bloc Listener
11:12 - 12

Creación y Validación de Formularios en Flutter con Firebase
17:44 - 13

Configuración de rutas en Flutter con GoRouter
15:46 - 14

Funcionalidad de Inicio y Cierre de Sesión con Firebase en Flutter
11:34 - 15

Implementación de Autenticación y Cierre de Sesión con Firebase
10:30
- 18

Clase para Gestión de Ingresos y Gastos en Firestore
16:44 - 19

Manejo de Estados y Eventos en Flutter con Bloc para Finanzas
09:57 - 20

Agregar transacciones en Firebase con Flutter Bloc
06:41 - 21

Eliminar Transacciones con Firebase en Flutter
05:29 - 22

Implementación de MultiProvider y MultiRepository en Flutter
06:06
- 23

Visualización de Datos en Dashboard con Block Builder
15:13 - 24

Integración de Gráficas y Estados en Aplicaciones Flutter
11:50 - 25

Creación de Listados Dinámicos en Aplicaciones Flutter
18:25 - 26

Configuración de Balance y Estados en Pantalla de Wallet
07:12 - 27

Lista de Transacciones en Aplicaciones Móviles
04:02 - 28

Agregar Transacciones en Firebase con Flutter y Bloc
10:55 - 29

Eliminar transacciones en aplicación con Firebase
03:57
La arquitectura de bloques en Flutter es una técnica poderosa para organizar y estructurar componentes reutilizables en tus aplicaciones. En esta segunda parte del desarrollo de nuestro block builder, exploraremos cómo implementar un listado categorizado según el tipo de datos, complementando la funcionalidad de gráficas que ya habíamos construido anteriormente.
¿Cómo implementar un block builder para mostrar listados categorizados?
Continuando con nuestro proyecto, ahora nos enfocaremos en la sección de "category list". Anteriormente teníamos un list builder simple, pero lo transformaremos en un block builder más robusto que pueda manejar diferentes estados y presentar la información de manera más organizada.
Para comenzar, necesitamos eliminar el list builder existente y reemplazarlo con nuestro block builder. Este componente necesitará acceso a las mismas instancias que hemos estado utilizando:
// Implementación del block builder para category list
builder(context, state) {
// Verificamos si los datos están cargando
if (state is TransactionLoading) {
return const CircularProgressIndicator();
}
// Verificamos si los datos ya están cargados
else if (state is TransactionLoaded) {
// Separamos los datos por categoría
final categoryData = _calculateCategoryTotals(state.transactions);
return ListView.builder(
itemCount: categoryData.length,
itemBuilder: (context, index) {
final category = categoryData.keys.elementAt(index);
final total = categoryData[category];
return Card(
color: Theme.of(context).primaryColorDark,
margin: const EdgeInsets.symmetric(vertical: 8),
child: ListTile(
title: Text(
category == 'income' ? 'Income' : 'Expense',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: Theme.of(context).colorScheme.foreground,
),
),
trailing: Text(
'\$${total.toString()}',
style: TextStyle(
fontSize: 16,
color: Theme.of(context).colorScheme.foreground,
),
),
),
);
},
);
}
// Verificamos si hay algún error
else if (state is TransactionError) {
return Text(state.message);
}
// Si no hay transacciones
else {
return Center(
child: Text('No transactions'),
);
}
}
¿Cómo calcular los totales por categoría?
Una parte fundamental de nuestro block builder es la función que calcula los totales por categoría. Esta función privada recibe todas las transacciones y las separa según su tipo (ingreso o gasto):
Map<String, double> _calculateCategoryTotals(List<IncomeExpenseModel> transactions) {
// Inicializamos el mapa con valores por defecto
Map<String, double> categoryTotals = {
'income': 0,
'expense': 0,
};
// Recorremos cada transacción y sumamos según su tipo
for (var transaction in transactions) {
final category = transaction.type;
categoryTotals[category] = (categoryTotals[category] ?? 0) + transaction.amount;
}
return categoryTotals;
}
Esta función es crucial porque:
- Inicializa categorías con valor cero para evitar errores si no hay datos.
- Itera sobre cada transacción para clasificarla según su tipo.
- Suma los montos a la categoría correspondiente.
- Retorna un mapa con los totales acumulados por categoría.
¿Cómo mostrar la información de manera atractiva?
Para presentar los datos de manera visualmente atractiva, utilizamos un ListView.builder que crea tarjetas para cada categoría:
ListView.builder(
itemCount: categoryData.length,
itemBuilder: (context, index) {
final category = categoryData.keys.elementAt(index);
final total = categoryData[category];
return Card(
color: Theme.of(context).primaryColorDark,
margin: const EdgeInsets.symmetric(vertical: 8),
child: ListTile(
title: Text(
category == 'income' ? 'Income' : 'Expense',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: Theme.of(context).colorScheme.foreground,
),
),
trailing: Text(
'\$${total.toString()}',
style: TextStyle(
fontSize: 16,
color: Theme.of(context).colorScheme.foreground,
),
),
),
);
},
)
Cada tarjeta contiene:
- Un título que muestra si es un ingreso o un gasto.
- Un valor que muestra el monto total de esa categoría.
- Estilos personalizados que siguen el tema de la aplicación.
¿Cómo manejar diferentes estados en nuestra interfaz?
Un aspecto importante de nuestra implementación es el manejo de diferentes estados. Esto proporciona una mejor experiencia de usuario al mostrar:
- Indicador de carga mientras se obtienen los datos.
- Listado categorizado cuando los datos están disponibles.
- Mensaje de error si algo sale mal.
- Mensaje informativo si no hay transacciones.
Este enfoque basado en estados es una práctica recomendada en Flutter, ya que permite que la interfaz responda adecuadamente a diferentes situaciones sin necesidad de lógica compleja en el widget principal.
La implementación completa de nuestro block builder nos permite tener una pantalla de "spending" funcional que muestra claramente los ingresos y gastos categorizados. El siguiente paso sería ajustar la barra de progreso para reflejar estos valores, completando así la funcionalidad de esta pantalla.
La arquitectura de bloques en Flutter no solo mejora la organización del código, sino que también facilita la reutilización de componentes y el manejo de estados complejos. Estas técnicas son fundamentales para desarrollar aplicaciones robustas y mantenibles a largo plazo.
¿Has implementado esta funcionalidad en tu aplicación? Comparte una captura de pantalla en los comentarios para ver tu progreso y discutir posibles mejoras o alternativas.