Flutter学习笔记34-主题

Theme组件可以为Material APP定义主题数据(ThemeData)。Material组件库里很多组件都使用了主题数据,如导航栏颜色、标题字体、Icon样式等。Theme内会使用InheritedWidget来为其子树共享样式数据。

ThemeData

ThemeData用于保存是Material组件库的主题数据,Material组件需要遵守相应的设计规范,而这些规范可自定义部分都定义在ThemeData中了,所以可以通过ThemeData来自定义应用主题。在子组件中,可以通过Theme.of方法来获取当前的ThemeData
ThemeData部分数据定义:

ThemeData({
  Brightness brightness, // 深色还是浅色
  MaterialColor primarySwatch, // 主题颜色样本
  Color primaryColor, // 主色,决定导航栏颜色
  Color accentColor, // 次级色,决定大多数Widget的颜色,如进度条、开关等。
  Color cardColor, // 卡片颜色
  Color dividerColor, // 分割线颜色
  ButtonThemeData buttonTheme, // 按钮主题
  Color cursorColor, // 输入框光标颜色
  Color dialogBackgroundColor,// 对话框背景颜色
  String fontFamily, // 文字字体
  TextTheme textTheme,// 字体主题,包括标题、body等文字样式
  IconThemeData iconTheme, // Icon的默认样式
  TargetPlatform platform, // 指定平台,应用特定平台控件风格
  ...
})

代码示例:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        // primarySwatch传入不是Color, 而是MaterialColor(包含了primaryColor和accentColor)
        primarySwatch: Colors.red,
        // primaryColor: 单独设置导航和TabBar的颜色
        primaryColor: Colors.orange,
        // accentColor: 单独设置FloatingActionButton、Switch等widget
        accentColor: Colors.green,
        // Button的主题
        buttonTheme: ButtonThemeData(
            height: 25, minWidth: 10, buttonColor: Colors.yellow),
        // Card的主题
        cardTheme: CardTheme(color: Colors.greenAccent, elevation: 10),
        // Text的主题
        textTheme: TextTheme(
          bodyText2: TextStyle(fontSize: 16, color: Colors.red),
          bodyText1: TextStyle(fontSize: 20, color: Colors.blue),
          headline1: TextStyle(fontSize: 14),
          headline2: TextStyle(fontSize: 16),
          headline3: TextStyle(fontSize: 18),
          headline4: TextStyle(fontSize: 20),
        ),
      ),
      home: ThemeDemo(),
    );
  }
}

class ThemeDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("首页")),
      body: Center(
        child: Column(
          children: [
            Text("Hello World"),
            Text(
              "Hello World",
              style: TextStyle(fontSize: 14),
            ),
            Text(
              "Hello World",
              style: TextStyle(fontSize: 20),
            ),
            Text(
              "Hello World",
              style: Theme.of(context).textTheme.bodyText1,
            ),
            Text(
              "Hello World",
              style: Theme.of(context).textTheme.headline3,
            ),
            Switch(
              value: true,
              onChanged: (value) {},
            ),
            CupertinoSwitch(
              value: true,
              onChanged: (value) {},
              activeColor: Colors.red,
            ),
            RaisedButton(
              child: Text("R"),
              onPressed: () {},
            ),
            Card(
              child: Text(
                "Hello,Smile",
                style: TextStyle(fontSize: 50),
              ),
            )
          ],
        ),
      ),
      bottomNavigationBar: BottomNavigationBar(
        items: [
          BottomNavigationBarItem(label: '首页', icon: Icon(Icons.home)),
          BottomNavigationBarItem(label: '分类', icon: Icon(Icons.category))
        ],
      ),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.add),
        onPressed: () {
          Navigator.of(context).push(
            MaterialPageRoute(
              builder: (ctx) {
                return SecondPage();
              },
            ),
          );
        },
      ),
    );
  }
}

代码运行效果图如下:


效果图

如果某个具体的Widget不希望直接使用全局的Theme,而希望自己来定义,只需要在Widget的父节点包裹一下Theme即可。创建另外一个新的页面,页面中使用新的主题:在新的页面的Scaffold外,包裹了一个Theme,并且设置data为一个新的ThemeData,代码示例:

class SecondPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Theme(
      data: Theme.of(context).copyWith(primaryColor: Colors.purple),
      child: Scaffold(
        appBar: AppBar(
          title: Text("第二页"),
          backgroundColor: Colors.purple,
        ),
        body: Center(
          child: Text("Second Page"),
        ),
        floatingActionButton: Theme(
          data: Theme.of(context).copyWith(
            colorScheme:
                Theme.of(context).colorScheme.copyWith(secondary: Colors.pink),
          ),
          child: FloatingActionButton(
            child: Icon(Icons.pets),
            onPressed: () {},
          ),
        ),
      ),
    );
  }
}

代码运行效果图如下:


效果图

这里有一个注意事项:accentColor在这里并不会被覆盖。需要使用:

Theme.of(context).copyWith
(
   colorScheme:Theme.of(context).colorScheme.copyWith(secondary: Colors.pink),
)

代码传送门

你可能感兴趣的:(Flutter学习笔记34-主题)