Build a Todo App with Flutter(6)
The ToDo application helps us manage and organize our tasks more easily. Managing tasks using the ToDo app will require us to work with data persistence, user input processing, and state management.
$ flutter create todo --emptyCreating project .... windows/runner/flutter_window.cpp (created) windows/runner/utils.h (created) windows/runner/utils.cpp (created) windows/runner/runner.exe.manifest (created) windows/runner/CMakeLists.txt (created) windows/runner/win32_window.h (created) windows/runner/Runner.rc (created) windows/runner/win32_window.cpp (created) windows/runner/resources/app_icon.ico (created) windows/runner/main.cpp (created) windows/runner/resource.h (created) windows/runner/flutter_window.h (created) windows/flutter/CMakeLists.txt (created) windows/.gitignore (created) windows/CMakeLists.txt (created) ios/Runner.xcworkspace/contents.xcworkspacedata (created) ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist (created) ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings (created) ios/RunnerTests/RunnerTests.swift (created) ios/Runner/Info.plist (created) ios/Runner/Runner-Bridging-Header.h (created) ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png (created) ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md (created) ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json (created) ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png (created) ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png (created) ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png (created) ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png (created) ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png (created) ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png (created) ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png (created) ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png (created) ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png (created) ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png (created) ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png (created) ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json (created) ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png (created) ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png (created) ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png (created) ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png (created) ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png (created) ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png (created) ios/Runner/Base.lproj/LaunchScreen.storyboard (created) ios/Runner/Base.lproj/Main.storyboard (created) ios/Runner/AppDelegate.swift (created) ios/Runner/SceneDelegate.swift (created) ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata (created) ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist (created) ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings (created) ios/Runner.xcodeproj/project.pbxproj (created) ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme (created) ios/Flutter/Debug.xcconfig (created) ios/Flutter/Release.xcconfig (created) ios/Flutter/AppFrameworkInfo.plist (created) ios/.gitignore (created) .gitignore (created) web/favicon.png (created) web/index.html (created) web/manifest.json (created) web/icons/Icon-maskable-512.png (created) web/icons/Icon-192.png (created) web/icons/Icon-maskable-192.png (created) web/icons/Icon-512.png (created) macos/Runner.xcworkspace/contents.xcworkspacedata (created) macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist (created) macos/RunnerTests/RunnerTests.swift (created) macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png (created) macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png (created) macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png (created) macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png (created) macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png (created) macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json (created) macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png (created) macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png (created) macos/Runner/DebugProfile.entitlements (created) macos/Runner/Base.lproj/MainMenu.xib (created) macos/Runner/MainFlutterWindow.swift (created) macos/Runner/Configs/Debug.xcconfig (created) macos/Runner/Configs/Release.xcconfig (created) macos/Runner/Configs/Warnings.xcconfig (created) macos/Runner/Configs/AppInfo.xcconfig (created) macos/Runner/AppDelegate.swift (created) macos/Runner/Info.plist (created) macos/Runner/Release.entitlements (created) macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist (created) macos/Runner.xcodeproj/project.pbxproj (created) macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme (created) macos/Flutter/Flutter-Debug.xcconfig (created) macos/Flutter/Flutter-Release.xcconfig (created) macos/.gitignore (created) android/app/src/profile/AndroidManifest.xml (created) android/app/src/main/res/mipmap-mdpi/ic_launcher.png (created) android/app/src/main/res/mipmap-hdpi/ic_launcher.png (created) android/app/src/main/res/drawable/launch_background.xml (created) android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png (created) android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png (created) android/app/src/main/res/values-night/styles.xml (created) android/app/src/main/res/values/styles.xml (created) android/app/src/main/res/drawable-v21/launch_background.xml (created) android/app/src/main/res/mipmap-xhdpi/ic_launcher.png (created) android/app/src/main/AndroidManifest.xml (created) android/app/src/debug/AndroidManifest.xml (created) android/settings.gradle.kts (created) android/gradle/wrapper/gradle-wrapper.properties (created) android/gradle.properties (created) android/.gitignore (created) android/build.gradle.kts (created) android/app/build.gradle.kts (created) pubspec.yaml (created) README.md (created) lib/main.dart (created) analysis_options.yaml (created) .idea/runConfigurations/main_dart.xml (created) .idea/libraries/Dart_SDK.xml (created) .idea/libraries/KotlinJavaRuntime.xml (created) .idea/modules.xml (created) .idea/workspace.xml (created) linux/runner/main.cc (created) linux/runner/CMakeLists.txt (created) linux/runner/my_application.h (created) linux/runner/my_application.cc (created) linux/flutter/CMakeLists.txt (created) linux/.gitignore (created) linux/CMakeLists.txt (created)Resolving dependencies... (7.0s)Downloading packages...Got dependencies.Wrote 130 files.All done!You can find general documentation for Flutter at: https://docs.flutter.dev/Detailed API documentation is available at: https://api.flutter.dev/If you prefer video documentation, consider: https://www.youtube.com/c/flutterdevIn order to run your empty application, type: $ flutter runYour empty application code is in ./lib/main.dart.
Add the boilerplate code below in main.dart to create a basic structure with an AppBar and body using a Scaffold.
void main() { runApp(const MainApp());}classMainAppextendsStatelessWidget{ const MainApp({super.key}); @override Widget build(BuildContext context) {return MaterialApp( home: HomeScreen(), debugShowCheckedModeBanner: false, theme: ThemeData(primarySwatch: Colors.indigo), ); }}
We create a HomeScreen widget to display the home screen of this app.
classHomeScreenextendsStatefulWidget{ const HomeScreen({super.key}); @override State<HomeScreen> createState() => _HomeScreenState();}class_HomeScreenStateextendsState<HomeScreen> { @override Widget build(BuildContext context) {return Scaffold( appBar: AppBar( title: const Text('Todo App', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 25), ), centerTitle: true, backgroundColor: Colors.green, foregroundColor: Colors.white, ), body: Container(), ); }}
We intialize required variables to work with Todos:
class_HomeScreenStateextendsState<HomeScreen> { // List to store tasks List<String> todoList = []; // Controller for text input final TextEditingController _controller = TextEditingController(); // Index to track which task is being edited int updateIndex = -1; // ...}
Next we create methods to add, update, and delete tasks in a list.
// Function to add a new task to the list void addList(String task) { setState(() { todoList.add(task); _controller.clear(); }); } // Function to update an existing task void updateListItem(String task, int index) { setState(() { todoList[index] = task;// Reset update index updateIndex = -1; _controller.clear(); }); } // Function to delete a task void deleteItem(int index) { setState(() { todoList.removeAt(index); }); }// ...
We update the UI to receive input from the user.
TextFormField( // Input field controller controller: _controller, decoration: InputDecoration( focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(8), borderSide: BorderSide( color: Colors.green, )), filled: true,// Placeholder text labelText: 'Create Task....', labelStyle: TextStyle( color: Colors.black, fontWeight: FontWeight.bold, ), ),),
We use ListView.builder to display the list of tasks.
ListView.builder(// Number of tasks in the list itemCount: todoList.length, itemBuilder: (context, index) {return Card( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ),// Card background color color: Colors.green, child: Container( margin: EdgeInsets.only(left: 20), alignment: Alignment.center, padding: EdgeInsets.all(10), child: Row( children: [ Expanded( flex: 80, child: Text(// Display the task text todoList[index], style: TextStyle( color: Colors.white, fontWeight: FontWeight.bold, fontSize: 20), ), ),// Edit button IconButton( onPressed: () { setState(() { _controller.clear(); _controller.text = todoList[index]; updateIndex = index; }); }, icon: Icon( Icons.edit, size: 30, color: Colors.white, ), ), SizedBox(width: 10),// Delete button IconButton( onPressed: () { deleteItem(index); }, icon: Icon( Icons.delete, size: 30, color: Colors.white, ), ), ], ), ), ); }),
We use a FloatingActionButton to add an item to the list.
FloatingActionButton( backgroundColor: Colors.green, foregroundColor: Colors.white, onPressed: () { updateIndex != -1 ? updateListItem(_controller.text, updateIndex) // Update task if editing : addList(_controller.text); // Add new task },// Icon changes based on action child: Icon(updateIndex != -1 ? Icons.edit : Icons.add), ),
We use two IconButton to implement actions such as Edit and Delete.
// Edit buttonIconButton( onPressed: () { setState(() { _controller.clear(); _controller.text = todoList[index]; updateIndex = index; }); }, icon: Icon( Icons.edit, size: 30, color: Colors.white, ),),SizedBox(width: 10),// Delete buttonIconButton( onPressed: () { deleteItem(index); }, icon: Icon( Icons.delete, size: 30, color: Colors.white, ),),
夜雨聆风