ข้ามไปยังเนื้อหาหลัก
คู่มือระบบ เนื้อหาผ่านการตรวจสอบแล้ว

การสร้าง Custom Widget ที่มี State

บทความนี้อธิบายถึงการสร้าง Custom Widget ที่มี State ใน Flutter โดยเน้นที่การใช้งาน StatefulWidget ซึ่งประกอบด้วย StatefulWidget Class และ State Class เพื่อจัดก...

การสร้าง Custom Widget ที่มี State ใน Flutter

ในบทความก่อนหน้า เราได้เรียนรู้การใช้งาน Camera API ใน Flutter เพื่อถ่ายรูปและบันทึกวิดีโอ ในบทความนี้ เราจะมาเรียนรู้การสร้าง Custom Widget ที่สามารถเปลี่ยนแปลง State ได้ ซึ่งเป็นหัวใจสำคัญของการสร้างแอปพลิเคชัน Flutter ที่มีความ interactive และ dynamic

StatefulWidget คืออะไร?

ใน Flutter, Widget แบ่งออกเป็นสองประเภทหลักๆ คือ:

  • StatelessWidget: Widget ที่ไม่มี state ภายในตัวเอง และไม่สามารถเปลี่ยนแปลงได้เมื่อสร้างขึ้นมาแล้ว ตัวอย่างเช่น Text, Icon, Image
  • StatefulWidget: Widget ที่มี state ภายในตัวเอง และสามารถเปลี่ยนแปลงได้ตลอดเวลา ตัวอย่างเช่น Checkbox, Slider, TextField

StatefulWidget มีความซับซ้อนกว่า StatelessWidget เล็กน้อย เพราะต้องมีคลาส State ที่จัดการ state ของ Widget นั้นๆ

โครงสร้างของ StatefulWidget

StatefulWidget ประกอบด้วยสองส่วนหลักๆ:

  1. StatefulWidget Class: คลาสที่ extends StatefulWidget และสร้าง instance ของ State class
  2. State Class: คลาสที่ extends State<StatefulWidget> และจัดการ state ของ Widget รวมถึง UI ที่แสดงผล

ตัวอย่างโครงสร้างพื้นฐานของ StatefulWidget:

import 'package:flutter/material.dart';

class MyCustomWidget extends StatefulWidget {
  const MyCustomWidget({Key? key}) : super(key: key);

  @override
  State<MyCustomWidget> createState() => _MyCustomWidgetState();
}

class _MyCustomWidgetState extends State<MyCustomWidget> {
  @override
  Widget build(BuildContext context) {
    return Container(); // Replace with your actual UI
  }
}

ในตัวอย่างนี้:

  • MyCustomWidget คือ StatefulWidget class ที่ extends StatefulWidget
  • _MyCustomWidgetState คือ State class ที่ extends State<MyCustomWidget> และจัดการ state ของ MyCustomWidget
  • createState() method ใน MyCustomWidget จะสร้าง instance ของ _MyCustomWidgetState
  • build() method ใน _MyCustomWidgetState จะสร้าง UI ที่แสดงผล โดยใช้ state ที่เก็บไว้

setState() Method

setState() เป็น method ที่สำคัญที่สุดในการจัดการ state ใน StatefulWidget เมื่อ state ของ Widget เปลี่ยนแปลง เราจะต้องเรียก setState() เพื่อบอกให้ Flutter rebuild UI ใหม่ด้วย state ที่อัปเดต

ตัวอย่างการใช้งาน setState():

import 'package:flutter/material.dart';

class MyCounterWidget extends StatefulWidget {
  const MyCounterWidget({Key? key}) : super(key: key);

  @override
  State<MyCounterWidget> createState() => _MyCounterWidgetState();
}

class _MyCounterWidgetState extends State<MyCounterWidget> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Counter App'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}

ในตัวอย่างนี้:

  • เราสร้าง StatefulWidget ชื่อ MyCounterWidget ที่มี state เป็นตัวแปร _counter
  • เมื่อกดปุ่ม FloatingActionButton, _incrementCounter() จะถูกเรียก
  • _incrementCounter() จะเรียก setState() เพื่ออัปเดตค่าของ _counter และบอกให้ Flutter rebuild UI ใหม่
  • build() method จะใช้ค่า _counter ที่อัปเดตเพื่อแสดงผลตัวเลขบนหน้าจอ

สิ่งที่ควรจำ:

  • การเรียก setState() จะทำให้ Flutter rebuild เฉพาะส่วนของ Widget tree ที่เกี่ยวข้องกับการเปลี่ยนแปลง state เท่านั้น ไม่ได้ rebuild ทั้งหน้าจอ ซึ่งช่วยให้แอปพลิเคชันทำงานได้อย่างรวดเร็ว
  • ควรเรียก setState() ภายใน State Class เท่านั้น

BuildContext คืออะไร?

BuildContext เป็น interface ที่ให้ข้อมูลเกี่ยวกับตำแหน่งของ Widget ใน Widget tree และช่วยให้ Widget สามารถเข้าถึง resources ต่างๆ เช่น Theme, MediaQuery, Localizations ได้

BuildContext จะถูกส่งผ่านไปยัง build() method ของทุก Widget:

@override
Widget build(BuildContext context) {
  // Use context to access resources
  final theme = Theme.of(context);
  final size = MediaQuery.of(context).size;

  return Container(
    width: size.width,
    height: size.height,
    color: theme.primaryColor,
  );
}

ในตัวอย่างนี้:

  • เราใช้ context เพื่อเข้าถึง Theme และ MediaQuery
  • Theme.of(context) จะคืนค่า ThemeData ที่ใช้กับ Widget tree ปัจจุบัน
  • MediaQuery.of(context) จะคืนค่าข้อมูลเกี่ยวกับหน้าจอ เช่น ขนาด, orientation, pixel density

BuildContext มีประโยชน์อย่างมากในการสร้าง Widget ที่ปรับตัวตามสภาพแวดล้อมต่างๆ เช่น ขนาดหน้าจอ, theme, ภาษา

ตัวอย่างการสร้าง Custom Widget ที่มี State และใช้ BuildContext

ลองสร้าง Custom Widget ที่แสดงข้อความและเปลี่ยนสีเมื่อกดปุ่ม:

import 'package:flutter/material.dart';
import 'dart:math';

class MyColorChangingText extends StatefulWidget {
  const MyColorChangingText({Key? key}) : super(key: key);

  @override
  State<MyColorChangingText> createState() => _MyColorChangingTextState();
}

class _MyColorChangingTextState extends State<MyColorChangingText> {
  Color _textColor = Colors.black;

  void _changeColor() {
    setState(() {
      _textColor = Color((Random().nextDouble() * 0xFFFFFF).toInt()).withOpacity(1.0);
    });
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: _changeColor,
      child: Text(
        'แตะเพื่อเปลี่ยนสี',
        style: TextStyle(
          color: _textColor,
          fontSize: 20,
        ),
      ),
    );
  }
}

ในตัวอย่างนี้:

  • เราสร้าง StatefulWidget ชื่อ MyColorChangingText ที่มี state เป็นตัวแปร _textColor
  • เมื่อแตะที่ข้อความ, _changeColor() จะถูกเรียก
  • _changeColor() จะสร้างสีใหม่แบบสุ่ม และเรียก setState() เพื่ออัปเดตค่าของ _textColor
  • build() method จะใช้ค่า _textColor ที่อัปเดตเพื่อแสดงผลข้อความด้วยสีใหม่
  • เราใช้ GestureDetector เพื่อตรวจจับการแตะที่ข้อความ

การใช้งาน Widget นี้ในหน้าจอ:

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Color Changing App',
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Color Changing App'),
        ),
        body: const Center(
          child: MyColorChangingText(),
        ),
      ),
    );
  }
}

สรุป

ในบทความนี้ เราได้เรียนรู้เกี่ยวกับ StatefulWidget, setState(), และ BuildContext ซึ่งเป็นพื้นฐานสำคัญในการสร้างแอปพลิเคชัน Flutter ที่มีความ interactive และ dynamic การเข้าใจ concepts เหล่านี้จะช่วยให้คุณสามารถสร้าง Custom Widget ที่ซับซ้อนและปรับแต่งได้ตามต้องการ

ในบทความถัดไป เราจะเรียนรู้การสร้าง Layout ที่ซับซ้อนด้วย Custom Layouts ซึ่งจะช่วยให้คุณสามารถควบคุมการจัดวาง Widget บนหน้าจอได้อย่างละเอียด

Office.in.th Custom Service

ต้องการพัฒนาระบบหรือปรับแต่งจากโครงสร้างนี้?

Office.in.th รับพัฒนาและออกแบบ Enterprise Web Application, API Integration และระบบบริหารงานภาครัฐ/เอกชน พร้อมการสนับสนุนระยะยาว

ดูบริการรับพัฒนาซอฟต์แวร์