---
title: 📋 Modificar listas
description: "## 📋 Unha lista que pode cambiar No Tema 3.2 aprendemos a mostrar listas utilizando `ListView` e `ListView.builder`. Ata agora, os elementos das listas estaban definidos no código e non podiamos engadir ou eliminar elementos desde a interface. Neste exemplo…"
url: "https://www.drodicio.com/docs/flutter/tema-5-navegacion/listas-e-cuadriculas/"
updated: "2026-10-12"
category: Tema 5. Interaccion, formularios e navegacion
---

# 📋 Modificar listas

## 📋 Unha lista que pode cambiar

No Tema 3.2 aprendemos a mostrar listas utilizando `ListView` e `ListView.builder`.

Ata agora, os elementos das listas estaban definidos no código e non podiamos engadir ou eliminar elementos desde a interface.

Neste exemplo imos crear unha lista de alumnos que permita:

- **Mostrar** os alumnos que temos gardados.
- **Engadir** un alumno escribindo o seu nome.
- **Eliminar** un alumno premendo unha icona.

Para conseguilo, gardaremos os nomes nunha lista dentro do `State` e utilizaremos `setState()` cada vez que a modifiquemos.

![Lista de alumnado con opcións para engadir e eliminar nomes](https://www.drodicio.com/wp-content/uploads/2026/10/listas.png)
Lista de alumnado con opcións para engadir e eliminar nomes

## 📝 Engadir e eliminar elementos dunha lista

En Dart podemos crear unha lista de nomes:

```dart
final _nomes = <String>['Xurxo', 'Iria'];
```

Neste caso, a lista contén dous alumnos: Xurxo e Iria.

Para **engadir un novo elemento**, utilizamos o método `add()`:

```dart
_nomes.add('Roi');
```

Agora a lista contén tres alumnos: Xurxo, Iria e Roi.

Para **eliminar un elemento**, podemos utilizar `removeAt()`, indicando a súa posición:

```dart
_nomes.removeAt(1);
```

Esta instrución elimina o elemento da posición `1`, é dicir, Iria.

Lembra que **as posicións dunha lista comezan en 0**:

| Posición (índice) | Nome |
| --- | --- |
| 0 | Xurxo |
| 1 | Iria |
| 2 | Roi |

Tamén podemos consultar cantos elementos ten unha lista mediante `length`:

```dart
_nomes.length
```

E comprobar se está baleira mediante `isEmpty`:

```dart
_nomes.isEmpty
```

> 💡 A palabra `final` impide substituír `_nomes` por outra lista, pero permite engadir ou eliminar elementos da lista existente.

## ➕ Engadir un alumno

Para engadir alumnos utilizaremos un `TextField` e un botón «Engadir».

O usuario escribirá un nome e, ao premer o botón, executarase o método `_engadir()`:

```dart
void _engadir() {
  final nome = _controlador.text.trim();

  if (nome.isEmpty) return;

  setState(() {
    _nomes.add(nome);
  });

  _controlador.clear();
}
```

O funcionamento é o seguinte:

1. **Lemos o nome** escrito no `TextField` mediante `_controlador.text`.
2. **Eliminamos os espazos** dos extremos utilizando `trim()`.
3. **Comprobamos se está baleiro** con `isEmpty`. Se é así, `return` remata o método e non engadimos nada.
4. **Engadimos o nome** á lista mediante `_nomes.add(nome)`.
5. **Actualizamos a pantalla** utilizando `setState()`.
6. **Limpamos o campo** mediante `_controlador.clear()` para poder escribir outro nome.

### 🔄 Por que necesitamos `setState()`?

Como vimos no Tema 3.3, `setState()` informa a Flutter de que cambiaron os datos que utiliza a interface e que debe reconstruíla.

Neste caso:

```dart
setState(() {
  _nomes.add(nome);
});
```

A instrución `add()` engade o novo alumno á lista, mentres que `setState()` permite que Flutter actualice a pantalla para mostrar o cambio.

**É importante distinguir as dúas operacións:** `add()` modifica os datos e `setState()` provoca a actualización da interface.

## ➖ Eliminar un alumno

Para eliminar un alumno necesitamos coñecer a súa posición na lista.

Por exemplo, podemos crear este método:

```dart
void _eliminar(int indice) {
  setState(() {
    _nomes.removeAt(indice);
  });
}
```

O parámetro `indice` indica a posición do alumno que queremos eliminar.

Se chamamos ao método con `_eliminar(0)`, eliminaremos o primeiro alumno da lista. Se utilizamos `_eliminar(1)`, eliminaremos o segundo.

Grazas a `setState()`, a pantalla actualizarase automaticamente para mostrar a lista sen ese alumno.

Con todo, **non é recomendable eliminar un alumno inmediatamente ao premer a icona**. Podemos evitar eliminacións accidentais preguntando primeiro ao usuario se realmente quere facelo.

## 💬 Confirmar a eliminación

Para pedir unha confirmación podemos utilizar un **`AlertDialog`**, unha pequena ventá que aparece sobre a pantalla e permite mostrar unha mensaxe con varios botóns.

Neste exemplo, cando o usuario prema a icona de eliminar, aparecerá unha pregunta con dúas opcións:

- **Cancelar:** pecha o diálogo sen eliminar o alumno.
- **Eliminar:** confirma que queremos eliminar o alumno.

![Diálogo de confirmación antes de eliminar un alumno](https://www.drodicio.com/wp-content/uploads/2026/10/eliminar_alumno.png)
Diálogo de confirmación antes de eliminar un alumno

### 🪟 Como mostramos un diálogo?

Para abrir un diálogo utilizamos `showDialog()`.

Por exemplo:

```dart
showDialog(
  context: context,
  builder: (contextoDialogo) => AlertDialog(
    title: const Text('Eliminar alumno?'),
    content: const Text('Queres eliminar este alumno?'),
    actions: [
      TextButton(
        onPressed: () => Navigator.pop(contextoDialogo, false),
        child: const Text('Cancelar'),
      ),
      TextButton(
        onPressed: () => Navigator.pop(contextoDialogo, true),
        child: const Text('Eliminar'),
      ),
    ],
  ),
);
```

Neste código:

- **`showDialog()`** abre o diálogo.
- **`builder`** constrúe o widget que queremos mostrar.
- **`AlertDialog`** define o contido da ventá.
- **`title`** establece o título.
- **`content`** establece a mensaxe.
- **`actions`** contén os botóns.

Para pechar o diálogo utilizamos `Navigator.pop()`, como vimos ao traballar coa navegación entre pantallas.

Neste caso, tamén devolvemos un valor:

```dart
Navigator.pop(contextoDialogo, false);
```

Pecha o diálogo devolvendo `false`, porque o usuario cancelou a operación.

```dart
Navigator.pop(contextoDialogo, true);
```

Pecha o diálogo devolvendo `true`, porque o usuario confirmou a eliminación.

> 💡 Utilizamos `contextoDialogo` para identificar o contexto do propio diálogo. Deste xeito, podemos pechalo desde os seus botóns.

### ⏳ Como esperamos a resposta do usuario?

Cando mostramos un diálogo, necesitamos esperar a que o usuario escolla unha opción antes de continuar coa eliminación.

Para iso utilizamos `async` e `await`:

- **`async`** indica que un método pode realizar operacións asíncronas.
- **`await`** permite esperar a que remate unha operación antes de continuar coas seguintes instrucións.

Por exemplo:

```dart
final confirmado = await showDialog<bool>(
  context: context,
  builder: (contextoDialogo) => AlertDialog(
    title: const Text('Eliminar alumno?'),
    content: const Text('Queres eliminar este alumno?'),
    actions: [
      TextButton(
        onPressed: () => Navigator.pop(contextoDialogo, false),
        child: const Text('Cancelar'),
      ),
      TextButton(
        onPressed: () => Navigator.pop(contextoDialogo, true),
        child: const Text('Eliminar'),
      ),
    ],
  ),
);
```

A instrución `await` espera a que se peche o diálogo. Cando isto sucede, gardamos a resposta na variable `confirmado`.

O resultado pode ser:

| Valor | Significado |
| --- | --- |
| `true` | O usuario premeu «Eliminar». |
| `false` | O usuario premeu «Cancelar». |
| `null` | O diálogo pechouse sen escoller ningunha opción. |

O tipo `<bool>` indica que esperamos unha resposta booleana (`true` ou `false`), aínda que tamén podemos recibir `null` se o diálogo se pecha sen responder.

### 🔍 Como comprobamos a resposta?

Unha vez pechado o diálogo, debemos comprobar se o usuario confirmou a eliminación.

Para iso utilizaremos:

```dart
if (!mounted || confirmado != true) return;
```

Esta condición comproba dúas cousas:

- **`!mounted`:** comproba se o `State` do widget xa non forma parte da interface.
- **`confirmado != true`:** comproba se o usuario non confirmou a eliminación.

O operador `||` significa **OU**, polo que se se cumpre algunha destas condicións, `return` remata o método e non eliminamos nada.

A propiedade `mounted` é importante porque, mentres esperamos a resposta do diálogo, podería suceder que a pantalla deixase de existir.

> 💡 Polo momento, abonda con saber que `mounted` evita intentar actualizar unha pantalla que xa non existe. Utilizámolo por seguridade antes de chamar a `setState()` despois dunha operación asíncrona.

Se a pantalla continúa activa e o usuario confirmou a eliminación, podemos eliminar o alumno mediante `removeAt()`.

Como o método utiliza `async` e non devolve un resultado útil, declarámolo como `Future<void>`.

## 🧪 Exemplo completo: lista de alumnos

Agora imos reunir todo o que aprendemos nunha aplicación que permita engadir e eliminar alumnos.

O programa utiliza:

- Un `TextField` para introducir o nome.
- Un botón para engadir novos alumnos.
- Un `ListView.builder` para mostrar a lista.
- Unha icona para eliminar cada alumno.
- Un `AlertDialog` para confirmar a eliminación.

![Lista de alumnado con opcións para engadir e eliminar nomes](https://www.drodicio.com/wp-content/uploads/2026/10/listas.png)
Lista de alumnado con opcións para engadir e eliminar nomes

> 🔗 DartPad:
>
>
>
> - [`https://dartpad.dev/?id=b74e8e0f06fd9db46c2cec2fa0575e8d`](https://dartpad.dev/?id=b74e8e0f06fd9db46c2cec2fa0575e8d).

[https://dartpad.dev/embed-inline.html?id=b74e8e0f06fd9db46c2cec2fa0575e8d](https://dartpad.dev/embed-inline.html?id=b74e8e0f06fd9db46c2cec2fa0575e8d)

### 🔍 Como se constrúe a lista?

A parte encargada de mostrar os alumnos é:

```dart
Expanded(
  child: _nomes.isEmpty
      ? const Center(child: Text('Non hai alumnos'))
      : ListView.builder(
          itemCount: _nomes.length,
          itemBuilder: (context, indice) {
            final nome = _nomes[indice];

            return ListTile(
              title: Text(nome),
              trailing: IconButton(
                tooltip: 'Eliminar $nome',
                icon: const Icon(Icons.delete),
                onPressed: () => _eliminar(indice),
              ),
            );
          },
        ),
),
```

Neste fragmento utilizamos varios elementos que xa coñecemos:

| Instrución | Para que serve? |
| --- | --- |
| `Expanded` | Permite que a lista ocupe o espazo dispoñible dentro da `Column`. |
| `_nomes.isEmpty` | Comproba se a lista está baleira. |
| `itemCount: _nomes.length` | Indica cantos alumnos hai na lista. |
| `itemBuilder` | Constrúe as filas da lista segundo se necesitan. |
| `_nomes[indice]` | Obtén o nome do alumno correspondente a esa posición. |
| `ListTile` | Mostra unha fila co nome e a icona de eliminar. |
| `onPressed: () => _eliminar(indice)` | Executa o método para eliminar o alumno seleccionado. |

Tamén utilizamos o **operador ternario `? :`**, que permite escoller entre dúas opcións segundo se cumpra unha condición:

```dart
_nomes.isEmpty
    ? const Center(child: Text('Non hai alumnos'))
    : ListView.builder(...)
```

Se a lista está baleira, mostramos a mensaxe «Non hai alumnos». En caso contrario, mostramos o `ListView.builder` cos alumnos.

### 🔄 Que sucede cando modificamos a lista?

Cando engadimos ou eliminamos un alumno, chamamos a `setState()`.

Flutter volve executar `build()` e actualiza a interface cos datos actuais.

Por exemplo, se inicialmente temos dous alumnos:

```dart
['Xurxo', 'Iria']
```

E engadimos «Roi»:

```dart
_nomes.add('Roi');
```

A lista pasa a conter tres alumnos:

```dart
['Xurxo', 'Iria', 'Roi']
```

Ao reconstruírse a interface, `itemCount` utiliza a nova lonxitude da lista e `ListView.builder` pode mostrar os tres alumnos.

> 💡 `ListView.builder` non engade nin elimina elementos por si mesmo. Limítase a construír as filas a partir dos datos que lle proporcionamos. Somos nós quen modificamos a lista mediante métodos como `add()`, `removeAt()` ou `remove()`.

## 🧪 Comproba o funcionamento

Executa a aplicación e realiza estas probas:

1. **Engade un alumno:** escribe «Roi» e preme «Engadir». Comproba que aparece na lista.
2. **Engade outro alumno:** escribe «Uxía» e comproba que tamén aparece.
3. **Intenta engadir un nome baleiro:** preme «Engadir» sen escribir nada. Non debería engadirse ningún elemento.
4. **Cancela unha eliminación:** preme a icona de eliminar dun alumno e escolle «Cancelar». O alumno debe continuar na lista.
5. **Confirma unha eliminación:** volve premer a icona e escolle «Eliminar». O alumno debe desaparecer.
6. **Elimina todos os alumnos:** comproba que aparece a mensaxe «Non hai alumnos».

> 💡 Os datos desta aplicación só se gardan na memoria mentres se executa. Se reiniciamos a aplicación, a lista volverá conter os alumnos definidos inicialmente no código. No Tema 3.6 aprenderemos a gardar información para conservala entre execucións.

O desenvolvemento máis completo de diálogos e seleccións queda para o Tema 3.7.

> 📚 Consulta:
>
>
>
> - [ListView.builder → `https://api.flutter.dev/flutter/widgets/ListView/ListView.builder.html`](https://api.flutter.dev/flutter/widgets/ListView/ListView.builder.html).
> - [showDialog → `https://api.flutter.dev/flutter/material/showDialog.html`](https://api.flutter.dev/flutter/material/showDialog.html).
