Daftar Tugas: Batalkan Penghapusan
Termasuk bagian Proyek dalam perjalanan Flutter di Coddy. Pelajaran 7 dari 36.
Geseran berlangsung cepat, begitu juga geseran yang tidak disengaja. Aplikasi yang baik memungkinkan kamu membatalkannya: pesan di bagian bawah memberi tahu apa yang dihapus, dengan tombol Undo di sampingnya.
SnackBar menerima action:, yaitu SnackBarAction dengan label dan onPressed. Untuk mengembalikan tugas ke posisi semula, ingat posisinya sebelum kamu menghapusnya:
final index = _tasks.indexOf(task);
// hapus tugasnya, lalu tampilkan SnackBar
SnackBarAction(
label: 'Undo',
onPressed: () {
setState(() {
_tasks.insert(index, task);
});
},
)Jika kamu menggeser dua tugas dengan cepat, pesan kedua menunggu sampai waktu pesan pertama habis. Panggil ScaffoldMessenger.of(context).hideCurrentSnackBar(); sebelum showSnackBar, agar pesan terbaru langsung muncul.
insert(index, task) mengembalikan tugas ke posisi tersebut dan menggeser tugas-tugas setelahnya ke bawah. add akan menambahkannya di akhir.
Fungsi yang kamu berikan ke onPressed mengingat index dan task dari saat kamu membuatnya, meskipun fungsi itu dijalankan nanti. Itulah closure, dan callback mengandalkannya setiap saat.
Tantangan
SedangBuat agar penghapusan bisa dibatalkan. Di _deleteTask:
- sebelum menghapus tugas, simpan posisinya dengan
indexOf - setelah menghapusnya, tampilkan
SnackBardengan teksDeleteddan judul tugas, sepertiDeleted Walk the dog - tambahkan aksi
Undoyang mengembalikan tugas ke posisi semula - sembunyikan pesan yang sedang ditampilkan terlebih dahulu, agar penghapusan baru menggantikannya
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();
}
void _deleteTask(Task task) {
setState(() {
_tasks.remove(task);
});
}
@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 Dismissible(
key: ObjectKey(task),
direction: DismissDirection.endToStart,
background: Container(
color: Colors.red,
alignment: Alignment.centerRight,
padding: const EdgeInsets.symmetric(horizontal: 24),
child: const Icon(Icons.delete, color: Colors.white),
),
onDismissed: (direction) => _deleteTask(task),
child: 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