Menu
CoddyTech

To-do List: Add a Task

Part of the Projects section of Coddy's Flutter journey. Lesson 2 of 36.

A to-do list you cannot add to is a poster. Put a field and a round add button above the list, in a Row.

The field gets a TextEditingController, so the add button can read what was typed. Adding is two steps: put a new Task on the list inside setState, so the list is drawn again, then clear the field for the next one:

void _addTask() {
  setState(() {
    _tasks.add(Task(_controller.text));
  });
  _controller.clear();
}

The list now shares the screen with the field. A ListView inside a Column needs an Expanded around it, so it takes the space that is left instead of asking for all of it.

IconButton.filled is an IconButton on a filled circle in the theme's color, the way a main action looks in Material 3.

challenge icon

Challenge

Medium

Add tasks from a field:

  • give the state a TextEditingController named _controller (and dispose it)
  • make the body a Column: first a Row in 16 pixels of padding with an Expanded TextField labelled New task and an IconButton.filled with Icons.add, then the list inside an Expanded
  • tapping the button adds the typed task at the end of the list and empties the field

Try it yourself

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;
}

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')];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('My Tasks')),
      body: ListView.builder(
        itemCount: _tasks.length,
        itemBuilder: (context, index) {
          final task = _tasks[index];
          return ListTile(
            title: Text(task.title),
          );
        },
      ),
    );
  }
}
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Projects

Practice on your own: Online Flutter compiler