πŸŽ“Flutter TodoList tutorial

Overview

Todo List built with Flutter

Awesome Flutter

Built with Git Tutor

lesnitsky.dev GitHub stars Twitter Follow

This tutorial will walk you through the process of building of a simple todo-list with Flutter

Getting started

Make sure to complete flutter installation

First steps

Execute in your terminal

flutter create todo_list

First line is an import of material library provided by Flutter. This library is an implementation of various android components

πŸ“„ lib/main.dart

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

This function is an entry point of flutter application. It calls just runApp, but we can do more in this function (like making your application full-screen).

πŸ“„ lib/main.dart

  import 'package:flutter/material.dart';
+
+ void main() => runApp(MyApp());

Let's actually do this 😏

πŸ“„ lib/main.dart

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

- void main() => runApp(MyApp());
+ void main() {
+   SystemChrome.setEnabledSystemUIOverlays([]);
+   runApp(MyApp());
+ }

Every component in flutter is called widget. It could be either stateless (read - pure) or stateful (container for some state). Top-level app component should be a stateless components, so let's create one

πŸ“„ lib/main.dart

    SystemChrome.setEnabledSystemUIOverlays([]);
    runApp(MyApp());
  }
+
+ class MyApp extends StatelessWidget {}

Every widget should override build function. It returns a hierarchy of your layout widgets (Container, Padding, Flex, etc) or your stateful widgets which contain some business logic

πŸ“„ lib/main.dart

    runApp(MyApp());
  }

- class MyApp extends StatelessWidget {}
+ class MyApp extends StatelessWidget {
+   @override
+   Widget build(BuildContext context) {
+     return Container();
+   }
+ }

But in case of top-level App widget, it should return either CupertinoApp from 'package:flutter/cupertino.dart', or MaterialApp from 'package:flutter/material.dart'

We'll use material in this tutorial

πŸ“„ lib/main.dart

  class MyApp extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
-     return Container();
+     return MaterialApp();
    }
  }

Let's add title

πŸ“„ lib/main.dart

  class MyApp extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
-     return MaterialApp();
+     return MaterialApp(
+       title: 'Todo List',
+     );
    }
  }

Let's also make a Scaffold a home of our application

Scaffold is a helper class from material library which implements basic app layout (app bar, floating action button)

πŸ“„ lib/main.dart

    Widget build(BuildContext context) {
      return MaterialApp(
        title: 'Todo List',
+       home: Scaffold(
+       ),
      );
    }
  }

Now we need to add an application header which will display our app title

πŸ“„ lib/main.dart

      return MaterialApp(
        title: 'Todo List',
        home: Scaffold(
+         appBar: AppBar(title: Text('Todo List')),
        ),
      );
    }

And finally the body of our app is todolist itself. Let's just add this line and implement the class later

πŸ“„ lib/main.dart

        title: 'Todo List',
        home: Scaffold(
          appBar: AppBar(title: Text('Todo List')),
+         body: TodoList(),
        ),
      );
    }

Render list

Basic statefull widget will look like this

πŸ“„ lib/todo_list.dart

import 'package:flutter/material.dart';

class TodoList extends StatefulWidget {
  @override
  _TodoListState createState() => _TodoListState();
}

class _TodoListState extends State<TodoList> {
  @override
  Widget build(BuildContext context) {
    return Container();
  }
}

We also need to import our TodoList widget

πŸ“„ lib/main.dart

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

+ import 'package:todo_list/todo_list.dart';
+
  void main() {
    SystemChrome.setEnabledSystemUIOverlays([]);
    runApp(MyApp());

Now let's describe Todo entity as class

πŸ“„ lib/todo.dart

class Todo {
  Todo({this.title, this.isDone = false});

  String title;
  bool isDone;
}

and import it to TodoList

πŸ“„ lib/todo_list.dart

  import 'package:flutter/material.dart';
+ import 'package:todo_list/todo.dart';

  class TodoList extends StatefulWidget {
    @override

Now we need to extend our TodoList state and add a list of todos

πŸ“„ lib/todo_list.dart

  }

  class _TodoListState extends State<TodoList> {
+   List<Todo> todos = [];
+
    @override
    Widget build(BuildContext context) {
      return Container();

Let's use ListView to render our todo items.

πŸ“„ lib/todo_list.dart

  class _TodoListState extends State<TodoList> {
    List<Todo> todos = [];

+   _buildItem() {}
+
    @override
    Widget build(BuildContext context) {
-     return Container();
+     return ListView.builder(
+       itemBuilder: _buildItem,
+       itemCount: todos.length,
+     );
    }
  }

Now we're going to implement _buildItem which will be called each time todo has to be rendered

We'll use CheckboxListTile from material library as it has everything we need (checkbox indicating whether todo is completed and title)

πŸ“„ lib/todo_list.dart

  class _TodoListState extends State<TodoList> {
    List<Todo> todos = [];

-   _buildItem() {}
+   Widget _buildItem(BuildContext context, int index) {
+     final todo = todos[index];
+
+     return CheckboxListTile(
+     );
+   }

    @override
    Widget build(BuildContext context) {

Value indicates if list item should be checked

πŸ“„ lib/todo_list.dart

      final todo = todos[index];

      return CheckboxListTile(
+       value: todo.isDone,
      );
    }

Title is a widget which should be rendered in first row. Typically it is a Text widget

πŸ“„ lib/todo_list.dart

      return CheckboxListTile(
        value: todo.isDone,
+       title: Text(todo.title),
      );
    }

Finally we need to handle taps on every list item

πŸ“„ lib/todo_list.dart

      return CheckboxListTile(
        value: todo.isDone,
        title: Text(todo.title),
+       onChanged: (bool isChecked) {
+         _toggleTodo(todo, isChecked);
+       },
      );
    }

_toggleTodo implementation is pretty straightforward

πŸ“„ lib/todo_list.dart

  class _TodoListState extends State<TodoList> {
    List<Todo> todos = [];

+   _toggleTodo(Todo todo, bool isChecked) {
+     todo.isDone = isChecked;
+   }
+
    Widget _buildItem(BuildContext context, int index) {
      final todo = todos[index];

Let's try to add some mock todos and see if they are rendered correctly

πŸ“„ lib/todo_list.dart

  }

  class _TodoListState extends State<TodoList> {
-   List<Todo> todos = [];
+   List<Todo> todos = [
+     Todo(title: 'Learn Dart'),
+     Todo(title: 'Try Flutter'),
+     Todo(title: 'Be amazed'),
+   ];

    _toggleTodo(Todo todo, bool isChecked) {
      todo.isDone = isChecked;

Ok, everything is rendered correctly, but nothing happens when we tap on items, weird..

Let's add a debug print and see if the handler even called

πŸ“„ lib/todo_list.dart

    ];

    _toggleTodo(Todo todo, bool isChecked) {
+     print('${todo.title} ${todo.isDone}');
+
      todo.isDone = isChecked;
    }

Console shows items are checked, value isChecked is true, but checkbox is never rendered

The problem is that we modify our entities, but flutter has no idea this happened, so we need to call setState. (Hi there, react fans! 😏 )

πŸ“„ lib/todo_list.dart

    ];

    _toggleTodo(Todo todo, bool isChecked) {
-     print('${todo.title} ${todo.isDone}');
-
-     todo.isDone = isChecked;
+     setState(() {
+       todo.isDone = isChecked;
+     });
    }

    Widget _buildItem(BuildContext context, int index) {

Now we're good with rendering and updates, time to get rid of mock items and add some ui to add new todos.

Let's add a FloatingActionButton

πŸ“„ lib/main.dart

        home: Scaffold(
          appBar: AppBar(title: Text('Todo List')),
          body: TodoList(),
+         floatingActionButton: FloatingActionButton(
+           child: Icon(Icons.add),
+         ),
        ),
      );
    }

πŸ“„ lib/todo_list.dart

  }

  class _TodoListState extends State<TodoList> {
-   List<Todo> todos = [
-     Todo(title: 'Learn Dart'),
-     Todo(title: 'Try Flutter'),
-     Todo(title: 'Be amazed'),
-   ];
+   List<Todo> todos = [];

    _toggleTodo(Todo todo, bool isChecked) {
      setState(() {

Ok, but what should we do in onPressed? We need to access a state of TodoList and messing with children state directly from parent statelsess widget doesn't sound like a good idea

πŸ“„ lib/main.dart

          body: TodoList(),
          floatingActionButton: FloatingActionButton(
            child: Icon(Icons.add),
+           onPressed: () {
+             // 😒
+           },
          ),
        ),
      );

So let's just move Scaffold widget down to TodoList

πŸ“„ lib/main.dart

    Widget build(BuildContext context) {
      return MaterialApp(
        title: 'Todo List',
-       home: Scaffold(
-         appBar: AppBar(title: Text('Todo List')),
-         body: TodoList(),
-         floatingActionButton: FloatingActionButton(
-           child: Icon(Icons.add),
-           onPressed: () {
-             // 😒
-           },
-         ),
-       ),
+       home: TodoList(),
      );
    }
  }

πŸ“„ lib/todo_list.dart

      );
    }

+   _addTodo() {}
+
    @override
    Widget build(BuildContext context) {
-     return ListView.builder(
-       itemBuilder: _buildItem,
-       itemCount: todos.length,
+     return Scaffold(
+       appBar: AppBar(title: Text('Todo List')),
+       body: ListView.builder(
+         itemBuilder: _buildItem,
+         itemCount: todos.length,
+       ),
+       floatingActionButton: FloatingActionButton(
+         child: Icon(Icons.add),
+         onPressed: _addTodo,
+       ),
      );
    }
  }

Now we can show a dialog when user taps on FloatingActionButton

πŸ“„ lib/todo_list.dart

      );
    }

-   _addTodo() {}
+   _addTodo() {
+     showDialog(
+       context: context,
+       builder: (BuildContext context) {
+         return AlertDialog(
+           title: Text('New todo'),
+         );
+       },
+     );
+   }

    @override
    Widget build(BuildContext context) {

Dialog will contain a text input:

πŸ“„ lib/todo_list.dart

        builder: (BuildContext context) {
          return AlertDialog(
            title: Text('New todo'),
+           content: TextField(),
          );
        },
      );

and two action buttons: Cancel and Add

πŸ“„ lib/todo_list.dart

          return AlertDialog(
            title: Text('New todo'),
            content: TextField(),
+           actions: <Widget>[
+             FlatButton(
+               child: Text('Cancel'),
+             ),
+             FlatButton(
+               child: Text('Add'),
+             ),
+           ],
          );
        },
      );

Dialogs are not just overlays, but actually a routes, so to handle Cancel action we can just call .pop on Navigator of current context

πŸ“„ lib/todo_list.dart

            actions: <Widget>[
              FlatButton(
                child: Text('Cancel'),
+               onPressed: () {
+                 Navigator.of(context).pop();
+               },
              ),
              FlatButton(
                child: Text('Add'),

Now we need to access the value of a TextField to create a Todo To do this we need to create a TextEditingController

πŸ“„ lib/todo_list.dart

  class _TodoListState extends State<TodoList> {
    List<Todo> todos = [];

+   TextEditingController controller = new TextEditingController();
+
    _toggleTodo(Todo todo, bool isChecked) {
      setState(() {
        todo.isDone = isChecked;

and supply it to the TextField

πŸ“„ lib/todo_list.dart

        builder: (BuildContext context) {
          return AlertDialog(
            title: Text('New todo'),
-           content: TextField(),
+           content: TextField(controller: controller),
            actions: <Widget>[
              FlatButton(
                child: Text('Cancel'),

now in onPressed of Add action we can log the value of a TextField and clear it

πŸ“„ lib/todo_list.dart

              ),
              FlatButton(
                child: Text('Add'),
+               onPressed: () {
+                 print(controller.value.text);
+                 controller.clear();
+               },
              ),
            ],
          );

Finally let's actually create new todo and add it to the list of existing todos (don't forget to wrap the code with setState)

πŸ“„ lib/todo_list.dart

              FlatButton(
                child: Text('Add'),
                onPressed: () {
-                 print(controller.value.text);
-                 controller.clear();
+                 setState(() {
+                   final todo = new Todo(title: controller.value.text);
+
+                   todos.add(todo);
+                   controller.clear();
+
+                   Navigator.of(context).pop();
+                 });
                },
              ),
            ],

Tiny UX improvement: make keyboard pop automatically by passing autofocus: true to a TextField

πŸ“„ lib/todo_list.dart

        builder: (BuildContext context) {
          return AlertDialog(
            title: Text('New todo'),
-           content: TextField(controller: controller),
+           content: TextField(
+             controller: controller,
+             autofocus: true,
+           ),
            actions: <Widget>[
              FlatButton(
                child: Text('Cancel'),

Refactoring

TodoListis working, but todo_list.dart is kinda messy and hard to read. The most complex method is _addTodo, so let's start with rewriting it. It seems like we can move the AlertDialog to a separate widget, but we can't do this right now, as we rely on setState from parent widget. Instead we can pass a freshly created todo to a Navigator.pop

πŸ“„ lib/todo_list.dart

    }

    _addTodo() {
-     showDialog(
+     showDialog<Todo>(
        context: context,
        builder: (BuildContext context) {
          return AlertDialog(
              FlatButton(
                child: Text('Add'),
                onPressed: () {
-                 setState(() {
-                   final todo = new Todo(title: controller.value.text);
+                 final todo = new Todo(title: controller.value.text);
+                 controller.clear();

-                   todos.add(todo);
-                   controller.clear();
-
-                   Navigator.of(context).pop();
-                 });
+                 Navigator.of(context).pop(todo);
                },
              ),
            ],

In order to be able to receive the Todo in _addTodo method we need to make it async and await showDialog function result (which will be null in case it was dismissed and instance of Todo otherwise)

πŸ“„ lib/todo_list.dart

      );
    }

-   _addTodo() {
-     showDialog<Todo>(
+   _addTodo() async {
+     final todo = await showDialog<Todo>(
        context: context,
        builder: (BuildContext context) {
          return AlertDialog(

And move back the logic with state update

πŸ“„ lib/todo_list.dart

          );
        },
      );
+
+     if (todo != null) {
+       setState(() {
+         todos.add(todo);
+       });
+     }
    }

    @override

Now we don't have any dependencies on a parent widget, so we can extract AlertDialog to a separate widget

πŸ“„ lib/new_todo_dialog.dart

import 'package:flutter/material.dart';

import 'package:todo_list/todo.dart';

class NewTodoDialog extends StatelessWidget {
  final controller = new TextEditingController();

  @override
  Widget build(BuildContext context) {
    return AlertDialog(
      title: Text('New todo'),
      content: TextField(
        controller: controller,
        autofocus: true,
      ),
      actions: <Widget>[
        FlatButton(
          child: Text('Cancel'),
          onPressed: () {
            Navigator.of(context).pop();
          },
        ),
        FlatButton(
          child: Text('Add'),
          onPressed: () {
            final todo = new Todo(title: controller.value.text);
            controller.clear();

            Navigator.of(context).pop(todo);
          },
        ),
      ],
    );
  }
}

and use it inside TodoList

πŸ“„ lib/todo_list.dart

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

+ import 'package:todo_list/new_todo_dialog.dart';
+
  class TodoList extends StatefulWidget {
    @override
    _TodoListState createState() => _TodoListState();
  class _TodoListState extends State<TodoList> {
    List<Todo> todos = [];

-   TextEditingController controller = new TextEditingController();
-
    _toggleTodo(Todo todo, bool isChecked) {
      setState(() {
        todo.isDone = isChecked;
      final todo = await showDialog<Todo>(
        context: context,
        builder: (BuildContext context) {
-         return AlertDialog(
-           title: Text('New todo'),
-           content: TextField(
-             controller: controller,
-             autofocus: true,
-           ),
-           actions: <Widget>[
-             FlatButton(
-               child: Text('Cancel'),
-               onPressed: () {
-                 Navigator.of(context).pop();
-               },
-             ),
-             FlatButton(
-               child: Text('Add'),
-               onPressed: () {
-                 final todo = new Todo(title: controller.value.text);
-                 controller.clear();
-
-                 Navigator.of(context).pop(todo);
-               },
-             ),
-           ],
-         );
+         return NewTodoDialog();
        },
      );

Next step – extract todo list component

List istself could also be treated as stateless widget, state related logic could be handled by parent

So let's first rename TodoList to TodoListScreen

πŸ“„ lib/todo_list.dart

  import 'package:todo_list/new_todo_dialog.dart';

- class TodoList extends StatefulWidget {
+ class TodoListScreen extends StatefulWidget {
    @override
-   _TodoListState createState() => _TodoListState();
+   _TodoListScreenState createState() => _TodoListScreenState();
  }

- class _TodoListState extends State<TodoList> {
+ class _TodoListScreenState extends State<TodoListScreen> {
    List<Todo> todos = [];

    _toggleTodo(Todo todo, bool isChecked) {

rename file

πŸ“„ lib/todo_list_screen.dart => lib/todo_list.dart

and fix import

πŸ“„ lib/main.dart

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

- import 'package:todo_list/todo_list.dart';
+ import 'package:todo_list/todo_list_screen.dart';

  void main() {
    SystemChrome.setEnabledSystemUIOverlays([]);
    Widget build(BuildContext context) {
      return MaterialApp(
        title: 'Todo List',
-       home: TodoList(),
+       home: TodoListScreen(),
      );
    }
  }

Let's move list related logic to a separate stateless widget

πŸ“„ lib/todo_list.dart

import 'package:flutter/material.dart';

class TodoList extends StatelessWidget {
  _toggleTodo(Todo todo, bool isChecked) {
    setState(() {
      todo.isDone = isChecked;
    });
  }

  Widget _buildItem(BuildContext context, int index) {
    final todo = todos[index];

    return CheckboxListTile(
      value: todo.isDone,
      title: Text(todo.title),
      onChanged: (bool isChecked) {
        _toggleTodo(todo, isChecked);
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      itemBuilder: _buildItem,
      itemCount: todos.length,
    );
  }
}

and remove this logic from TodoListScreen

πŸ“„ lib/todo_list_screen.dart

  import 'package:todo_list/todo.dart';

  import 'package:todo_list/new_todo_dialog.dart';
+ import 'package:todo_list/todo_list.dart';

  class TodoListScreen extends StatefulWidget {
    @override
  class _TodoListScreenState extends State<TodoListScreen> {
    List<Todo> todos = [];

-   _toggleTodo(Todo todo, bool isChecked) {
-     setState(() {
-       todo.isDone = isChecked;
-     });
-   }
-
-   Widget _buildItem(BuildContext context, int index) {
-     final todo = todos[index];
-
-     return CheckboxListTile(
-       value: todo.isDone,
-       title: Text(todo.title),
-       onChanged: (bool isChecked) {
-         _toggleTodo(todo, isChecked);
-       },
-     );
-   }
-
    _addTodo() async {
      final todo = await showDialog<Todo>(
        context: context,
    Widget build(BuildContext context) {
      return Scaffold(
        appBar: AppBar(title: Text('Todo List')),
-       body: ListView.builder(
-         itemBuilder: _buildItem,
-         itemCount: todos.length,
-       ),
+       body: TodoList(),
        floatingActionButton: FloatingActionButton(
          child: Icon(Icons.add),
          onPressed: _addTodo,

Now let's review our TodoList widget

It is missing Todo class import

πŸ“„ lib/todo_list.dart

  import 'package:flutter/material.dart';

+ import 'package:todo_list/todo.dart';
+
  class TodoList extends StatelessWidget {
    _toggleTodo(Todo todo, bool isChecked) {
      setState(() {

It also doesn't have todos, so let's pass them from parent widget

πŸ“„ lib/todo_list.dart

  import 'package:todo_list/todo.dart';

  class TodoList extends StatelessWidget {
+   TodoList({@required this.todos});
+
+   final List<Todo> todos;
+
    _toggleTodo(Todo todo, bool isChecked) {
      setState(() {
        todo.isDone = isChecked;

πŸ“„ lib/todo_list_screen.dart

    Widget build(BuildContext context) {
      return Scaffold(
        appBar: AppBar(title: Text('Todo List')),
-       body: TodoList(),
+       body: TodoList(
+         todos: todos,
+       ),
        floatingActionButton: FloatingActionButton(
          child: Icon(Icons.add),
          onPressed: _addTodo,

_toggleTodo method relies on setState, so let's move it back to parent

πŸ“„ lib/todo_list.dart

    final List<Todo> todos;

-   _toggleTodo(Todo todo, bool isChecked) {
-     setState(() {
-       todo.isDone = isChecked;
-     });
-   }
-
    Widget _buildItem(BuildContext context, int index) {
      final todo = todos[index];

πŸ“„ lib/todo_list_screen.dart

  class _TodoListScreenState extends State<TodoListScreen> {
    List<Todo> todos = [];

+   _toggleTodo(Todo todo, bool isChecked) {
+     setState(() {
+       todo.isDone = isChecked;
+     });
+   }
+
    _addTodo() async {
      final todo = await showDialog<Todo>(
        context: context,

and pass it down to TodoList as a property

πŸ“„ lib/todo_list.dart

  import 'package:todo_list/todo.dart';

+ typedef ToggleTodoCallback = void Function(Todo, bool);
+
  class TodoList extends StatelessWidget {
-   TodoList({@required this.todos});
+   TodoList({@required this.todos, this.onTodoToggle});

    final List<Todo> todos;
+   final ToggleTodoCallback onTodoToggle;

    Widget _buildItem(BuildContext context, int index) {
      final todo = todos[index];
        value: todo.isDone,
        title: Text(todo.title),
        onChanged: (bool isChecked) {
-         _toggleTodo(todo, isChecked);
+         onTodoToggle(todo, isChecked);
        },
      );
    }

πŸ“„ lib/todo_list_screen.dart

        appBar: AppBar(title: Text('Todo List')),
        body: TodoList(
          todos: todos,
+         onTodoToggle: _toggleTodo,
        ),
        floatingActionButton: FloatingActionButton(
          child: Icon(Icons.add),

Conclusion

Yay! We have working and kinda well-structured Todo List application written in Flutter πŸŽ‰

But there is still a lot of work to do:

App-Screenshot-3.png

See you in next tutorials! πŸ‘‹

Built with Git Tutor

lesnitsky.dev GitHub stars Twitter Follow

You might also like...

An awesome Flutter 3d project by Flutter_Cube package

flutter3d A new Flutter project. Getting Started This project is a starting point for a Flutter application. A few resources to get you started if thi

Oct 26, 2021

A Collection of Flutter and Dart Tips and Tricks

A Collection of Flutter and Dart Tips and Tricks

A Collection of Flutter and Dart Tips and Tricks

Dec 27, 2022

A Flutter implementation of an expandable and animated floating search bar, also known as persistent search.

A Flutter implementation of an expandable and animated floating search bar, also known as persistent search.

Material Floating Search Bar A Flutter implementation of an expandable floating search bar, also known as persistent search, similar to the ones used

Mar 3, 2022

A curated list of awesome cheats needed to quickly get started with flutter development.

dart-cheat-sheet A curated list of awesome stuff needed to get started with your flutter development journey Table of Contents String interpolation Fu

Jan 2, 2023

A flexible multi select package for Flutter. Make multi select widgets the way you want.

A flexible multi select package for Flutter. Make multi select widgets the way you want.

Multi Select Flutter Multi Select Flutter is a package for creating multi-select widgets in a variety of ways. Dialog BottomSheet ChoiceChip Features

Dec 20, 2022

Animal Sounds App written in flutter for the #100daysOfCode

animalsounds A new Flutter project. Getting Started This project is a starting point for a Flutter application. A few resources to get you started if

Jan 9, 2022

Amazon Bookshelf Interface Design made in Flutter

amazon_ui_clone A new Flutter project. Getting Started This project is a starting point for a Flutter application. A few resources to get you started

Nov 25, 2021

A Flutter widget that scrolls text widget and other widget

A Flutter widget that scrolls text widget and other widget

marquee_widget A Flutter widget that scrolls Widget Text and other Widget with supported RTL. Provides many customizationsincluding custom scroll dire

Nov 21, 2022

Flutter.io - How Many People Are In Space Right Now?

Flutter.io - How Many People Are In Space Right Now?

hmpaisrn A new Flutter application. How Many People Are In Space Right Now? Google Play Store https://play.google.com/store/apps/details?id=de.bergera

Mar 16, 2021
Comments
  • Add removeTodo, line throught items and more

    Add removeTodo, line throught items and more

    If this pull request is accepted, it will add the following functionality.

    1. A line through the items when they are completed;
    2. A way to add a new item by simply pressing the return key, instead of moving your finger to the add button;
    3. It will be not able to enter an empty todo;
    4. A way to remove todo by using swipe to dismiss.
    opened by soonsam123 5
  • Explanation on _addTodo() function

    Explanation on _addTodo() function

    _addTodo() { showDialog( context: **context**, builder: (BuildContext context) { return AlertDialog( title: Text('New todo'), ); }, ); }

    Hi, referring to the function above, where does the context variable come from? It was not passed in as an argument. Why can we access to it?

    I am completely new to Flutter.

    Thank you.

    opened by AhSem 1
  • mock data not rendering

    mock data not rendering

    I was a little confused when I follow this step. Nothing would render on the screen:

      }
    
      class _TodoListState extends State<TodoList> {
    -   List<Todo> todos = [];
    +   List<Todo> todos = [
    +     Todo(title: 'Learn Dart'),
    +     Todo(title: 'Try Flutter'),
    +     Todo(title: 'Be amazed'),
    +   ];
    
        _toggleTodo(Todo todo, bool isChecked) {
          todo.isDone = isChecked;
    

    After checking for a few minutes, I moved on. The rest of the tutorial works fine, but I would like to report this since people might run into it.

    Thank for a great tutorial!

    opened by SonQBChau 1
Owner
Andrei Lesnitsky
Self-employed software dev πŸ€“ Flutter Β· WebGL Β· React
Andrei Lesnitsky
GetX SQLite Tutorial.

GetX SQLite Tutorial CΓ³digo-fonte do vΓ­deo "Lista de notas com SQLite e GetX - Tutorial 6" do canal AnthonyDev no YouTube. Link do vΓ­deo: https://yout

AnthonyDev 14 Dec 13, 2022
❀️Flutter ❀️ tips and tricks ❀️ Awesome Flutter ❀️ tips and tricks ❀️

❀️ Awesome Flutter ❀️ tips and tricks ❀️ Tip 1 : stless & stful We can type stless and stful and we get Autocomplete Suggestion to generate Stateless

Laxman Bhattarai 2.8k Dec 28, 2022
It says it all. Not In Flutter Docs, a sort of underground guide to flutter app development and design.

Not In Flutter Docs It says it all. Not In Flutter Docs, a sort of underground guide to flutter app development and design. Licenses Code is under BSD

Fred Grott 56 Dec 27, 2022
Highly Subjective Roadmap to Flutter Development

Flutter Roadmap Dev Environment https://learngitbranching.js.org Language https://dart.dev/guides/language/language-tour https://dart.dev/guides/langu

Oleksandr Leuschenko 4.3k Jan 2, 2023
Learn to Code While Building Apps - The Complete Flutter Development Bootcamp

Learn to Code While Building Apps - The Complete Flutter Development Bootcamp

London App Brewery 9.3k Dec 31, 2022
Based on Microsoft Fluent Design System and made using the help of Flutter VelocityX.

Vx Fluent UI for Flutter Based on Microsoft Fluent Design System and made using the help of Flutter VelocityX. VxFluentUI is a Flutter component libra

Pawan Kumar 14 Jan 28, 2022
Learn Flutter in 30 Days

flutter_catalog A new Flutter project. Getting Started This project is a starting point for a Flutter application. A few resources to get you started

Pawan Kumar 329 Dec 29, 2022
Personal Knowledge Base (PKB). Flutter Responsive Web, Desktop, Android, iOS app. MobX as state management.

PKB - Responsive Flutter Web / Desktop / Android / iOS "Personal Knowledge Base" app written on Flutter. >> View DEMO Video About project This project

Vladimir 21 Oct 10, 2022
Flutter Portfolio App Concept - Day 33

Flutter Portfolio App Concept - Day 33

Mohammad Rahmani 29 Nov 10, 2022
Flutter tips and tricks to make the development smoother and easier

Table of Contents Custom Clippers in Flutter Check if Website is Up or Down in Dart Section Titles on ListView in Flutter Circular Progress in Flutter

Praharsh Bhatt 17 Oct 11, 2022