MyDiaryคอร์ส Flutter · 6 สัปดาห์ ทุกสัปดาห์
สัปดาห์ที่ 1 · ใบงาน · Lab
สารบัญหน้านี้

ใบงานฝึกปฏิบัติ สัปดาห์ที่ 1: MyDiary หน้าตาและการนำทาง

ก่อนทำ Lab: ต้องผ่านส่วนที่ 3 ในเอกสารสอนมาแล้ว (แอป MyDiary มีรายการ + แตะดูรายละเอียด + เมนูล่าง ครบ 7 ขั้น) Lab นี้ = ต่อยอดของเดิม ให้แอปสมบูรณ์และสวยขึ้น ไม่ต้องเริ่มใหม่

การส่ง: ไฟล์ main.dart + ภาพหน้าจอ 3 ภาพ (หน้ารายการ / หน้ารายละเอียด / หน้าเกี่ยวกับ)


Lab 1 — เพิ่มข้อมูลบันทึกและวันที่

เป้าหมาย: เพิ่ม field วันที่ในบันทึก และเพิ่มบันทึกตัวอย่างให้ครบ 5 อัน

ขั้นที่ 1 — เพิ่ม field date ในแม่พิมพ์ Diary:

class Diary {
  final String title;
  final String content;
  final String date;                    // << เพิ่มบรรทัดนี้
  Diary({required this.title, required this.content, required this.date});
}

ขั้นที่ 2 — แก้ข้อมูลตัวอย่างให้มีวันที่ + เพิ่มเป็น 5 อัน

final List<Diary> diaries = [
  Diary(title: 'วันแรกของการเรียน Flutter', content: 'วันนี้ได้เริ่มเขียนแอปตัวแรก รู้สึกตื่นเต้นมาก', date: '1 มิ.ย. 2568'),
  Diary(title: 'เข้าใจ Widget แล้ว', content: 'ทุกอย่างใน Flutter คือ Widget เหมือนต่อเลโก้', date: '3 มิ.ย. 2568'),
  Diary(title: 'ทำ ListView สำเร็จ', content: 'วันนี้ทำรายการเลื่อนได้ ภูมิใจจัง', date: '5 มิ.ย. 2568'),
  // << เพิ่มอีก 2 อันด้วยตัวเอง (เรื่องอะไรก็ได้)
];

ขั้นที่ 3 — แสดงวันที่ในการ์ด (แก้ subtitle ให้เห็นวันที่ด้วย)

subtitle: Text('${diaries[i].date} • ${diaries[i].content}',
    maxLines: 1, overflow: TextOverflow.ellipsis),

ผลที่ควรได้: การ์ด 5 ใบ แต่ละใบมีวันที่นำหน้าเนื้อหา


Lab 2 — แสดงวันที่ในหน้ารายละเอียด

เป้าหมาย: หน้ารายละเอียดแสดงวันที่ด้วย จัดหน้าให้สวย

ขั้นที่ 1 — แก้ DiaryDetailPage เพิ่มวันที่ใต้ชื่อเรื่อง

child: Column(
  crossAxisAlignment: CrossAxisAlignment.start,
  children: [
    Text(diary.title, style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold)),
    const SizedBox(height: 4),
    Text(diary.date, style: const TextStyle(fontSize: 14, color: Colors.grey)),  // << วันที่
    const Divider(height: 32),          // << เส้นคั่น
    Text(diary.content, style: const TextStyle(fontSize: 16, height: 1.6)),
  ],
),

อธิบายของใหม่: - Divider(height: 32) = เส้นคั่นแนวนอน มีระยะห่างบน-ล่าง - color: Colors.grey = สีเทาให้วันที่ดูจางกว่าชื่อเรื่อง - height: 1.6 = ระยะห่างบรรทัดของเนื้อหา อ่านง่ายขึ้น

ผลที่ควรได้: หน้ารายละเอียดมีชื่อเรื่อง → วันที่สีเทา → เส้นคั่น → เนื้อหา


Lab 3 — ปุ่มลอยเพิ่มบันทึก (ยังกดไม่ได้จริง)

เป้าหมาย: เพิ่มปุ่ม + มุมขวาล่าง (เตรียมไว้สำหรับสัปดาห์หน้า)

แนวคิด: สัปดาห์นี้ยังเพิ่มบันทึกจริงไม่ได้ (เรียนสัปดาห์หน้า) แต่เราใส่ปุ่มไว้ก่อน กดแล้วขึ้นข้อความแจ้ง

ขั้นที่ 1 — เพิ่ม floatingActionButton ใน DiaryListPage (ใน Scaffold)

return Scaffold(
  appBar: AppBar(title: const Text('บันทึกของฉัน')),
  body: ListView.builder( ... ),        // ของเดิม
  floatingActionButton: FloatingActionButton(
    onPressed: () {
      // แสดงข้อความแจ้งชั่วคราว
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(content: Text('ฟีเจอร์เพิ่มบันทึก มาสัปดาห์หน้า!')),
      );
    },
    child: const Icon(Icons.add),
  ),
);

อธิบายของใหม่: - floatingActionButton = ปุ่มลอยมุมขวาล่าง (ตำแหน่งมาตรฐานของ "เพิ่ม") - ScaffoldMessenger.of(context).showSnackBar(...) = แสดงแถบข้อความสั้นๆ ด้านล่างจอ - SnackBar = แถบแจ้งเตือนที่โผล่แล้วหายเอง

ผลที่ควรได้: ปุ่ม + ลอยมุมขวาล่าง กดแล้วขึ้นข้อความด้านล่าง


Lab 4 — แต่งหน้าเกี่ยวกับให้เป็นของตัวเอง

เป้าหมาย: ใส่ข้อมูลตัวเองในหน้าเกี่ยวกับ + จัดให้สวย

ขั้นที่ 1 — แก้ AboutPage ใส่ชื่อจริง + เพิ่มข้อมูล:

body: Center(
  child: Padding(
    padding: const EdgeInsets.all(24),
    child: Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        const CircleAvatar(         // << รูปวงกลม (ใช้ไอคอนแทนรูปก่อน)
          radius: 50,
          backgroundColor: Colors.indigo,
          child: Icon(Icons.book, size: 50, color: Colors.white),
        ),
        const SizedBox(height: 20),
        const Text('MyDiary', style: TextStyle(fontSize: 28, fontWeight: FontWeight.bold)),
        const SizedBox(height: 8),
        const Text('แอปสมุดบันทึกส่วนตัว'),
        const SizedBox(height: 4),
        const Text('สร้างโดย [ใส่ชื่อจริง]'),      // << ใส่ชื่อตัวเอง
        const Text('รหัสนักศึกษา [ใส่รหัส]'),       // << ใส่รหัส
        const SizedBox(height: 16),
        const Text('เวอร์ชัน 1.0', style: TextStyle(color: Colors.grey)),
      ],
    ),
  ),
),

อธิบายของใหม่: - CircleAvatar = วงกลมสำหรับรูปโปรไฟล์ (ตอนนี้ใส่ไอคอนแทน) - radius: 50 = รัศมี (ขนาดวงกลม)

ผลที่ควรได้: หน้าเกี่ยวกับมีวงกลมไอคอน + ชื่อแอป + ชื่อตัวเอง จัดกลาง


Challenge — เปลี่ยนสีการ์ดตามลำดับ

สำหรับคนที่ทำ Lab 1-4 เสร็จแล้ว

โจทย์: ทำให้การ์ดแต่ละใบมีสีไอคอนต่างกัน (สลับสีไปเรื่อยๆ)

คำใบ้: สร้าง List ของสี แล้วเลือกสีตามตำแหน่ง i:

// ประกาศเหนือ return
final List<Color> colors = [Colors.indigo, Colors.teal, Colors.orange, Colors.pink, Colors.green];

// ใน ListTile เปลี่ยน leading เป็น
leading: Icon(Icons.book, color: colors[i % colors.length]),

อธิบาย: i % colors.length = เศษจากการหาร ทำให้สีวนซ้ำเมื่อบันทึกมากกว่าจำนวนสี (0,1,2,3,4,0,1,2...)

เกณฑ์ คะแนน
การ์ดแต่ละใบสีไอคอนต่างกัน 2
สีวนซ้ำได้เมื่อบันทึกเยอะ (ใช้ %) 1

เช็คลิสต์ก่อนส่ง

☐ Lab 1 — การ์ด 5 ใบ มีวันที่
☐ Lab 2 — หน้ารายละเอียดมีวันที่ + เส้นคั่น
☐ Lab 3 — ปุ่ม + ลอย กดขึ้น SnackBar
☐ Lab 4 — หน้าเกี่ยวกับใส่ชื่อตัวเอง
☐ ภาพหน้ารายการ
☐ แอป build ผ่าน ไม่มี error แดง

หมายเหตุ: เก็บโปรเจกต์ไว้ให้ดี — สัปดาห์หน้าเราจะต่อยอดแอปตัวนี้ (เพิ่มฟอร์มให้ผู้ใช้เขียนบันทึกเอง) ไม่ต้องสร้างใหม่