Lista de tareas: Deslizar para eliminar
Parte de la sección Proyectos del Journey de Flutter de Coddy. Lección 6 de 36.
En un teléfono, eliminas una tarea terminada deslizándola hacia un lado. Envuelve cada fila en un Dismissible y Flutter hará el deslizamiento por ti:
Dismissible(
key: ObjectKey(task),
direction: DismissDirection.endToStart,
background: Container(color: Colors.red, ...),
onDismissed: (direction) => _deleteTask(task),
child: ListTile(...),
)La key le indica a Flutter cuál es cada fila, para que deslice la correcta hacia fuera. ObjectKey(task) la vincula a la tarea misma. endToStart significa deslizar hacia la izquierda, y background es lo que se muestra detrás de la fila mientras se desliza: rojo con un icono de eliminación a la derecha.
onDismissed se ejecuta cuando la fila desaparece de la pantalla. Tu tarea es quitar la tarea de la lista ahí, dentro de setState. Elimina la tarea misma, no una posición, para que se quite la correcta incluso si la lista cambia más adelante.
Desafío
IntermedioDesliza las tareas para quitarlas:
- añade un método
_deleteTask(Task task)que elimine la tarea dentro desetState - envuelve cada
ListTileen unDismissibleconkey: ObjectKey(task)que se deslice hacia la izquierda - su
backgroundes unContainerrojo con unIcons.deleteblanco a la derecha, a 24 píxeles del borde
Pruébalo tú mismo
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.teal),
),
home: const TodoScreen(),
);
}
}
class Task {
Task(this.title);
final String title;
bool done = false;
}
class TodoScreen extends StatefulWidget {
const TodoScreen({super.key});
@override
State<TodoScreen> createState() => _TodoScreenState();
}
class _TodoScreenState extends State<TodoScreen> {
final List<Task> _tasks = [Task('Buy milk'), Task('Walk the dog'), Task('Read a book')];
final _controller = TextEditingController();
int get _left => _tasks.where((task) => !task.done).length;
void _addTask() {
final title = _controller.text.trim();
if (title.isEmpty) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Type a task first')),
);
return;
}
setState(() {
_tasks.add(Task(title));
});
_controller.clear();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('My Tasks')),
body: Column(
children: [
Padding(
padding: const EdgeInsets.fromLTRB(16, 16, 16, 8),
child: Row(
children: [
Expanded(
child: TextField(
controller: _controller,
decoration: const InputDecoration(
labelText: 'New task',
border: OutlineInputBorder(),
),
),
),
const SizedBox(width: 8),
IconButton.filled(
onPressed: _addTask,
icon: const Icon(Icons.add),
),
],
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
child: Row(
children: [
Text(
_left == 1 ? '1 task left' : '$_left tasks left',
style: Theme.of(context).textTheme.titleSmall,
),
],
),
),
Expanded(
child: ListView.builder(
itemCount: _tasks.length,
itemBuilder: (context, index) {
final task = _tasks[index];
return ListTile(
leading: Checkbox(
value: task.done,
onChanged: (value) {
setState(() {
task.done = value!;
});
},
),
title: Text(
task.title,
style: task.done
? const TextStyle(
decoration: TextDecoration.lineThrough,
color: Colors.grey,
)
: null,
),
);
},
),
),
],
),
);
}
}
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Proyectos
1Proyecto: Lista de tareas
Lista de tareas: La lista de tareasLista de tareas: Añadir una tarea4Proyecto: Rastreador de hábitos
Rastreador de hábitos: Tus hábitosRastreador de hábitos: La semana2Proyecto: Cuestionario
Cuestionario: La preguntaCuestionario: Correcto o incorrectoPractica por tu cuenta: Compilador de Flutter online