Menu
CoddyTech

רשימת משימות: החלקה למחיקה

חלק מהיחידה פרויקטים במסלול ה-Flutter של Coddy. שיעור 6 מתוך 36.

בטלפון, אפשר להסיר משימה שהושלמה באמצעות החלקה שלה הצדה. עטפו כל שורה ב־Dismissible, ו־Flutter יבצע את ההחלקה עבורכם:

Dismissible(
  key: ObjectKey(task),
  direction: DismissDirection.endToStart,
  background: Container(color: Colors.red, ...),
  onDismissed: (direction) => _deleteTask(task),
  child: ListTile(...),
)

ה־key אומר ל־Flutter איזו שורה היא איזו, כדי שהשורה הנכונה תחליק החוצה. ObjectKey(task) קושר אותה למשימה עצמה. endToStart פירושו החלקה שמאלה, ו־background הוא מה שמוצג מאחורי השורה בזמן שהיא מחליקה: רקע אדום עם סמל מחיקה בצד ימין.

onDismissed מופעל כשהשורה נעלמת מהמסך. התפקיד שלכם הוא להסיר שם את המשימה מהרשימה, בתוך setState. הסירו את המשימה עצמה, ולא מיקום, כדי שהמשימה הנכונה תוסר גם אם הרשימה תשתנה בהמשך.

challenge icon

אתגר

בינוני

החלק כדי להסיר משימות:

  • הוסף מתודה בשם _deleteTask(Task task) שמסירה את המשימה בתוך setState
  • עטוף כל ListTile ב־Dismissible עם key: ObjectKey(task), שאותו מחליקים שמאלה
  • ה־background שלו הוא Container אדום ובו Icons.delete לבן בצד ימין, במרחק 24 פיקסלים מהקצה

נסו בעצמכם

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,
                  ),
                );
              },
            ),
          ),
        ],
      ),
    );
  }
}
quiz iconבחנו את עצמכם

השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.

כל השיעורים ביחידה פרויקטים

תרגלו בעצמכם: קומפיילר Flutter אונליין