使用主題來分享顏色和字型樣式
若要在整個應用程式中分享顏色和字型樣式,請使用主題。
您可以定義應用程式範圍的主題。您可以延伸主題來變更一個元件的主題樣式。每個主題定義了 Material 元件的顏色、文字樣式和其他適用的參數。
Flutter 會依以下順序套用樣式
- 套用至特定 Widget 的樣式。
- 覆寫直接父主題的主題。
- 整個應用程式的主要主題。
在您定義 Theme
之後,請在您自己的 Widget 中使用它。Flutter 的 Material Widget 會使用您的主題來設定應用程式列、按鈕、核取方塊等等的背景顏色和字型樣式。
建立應用程式主題
#若要在整個應用程式中分享 Theme
,請將 theme
屬性設定為您的 MaterialApp
建構函式。此屬性會接受 ThemeData
實例。
自 Flutter 3.16 版本起,Material 3 是 Flutter 的預設主題。
如果您未在建構函式中指定主題,Flutter 會為您建立預設主題。
MaterialApp(
title: appName,
theme: ThemeData(
useMaterial3: true,
// Define the default brightness and colors.
colorScheme: ColorScheme.fromSeed(
seedColor: Colors.purple,
// ···
brightness: Brightness.dark,
),
// Define the default `TextTheme`. Use this to specify the default
// text styling for headlines, titles, bodies of text, and more.
textTheme: TextTheme(
displayLarge: const TextStyle(
fontSize: 72,
fontWeight: FontWeight.bold,
),
// ···
titleLarge: GoogleFonts.oswald(
fontSize: 30,
fontStyle: FontStyle.italic,
),
bodyMedium: GoogleFonts.merriweather(),
displaySmall: GoogleFonts.pacifico(),
),
),
home: const MyHomePage(
title: appName,
),
);
大多數 ThemeData
實例會為以下兩個屬性設定值。這些屬性會影響整個應用程式。
colorScheme
定義顏色。textTheme
定義文字樣式。
若要了解您可以定義的顏色、字型和其他屬性,請查看 ThemeData
文件。
套用主題
#若要套用您的新主題,請在指定 Widget 的樣式屬性時使用 Theme.of(context)
方法。這些屬性可以包括但不限於 style
和 color
。
Theme.of(context)
方法會在 Widget 樹狀結構中尋找並擷取樹狀結構中最近的 Theme
。如果您有獨立的 Theme
,則會套用該主題。如果沒有,Flutter 會套用應用程式的主題。
在以下範例中,Container
建構函式使用此技巧來設定其 color
。
Container(
padding: const EdgeInsets.symmetric(
horizontal: 12,
vertical: 12,
),
color: Theme.of(context).colorScheme.primary,
child: Text(
'Text with a background color',
// ···
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
color: Theme.of(context).colorScheme.onPrimary,
),
),
),
覆寫主題
#若要覆寫應用程式一部分的整體主題,請將該應用程式區段包裝在 Theme
Widget 中。
您可以使用兩種方式覆寫主題
- 建立獨特的
ThemeData
實例。 - 延伸父主題。
設定獨特的 ThemeData
實例
#如果您希望應用程式的元件忽略整體主題,請建立 ThemeData
實例。將該實例傳遞至 Theme
Widget。
Theme(
// Create a unique theme with `ThemeData`.
data: ThemeData(
colorScheme: ColorScheme.fromSeed(
seedColor: Colors.pink,
),
),
child: FloatingActionButton(
onPressed: () {},
child: const Icon(Icons.add),
),
);
延伸父主題
#請考慮延伸父主題,而非覆寫所有內容。若要延伸主題,請使用 copyWith()
方法。
Theme(
// Find and extend the parent theme using `copyWith`.
// To learn more, check out the section on `Theme.of`.
data: Theme.of(context).copyWith(
colorScheme: ColorScheme.fromSeed(
seedColor: Colors.pink,
),
),
child: const FloatingActionButton(
onPressed: null,
child: Icon(Icons.add),
),
);
觀看關於 Theme
的影片
#若要深入了解,請觀看這部關於 Theme
Widget 的簡短「Widget of the Week」影片
試用互動式範例
#import 'package:flutter/material.dart';
// Include the Google Fonts package to provide more text format options
// https://pub.dev/packages/google_fonts
import 'package:google_fonts/google_fonts.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
const appName = 'Custom Themes';
return MaterialApp(
title: appName,
theme: ThemeData(
useMaterial3: true,
// Define the default brightness and colors.
colorScheme: ColorScheme.fromSeed(
seedColor: Colors.purple,
// TRY THIS: Change to "Brightness.light"
// and see that all colors change
// to better contrast a light background.
brightness: Brightness.dark,
),
// Define the default `TextTheme`. Use this to specify the default
// text styling for headlines, titles, bodies of text, and more.
textTheme: TextTheme(
displayLarge: const TextStyle(
fontSize: 72,
fontWeight: FontWeight.bold,
),
// TRY THIS: Change one of the GoogleFonts
// to "lato", "poppins", or "lora".
// The title uses "titleLarge"
// and the middle text uses "bodyMedium".
titleLarge: GoogleFonts.oswald(
fontSize: 30,
fontStyle: FontStyle.italic,
),
bodyMedium: GoogleFonts.merriweather(),
displaySmall: GoogleFonts.pacifico(),
),
),
home: const MyHomePage(
title: appName,
),
);
}
}
class MyHomePage extends StatelessWidget {
final String title;
const MyHomePage({super.key, required this.title});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title,
style: Theme.of(context).textTheme.titleLarge!.copyWith(
color: Theme.of(context).colorScheme.onSecondary,
)),
backgroundColor: Theme.of(context).colorScheme.secondary,
),
body: Center(
child: Container(
padding: const EdgeInsets.symmetric(
horizontal: 12,
vertical: 12,
),
color: Theme.of(context).colorScheme.primary,
child: Text(
'Text with a background color',
// TRY THIS: Change the Text value
// or change the Theme.of(context).textTheme
// to "displayLarge" or "displaySmall".
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
color: Theme.of(context).colorScheme.onPrimary,
),
),
),
),
floatingActionButton: Theme(
data: Theme.of(context).copyWith(
// TRY THIS: Change the seedColor to "Colors.red" or
// "Colors.blue".
colorScheme: ColorScheme.fromSeed(
seedColor: Colors.pink,
brightness: Brightness.dark,
),
),
child: FloatingActionButton(
onPressed: () {},
child: const Icon(Icons.add),
),
),
);
}
}
除非另有說明,本網站上的文件反映了 Flutter 的最新穩定版本。頁面最後更新於 2024-07-06。 檢視原始碼 或 回報問題。