การใช้ ThemeData และ Custom Themes ใน Flutter
ในบทเรียนที่แล้ว เราได้เรียนรู้เกี่ยวกับการจัดการ Gesture ใน Flutter เพื่อให้แอปพลิเคชันตอบสนองต่อการสัมผัสของผู้ใช้ได้อย่างละเอียด ในบทนี้ เราจะมาเรียนรู้วิธีการสร้าง Theme ที่สอดคล้องกันทั้งแอปด้วยการใช้ ThemeData และ Custom Themes ซึ่งจะช่วยให้แอปพลิเคชันของคุณมีรูปลักษณ์ที่สวยงามและเป็นระเบียบมากยิ่งขึ้น
ทำไมต้องใช้ ThemeData และ Custom Themes?
- ความสอดคล้อง: ทำให้สี, ตัวอักษร, และสไตล์ต่างๆ ในแอปพลิเคชันมีความสอดคล้องกัน
- ความสะดวก: เปลี่ยนแปลงรูปลักษณ์ของแอปพลิเคชันได้อย่างง่ายดายเพียงแค่เปลี่ยน Theme
- การปรับแต่ง: สร้าง Theme ที่เป็นเอกลักษณ์และเหมาะสมกับแบรนด์ของคุณ
- การรองรับ Dark Mode: สร้าง Theme สำหรับ Dark Mode ได้อย่างง่ายดาย
ThemeData คืออะไร?
ThemeData คือคลาสที่เก็บข้อมูลเกี่ยวกับสไตล์ของแอปพลิเคชัน เช่น สี, ตัวอักษร, ไอคอน, และรูปร่างต่างๆ คุณสามารถสร้าง ThemeData object และกำหนดค่าต่างๆ เพื่อให้แอปพลิเคชันของคุณมีรูปลักษณ์ตามที่คุณต้องการ
การใช้งาน ThemeData พื้นฐาน
เริ่มต้นด้วยการสร้าง ThemeData object ใน MaterialApp widget:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Theme Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Home Page'),
),
body: Center(
child: Text(
'Hello, World!',
style: TextStyle(fontSize: 24),
),
),
);
}
}
ในตัวอย่างนี้ เรากำหนด primarySwatch เป็น Colors.blue ซึ่งจะทำให้สีหลักของแอปพลิเคชันเป็นสีน้ำเงิน
ค่าสำคัญใน ThemeData
ThemeData มีค่ามากมายที่คุณสามารถกำหนดได้ นี่คือค่าที่สำคัญบางส่วน:
primaryColor: สีหลักของแอปพลิเคชันaccentColor: สีรองที่ใช้สำหรับเน้นองค์ประกอบต่างๆbackgroundColor: สีพื้นหลังของแอปพลิเคชันtextTheme: กำหนดสไตล์ของตัวอักษรต่างๆiconTheme: กำหนดสไตล์ของไอคอนbuttonTheme: กำหนดสไตล์ของปุ่มcardTheme: กำหนดสไตล์ของการ์ดappBarTheme: กำหนดสไตล์ของ AppBar
การกำหนด primaryColor และ accentColor
primaryColor คือสีหลักที่ใช้ใน AppBar, ปุ่ม, และองค์ประกอบอื่นๆ ที่ต้องการเน้น ส่วน accentColor คือสีรองที่ใช้สำหรับเน้นองค์ประกอบบางอย่าง เช่น floating action button หรือตัวเลือกใน dropdown menu
theme: ThemeData(
primaryColor: Colors.purple,
accentColor: Colors.amber,
)
การกำหนด TextTheme
TextTheme คือชุดของสไตล์ตัวอักษรที่ใช้ในแอปพลิเคชัน คุณสามารถกำหนดสไตล์สำหรับหัวข้อ (headline), หัวข้อย่อย (subhead), เนื้อหา (body), และปุ่มต่างๆ
theme: ThemeData(
primaryColor: Colors.purple,
accentColor: Colors.amber,
textTheme: TextTheme(
headline1: TextStyle(fontSize: 72.0, fontWeight: FontWeight.bold, color: Colors.black),
headline6: TextStyle(fontSize: 36.0, fontStyle: FontStyle.italic, color: Colors.grey),
bodyText2: TextStyle(fontSize: 14.0, fontFamily: 'Hind', color: Colors.blueGrey),
),
)
ในการใช้งาน textTheme ใน widget ของคุณ:
Text(
'หัวข้อหลัก',
style: Theme.of(context).textTheme.headline1,
),
Text(
'เนื้อหา',
style: Theme.of(context).textTheme.bodyText2,
),
Theme.of(context) คืออะไร?
Theme.of(context) คือ method ที่ใช้ในการเข้าถึง ThemeData ที่ใกล้ที่สุดใน Widget Tree Widget ทุกตัวที่อยู่ภายใต้ MaterialApp จะสามารถเข้าถึง ThemeData ที่กำหนดไว้ใน MaterialApp ได้
ตัวอย่าง:
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
color: Theme.of(context).primaryColor,
child: Text(
'ข้อความสีขาว',
style: TextStyle(color: Theme.of(context).accentColor),
),
);
}
}
ในตัวอย่างนี้ เราใช้ Theme.of(context).primaryColor เพื่อกำหนดสีพื้นหลังของ Container และ Theme.of(context).accentColor เพื่อกำหนดสีของข้อความ
การสร้าง Custom Themes
นอกจากการใช้ ThemeData พื้นฐานแล้ว คุณยังสามารถสร้าง Custom Themes ที่มีสไตล์เฉพาะตัวได้ โดยการสร้าง class ที่ extends ThemeData และกำหนดค่าต่างๆ ตามที่คุณต้องการ
class MyCustomTheme {
static ThemeData get lightTheme { //1
return ThemeData( //2
primaryColor: Colors.green,
scaffoldBackgroundColor: Colors.white,
fontFamily: 'Montserrat', //3
buttonTheme: ButtonThemeData( //4
buttonColor: Colors.green,
textTheme: ButtonTextTheme.primary,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20.0))
)
);
}
static ThemeData get darkTheme { //5
return ThemeData(
primaryColor: Colors.black,
scaffoldBackgroundColor: Colors.grey.shade800,
fontFamily: 'Montserrat',
textTheme: ThemeData.dark().textTheme,
buttonTheme: ButtonThemeData(
buttonColor: Colors.amber,
textTheme: ButtonTextTheme.primary,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20.0))
)
);
}
}
- สร้าง class ชื่อ
MyCustomThemeเพื่อเก็บ themes ที่เราสร้างขึ้น - สร้าง static getter method ชื่อ
lightThemeที่ returnThemeDataobject สำหรับ light theme - กำหนดค่าต่างๆ ใน
ThemeDataเช่นprimaryColor,scaffoldBackgroundColor, และfontFamily - กำหนดสไตล์ของปุ่มด้วย
buttonTheme - สร้าง static getter method ชื่อ
darkThemeที่ returnThemeDataobject สำหรับ dark theme
จากนั้นใช้ Custom Theme ใน MaterialApp widget:
MaterialApp(
title: 'Flutter Custom Theme Demo',
theme: MyCustomTheme.lightTheme,
darkTheme: MyCustomTheme.darkTheme,
themeMode: ThemeMode.system, // or ThemeMode.light or ThemeMode.dark
home: MyHomePage(),
);
themeMode กำหนดว่าจะใช้ theme ไหน โดย ThemeMode.system จะใช้ theme ตามการตั้งค่าของระบบปฏิบัติการ
การรองรับ Dark Mode
Flutter รองรับ Dark Mode ได้อย่างง่ายดาย คุณสามารถสร้าง ThemeData สำหรับ Dark Mode และกำหนดให้ MaterialApp ใช้ theme นั้นเมื่อระบบปฏิบัติการอยู่ใน Dark Mode
theme: ThemeData(
brightness: Brightness.light,
primaryColor: Colors.blue,
accentColor: Colors.blueAccent,
),
darkTheme: ThemeData(
brightness: Brightness.dark,
primaryColor: Colors.black,
accentColor: Colors.white,
),
themeMode: ThemeMode.system,
ในตัวอย่างนี้ เรากำหนด brightness เป็น Brightness.light สำหรับ theme ปกติ และ Brightness.dark สำหรับ Dark Mode
สรุป
ในบทนี้ เราได้เรียนรู้เกี่ยวกับการใช้ ThemeData และ Custom Themes ใน Flutter เพื่อสร้าง Theme ที่สอดคล้องกันทั้งแอปพลิเคชัน การใช้ Theme จะช่วยให้แอปพลิเคชันของคุณมีรูปลักษณ์ที่สวยงามและเป็นระเบียบมากยิ่งขึ้น และยังช่วยให้คุณสามารถปรับแต่งรูปลักษณ์ของแอปพลิเคชันได้อย่างง่ายดาย
ในบทเรียนถัดไป เราจะมาเรียนรู้เกี่ยวกับการจัดการ Navigation ด้วย Named Routes และ Navigator 2.0