Daftar Tugas: Geser untuk Menghapus
Termasuk bagian Proyek dalam perjalanan Flutter di Coddy. Pelajaran 6 dari 36.
Di ponsel, kamu menghapus tugas yang sudah selesai dengan menggesernya. Bungkus setiap baris dengan Dismissible dan Flutter akan menggesernya untukmu:
Dismissible(
key: ObjectKey(task),
direction: DismissDirection.endToStart,
background: Container(color: Colors.red, ...),
onDismissed: (direction) => _deleteTask(task),
child: ListTile(...),
)key memberi tahu Flutter baris mana yang mana, sehingga baris yang tepat akan digeser keluar. ObjectKey(task) mengaitkannya dengan tugas itu sendiri. endToStart berarti geseran ke kiri, dan background adalah yang terlihat di balik baris saat digeser: warna merah dengan ikon hapus di sebelah kanan.
onDismissed berjalan saat baris sudah tidak ada di layar. Tugasmu adalah menghapus tugas itu dari daftar di dalam setState. Hapus tugas itu sendiri, bukan posisinya, agar tugas yang tepat tetap terhapus meskipun daftar berubah nanti.
Tantangan
SedangHapus tugas dengan menggeser:
- tambahkan method
_deleteTask(Task task)yang menghapus tugas di dalamsetState - bungkus setiap
ListTiledenganDismissibleyang memilikikey: ObjectKey(task)dan digeser ke kiri background-nya adalahContainermerah denganIcons.deleteputih di sebelah kanan, 24 piksel dari tepi
Coba sendiri
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,
),
);
},
),
),
],
),
);
}
}
Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.
Semua pelajaran di Proyek
1Proyek: Daftar Tugas
Daftar Tugas: Daftar TugasDaftar Tugas: Tambahkan Tugas4Proyek: Pelacak Kebiasaan
Pelacak Kebiasaan: KebiasaanmuPelacak Kebiasaan: Pekan IniLatihan sendiri: Compiler Flutter online