รวมสีและการจัดวางตัวอักษรไว้ที่ศูนย์กลางใน ThemeData สร้างพาเลตต์สี Material 3 ด้วย ColorScheme.fromSeed และมอบโหมดมืดได้อย่างไม่ยากเย็น
เปิดบทเรียนนี้ใน Kodokonการเลิกจัดสไตล์ทีละวิดเจ็ตคือก้าวสำคัญสู่ความเป็นมืออาชีพ ThemeData รวมสี การจัดวางตัวอักษร และรูปทรงของทั้งแอปไว้ที่ศูนย์กลาง ด้วย Material 3 (เปิดใช้เป็นค่าเริ่มต้นตั้งแต่ Flutter 3.16) ทุกอย่างเริ่มต้นจาก ColorScheme โดย ColorScheme.fromSeed จะสกัดพาเลตต์สีที่ครบถ้วน กลมกลืน และเข้าถึงได้ ออกมาจากสี seed เพียงสีเดียว
import 'package:flutter/material.dart';
void main() {
runApp(const ShopApp());
}
class ShopApp extends StatelessWidget {
const ShopApp({super.key});
@override
Widget build(BuildContext context) {
const seed = Colors.teal;
return MaterialApp(
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(
seedColor: seed,
),
),
darkTheme: ThemeData(
colorScheme: ColorScheme.fromSeed(
seedColor: seed,
brightness: Brightness.dark,
),
),
themeMode: ThemeMode.system,
home: Scaffold(
appBar: AppBar(title: const Text('Shop')),
body: const Center(child: Text('Welcome')),
),
);
}
}ภายในวิดเจ็ตของคุณ อย่าประดิษฐ์อะไรขึ้นใหม่ จงอ่านธีมโดยรอบด้วย Theme.of(context) ตัว colorScheme เปิดเผย บทบาท (role) เชิงความหมาย (primary, onPrimary, primaryContainer, surface และอื่น ๆ) และ textTheme เปิดเผยสไตล์ที่มีชื่อ (titleMedium, bodyLarge และอื่น ๆ) วิดเจ็ตที่เขียนแบบนี้จะปรับตัวเข้ากับธีมสว่างและธีมมืดได้โดยอัตโนมัติ
import 'package:flutter/material.dart';
class PriceTag extends StatelessWidget {
const PriceTag({super.key, required this.price});
final double price;
@override
Widget build(BuildContext context) {
final colors = Theme.of(context).colorScheme;
final text = Theme.of(context).textTheme;
return Container(
padding: const EdgeInsets.symmetric(
horizontal: 12,
vertical: 6,
),
decoration: BoxDecoration(
color: colors.primaryContainer,
borderRadius: BorderRadius.circular(8),
),
child: Text(
'$price €',
style: text.titleMedium?.copyWith(
color: colors.onPrimaryContainer,
),
),
);
}
}หากต้องการก้าวไปอีกขั้น จงตั้งค่า ธีมของคอมโพเนนต์ วิดเจ็ตแต่ละตระกูล (แถบแอป ปุ่ม ช่องกรอกข้อมูล) รับธีมเฉพาะตัวใน ThemeData ได้ คุณกำหนดระยะขอบ (padding) ของปุ่มหรือการจัดกึ่งกลางของหัวข้อเพียงครั้งเดียว แล้วทุกอินสแตนซ์จะสืบทอดมันไปโดยไม่ต้องมีสไตล์เฉพาะที่สักบรรทัดเดียว
import 'package:flutter/material.dart';
final ThemeData appTheme = ThemeData(
colorScheme: ColorScheme.fromSeed(
seedColor: Colors.teal,
),
appBarTheme: const AppBarTheme(
centerTitle: true,
elevation: 0,
),
filledButtonTheme: FilledButtonThemeData(
style: FilledButton.styleFrom(
padding: const EdgeInsets.symmetric(
horizontal: 24,
vertical: 12,
),
),
),
);