Flutter 基础之 Theme 主题(样式篇)

article/2025/8/22 7:55:39

声明:本篇文章已授权微信公众号 YYGeeker 独家发布。
博主原创文章,转载请注明出处:小嵩的博客

一、介绍

Theme 类将主题应用于子控件,Theme(主题)它描述了应用程序的颜色和排版选择。Theme有两种:全局Theme和局部Theme。全局Theme是由应用程序根MaterialApp创建的Theme;而局部Theme是在应用程序某个区域范围中用于覆盖全局主题。

Google官网介绍:https://api.flutter.dev/flutter/material/Theme-class.html

构造函数

Theme({Key key,
@required ThemeData data,
bool isMaterialAppTheme: false, 
@required Widget child })
  • ThemeData data: 保存 Material 主题的颜色和字体等排版样式。
  • isMaterialAppTheme: 默认值是false ,表示是否为材料设计风格的主题。
  • child: 子控件。

继承关系

Object -> Diagnosticable -> DiagnosticableTree -> Widget -> StatelessWidget -> Theme。

二、ThemeData

从Theme的构造函数我们不难看出,Flutter 中是通过ThemeData去保存共享应用的主题及样式等信息的,因此我们继续翻一下官方文档,研究研究一下ThemeData包含了哪些知识点。

继承关系:
Object -> Diagnosticable -> ThemeData

构造函数:

ThemeData({Brightness brightness,
MaterialColor primarySwatch, 
Color primaryColor, 
Brightness primaryColorBrightness, 
Color primaryColorLight, 
Color primaryColorDark, 
Color accentColor, 
Brightness accentColorBrightness,
Color canvasColor, 
Color scaffoldBackgroundColor, 
Color bottomAppBarColor, 
Color cardColor, 
Color dividerColor, 
Color focusColor, 
Color hoverColor, 
Color highlightColor, 
Color splashColor, 
InteractiveInkFeatureFactory splashFactory, 
Color selectedRowColor, 
Color unselectedWidgetColor, 
Color disabledColor, 
Color buttonColor, 
ButtonThemeData buttonTheme,
Color secondaryHeaderColor,
Color textSelectionColor,
Color cursorColor, 
Color textSelectionHandleColor, 
Color backgroundColor, 
Color dialogBackgroundColor, 
Color indicatorColor, 
Color hintColor, 
Color errorColor, 
Color toggleableActiveColor, 
String fontFamily, 
TextTheme textTheme, 
TextTheme primaryTextTheme, 
TextTheme accentTextTheme, 
InputDecorationTheme inputDecorationTheme, 
IconThemeData iconTheme, 
IconThemeData primaryIconTheme, 
IconThemeData accentIconTheme, 
SliderThemeData sliderTheme, 
TabBarTheme tabBarTheme,
CardTheme cardTheme, 
ChipThemeData chipTheme, 
TargetPlatform platform, 
MaterialTapTargetSize materialTapTargetSize, 
PageTransitionsTheme pageTransitionsTheme,
AppBarTheme appBarTheme,
BottomAppBarTheme bottomAppBarTheme, 
ColorScheme colorScheme, 
DialogTheme dialogTheme, 
FloatingActionButtonThemeData floatingActionButtonTheme, 
Typography typography, 
CupertinoThemeData cupertinoOverrideTheme, 
SnackBarThemeData snackBarTheme, 
BottomSheetThemeData bottomSheetTheme })

从其构造函数不难看出,它主要保存了各种颜色及字体、Icon样式等设置。由于属性过多,我们挑一些常用的讲一讲:

  • brightness - Brightness类型,应用程序的整体主题亮度。用于按钮等小部件,以确定在不使用主色(primaryColor)或强调色(accentColor)时选择什么颜色。当亮度较暗时,画布、卡片和原色都较暗。当亮度为光时,画布和卡片的颜色是明亮的,原色的暗度根据原色亮度变化。当亮度较暗时,原色(primaryColor)与卡片和画布颜色的对比度较差;当亮度较暗时,用白色或亮蓝色来对比。

  • primarySwatch - MaterialColor 类型,Material 主题中定义一种颜色,它具有十种颜色阴影的颜色样本。值越大颜色越深,10个有效的index分别为:50,100,200,…,900。默认是取中间值500。

  • primaryColor - Color类型,App主要部分的背景色(ToolBar,Tabbar等)

  • primaryColorBrightness - Brightness类型,primaryColor的亮度,用于确定设置在primaryColor上部的文本和图标颜色(如:工具栏文本(toolbar text))。

  • primaryColorLight - Color类型,primaryColor的较浅版本

  • primaryColorDark - Color类型,primaryColor的较深版本

  • accentColor - Color类型,前景色(按钮、文本、覆盖边缘效果等)

  • accentColorBrightness - Brightness类型,accentColor的亮度。用于确定位于accentColor上部的文本和图标颜色(例如,浮动操作按钮(FloatingButton)上的图标)

  • canvasColor - Color类型,MaterialType.canvas Material的默认颜色。

  • scaffoldBackgroundColor - Color类型,作为Scaffold下的Material默认颜色,用于materia应用程序或app内页面的背景色。

  • bottomAppBarColor - Color类型,bottomAppBarColor的默认颜色。这可以通过指定BottomAppBar.color来覆盖。

  • cardColor - Color类型,用在卡片(Card)上的Material的颜色。

  • dividerColor - Color类型,分隔符(Dividers)和弹窗分隔符(PopupMenuDividers)的颜色,也用于ListTiles和DataTables的行之间。要创建使用这种颜色的合适的边界,请考虑Divider.createBorderSide。

  • highlightColor - Color类型,用于墨水喷溅动画或指示菜单被选中时的高亮颜色

  • splashColor - Color类型,墨水溅出的颜色

  • splashFactory - InteractiveInkFeatureFactory类型,定义InkWall和InkResponse产成的墨水喷溅时的外观。

  • selectedRowColor - Color类型,用于高亮选定行的颜色。

  • unselectedWidgetColor - Color类型,小部件处于非活动(但启用)状态时使用的颜色。例如,未选中的复选框。通常与accentColor形成对比。

  • disabledColor - Color类型,无效的部件(widget)的颜色,不管它们的状态如何。例如,一个禁用的复选框(可以选中或不选中)。

  • buttonColor - Color类型,Material中RaisedButtons使用的默认填充色。

  • buttonTheme - ButtonThemeData类型,定义按钮小部件的默认配置,如RaisedButton和FlatButton。

  • secondaryHeaderColor - Color类型,有选定行时PaginatedDataTable标题的颜色

  • textSelectionColor - Color类型,文本字段(如TextField)中文本被选中的颜色。

  • cursorColor - Color类型,在 Material-style 文本字段(如TextField)中光标的颜色。

  • textSelectionHandleColor - Color类型,用于调整当前选定文本部分的句柄的颜色。

  • backgroundColor - Color类型,与primaryColor对比的颜色(例如 用作进度条的剩余部分)。

  • dialogBackgroundColor - Color类型,Color类型,Dialog元素的背景色

  • indicatorColor - Color类型,TabBar中选项选中的指示器颜色。

  • hintColor - Color类型,用于提示文本或占位符文本的颜色,例如在TextField中。

  • errorColor - Color类型,用于输入验证错误的颜色,例如在TextField中。

  • toggleableActiveColor - Color类型,用于突出显示切换Widget(如Switch,Radio和Checkbox)的活动状态的颜色。

  • fontFamily - String类型,字体类型

  • textTheme - TextTheme类型,与卡片和画布对比的文本颜色

  • primaryTextTheme - TextTheme类型,与primary color形成对比的文本主题。

  • accentTextTheme - TextTheme类型,与accent color形成对比的文本主题。

  • inputDecorationTheme - InputDecorationTheme类型,InputDecorator、TextField和TextFormField的默认InputDecoration值基于此主题。

  • iconTheme - IconThemeData类型,与卡片和画布颜色形成对比的图标主题。

  • primaryIconTheme - IconThemeData类型,与原色(primary color)形成对比的图标主题。

  • accentIconTheme - IconThemeData类型,与前景色(accent color)形成对比的图标主题。

  • sliderTheme - SliderThemeData类型,SliderThemeData类型,用于渲染Slider的颜色和形状。

  • tabBarTheme - TabBarTheme类型, 一个主题,用于自定义选项卡栏指示器的尺寸、形状和颜色。

  • chipTheme - ChipThemeData类型,用于Chip的颜色和样式

  • platform - TargetPlatform类型,widget应该适应目标的平台。

  • materialTapTargetSize - MaterialTapTargetSize类型,配置特定材料部件的hit测试大小。

  • pageTransitionsTheme - PageTransitionsTheme类型,每个目标平台的默认MaterialPageRoute转换。

  • colorScheme
    ColorScheme类型,一组13种颜色,可用于配置大多数组件的颜色属性。

  • typography - Typography类型,用于配置TextTheme、primaryTextTheme和accentTextTheme的颜色和几何文本主题值。

三、Theme.of 方法

它是一个 static 方法。子控件通过使用Theme.of来获取当前主题的ThemeData对象,当控件使用Theme.of时,如果主题稍后更改,则会自动重建以便可以应用更改。我们可以通过Theme.of查看当前应用程序的配色方案。

ThemeData.of 方法代码:

ThemeData of (
BuildContext context, {
bool shadowThemeOnly: false
})

ThemeData数据来自最近的给定上下文的Theme实例。如果给定的 context 包含在提供MaterialLocalizations的Localizations部件中,则返回的数据将根据最近的可用MaterialLocalizations进行本地化。如果给定的构建上下文中没有主题,则默认为新的ThemeData.fallback。

示例用法如下:

@override
Widget build(BuildContext context) {return Text('Theme Example',style: Theme.of(context).textTheme.title,);
}

到这里我们已经知道如何去设置flutter主题了,在flutter中,主题又分全局主题和局部主题。接下来我们讲解一下这两种方式的适用场景及区别。

四、全局主题

在创建应用全局主题时,我们提供一个ThemeData对象给MaterialApp即可,如果构造函数没有设置ThemeData,则Flutter会创建一个默认的主题。下面我们实践一下,写个自定义全局主题的简单示例:

import 'package:flutter/material.dart';void main() => runApp(MyApp());class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(brightness: Brightness.light, //指定亮度主题,有白色/黑色两种可选。primaryColor: Colors.blue[800], //这里我们选蓝色为基准色值。accentColor: Colors.lightBlue[100]), //这里我们选浅蓝色为强调色值。home: ThemeTest(),);}
}class ThemeTest extends StatelessWidget {@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("ThemeTest"), //页面标题),body: Container(color: Theme.of(context).primaryColor, //内容背景颜色margin: EdgeInsets.all(100.0),padding: EdgeInsets.all(10.0),child: Text("MaterialApp Theme Color", //内容文本style: TextStyle(fontSize: 20, color: Theme.of(context).accentColor), //内容文本颜色,引用的是accentColor。textAlign: TextAlign.center,),),);}
}

效果图如下:

theme.jpg

五、局部主题

局部主题是在应用程序某些区域中,用于覆盖全局主题。我们定义好一个主题后,就可以在Widget的build方法中通过Theme.of(context)方法来使用它。Theme.of(context)将查找Widget树并返回树中最近的Theme。如果Widget之上有一个单独的局部Theme定义,则返回该主题的值;如果不是,则返回App全局主题。我们讲一下主要的几种创建方法:

5.1 重新创建Theme对象

通过重新创建Theme的方式,创建一个实例, 并重新创建ThemeData,赋值给data。然后指定child Widget,将ThemeData传递给Theme Widget,代码如下:

import 'package:flutter/material.dart';void main() => runApp(MyApp());class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(brightness: Brightness.light, //指定亮度主题,有白色/黑色两种可选。primaryColor: Colors.blue[800], //这里我们选蓝色为基准色值。accentColor: Colors.lightBlue[100]), //这里我们选浅蓝色为强调色值。home: Theme(data: ThemeData(accentColor: Colors.yellow),child: ThemeTest())); //创建局部主题,将accentColor设置为黄色}
}class ThemeTest extends StatelessWidget {@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("ThemeTest"),),body: Container(color: Theme.of(context).primaryColor,margin: EdgeInsets.all(100.0),padding: EdgeInsets.all(10.0),child: Text("MaterialApp Theme Color",style: TextStyle(fontSize: 20, color: Theme.of(context).accentColor), //应用局部主题颜色textAlign: TextAlign.center,)),);}
}

效果图如下:

局部主题-黄色.jpg

局部主题不生效问题

这里有个小坑点需要注意,我们需要在Widget的父层Widget去设置局部Theme,才会生效;如果我们直接在局部Theme的child 属性指定的Widget中去使用的话,会拿到系统的全局Theme.

如下示例:

import 'package:flutter/material.dart';void main() => runApp(MyApp());class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(brightness: Brightness.light, //指定亮度主题,有白色/黑色两种可选。primaryColor: Colors.blue[800], //这里我们选蓝色为基准色值。accentColor: Colors.white), //设置为白色。home: ThemeTest(),);}
}class ThemeTest extends StatelessWidget {@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("ThemeTest"),//页面标题),body: Container(color: Theme.of(context).primaryColor,margin: EdgeInsets.all(100.0),padding: EdgeInsets.all(10.0),child: Theme(data: ThemeData(accentColor: Colors.red), //设置红色//创建accentColor 为绿色的局部主题,若局部主题Theme 的Child 是 Text,则Text引用局部主题色不会生效,拿到的还是局部Themes上层的值,即全局主题的值。child: Text("MaterialApp Theme Color",style: TextStyle(fontSize: 20, color: Theme.of(context).accentColor), //应用主题色textAlign: TextAlign.center,))),);}
}

效果图如下:

局部主题不生效.jpg

可以从截图看到,Text显示的颜色依旧是白色,并未变成我们所期望的红色,因此我们使用的时候需要额外注意这点。

5.2 扩展父主题

除了 创建Theme 对象的方式去使用局部主题,我们可以通过使用copyWith方法来实现,这样的话,我们去修改父主题时,无需覆盖所有的主题属性,只需要将我们想改动的属性指定即可。

将原先的:

data: ThemeData(accentColor: Colors.yellow)

改成:

Theme.of(context).copyWith(accentColor: Colors.yellow)

这样一来,我们的局部主题除了accentColor改成了指定值,其他属性依然可以使用它上一层 Theme的属性值,而不是变成系统默认的。

5.3 根据设备平台设置不同主题

除了上述两种方法之外,我们还可以根据设备的平台类型(iOS,Android和Fuchsia)去提供不同的主题:

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';void main() => runApp(MyApp());class MyApp extends StatelessWidget {final ThemeData iOSTheme = ThemeData(brightness: Brightness.light,primaryColor: Colors.grey[600],accentColor: Colors.white,);final ThemeData androidTheme = ThemeData(brightness: Brightness.dark,primaryColor: Colors.yellow[300],accentColor: Colors.deepPurple[800],);@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(brightness: Brightness.light,primaryColor: Colors.grey[100],accentColor: Colors.white,),home: Theme(data: defaultTargetPlatform == TargetPlatform.android? androidTheme: iOSTheme,child: ThemeTest()),);}
}class ThemeTest extends StatelessWidget {@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("ThemeTest"),),body: Container(color: Theme.of(context).primaryColor,margin: EdgeInsets.all(100.0),padding: EdgeInsets.all(10.0),child: Text("MaterialApp Theme Color",style:TextStyle(fontSize: 20, color: Theme.of(context).accentColor),textAlign: TextAlign.center,)),);}
}

Android 端效果图:

Android 端局部主题

iOS 端效果图:

iOS 端局部主题

六、总结

本篇文章主要讲述了Theme 的一些常用方法及属性。同时对全局主题、局部主题、不同平台主题的设置方法也做了较详细的实践示例,在flutter 中对主题的设置相对而言比较灵活,大家可以多多实践操作一波。


http://chatgpt.dhexx.cn/article/HDnfA3Mk.shtml

相关文章

Android中Theme主题和Style样式使用介绍总结

1.Theme主题 1.1.Theme主题作用范围 Theme主要是针对应用级别的或者说窗体级别,可以设置应用主题(应用换肤效果)和Activity的主题;主题是不能应用在某一个单独的View中;或者说Theme是用来设置应用全局主题风格的&…

【转】提升工作效率的一些小技巧——资源管理器篇

当我看到有人打开资源管理器,一个一个文件夹点进去,再点出来,我就着急。特别是有人在会议上打开我的电脑,然后寻找文件,我就特别捉急,这不只是在浪费自己的时间,还浪费参加会议人的时间。 我把资…

WPF 4 开发Windows 7 任务栏(Overlay Icon、Thumbnail Toolbar、Progress Bar)

在上一篇我们介绍了如何在WPF 4 中开发Windows 7 跳转列表,本篇将继续针对WPF 4 中任务栏其他功能:覆盖图标(Overlay Icon)、进度条(Progress Bar)、缩略图工具栏(Thumbnail Toolbar&#xff09…

HTML+CSS提升小实战

1 <html>2 <head>3 <meta http-equiv"Content-Type" content"text/html; charsetutf-8" />4 <title>几米简介</title>5 <style type"text/css">6 *{7 margin:0px;padding:0px;8 …

java实现qlearning,DQN(Deep Q-learning)入门教程(一)之强化学习介绍

什么是强化学习? 强化学习(Reinforcement learning,简称RL)是和监督学习,非监督学习并列的第三种机器学习方法,如下图示: 首先让我们举一个小时候的例子: 你现在在家,有两个动作选择:打游戏和读书。如果选择打游戏的话,你就跑到了网吧,选择读书的话,就坐在了书桌面前…

实验一 书桌

实验内容&#xff1a; 了解四种视图&#xff0c;在绘制时&#xff0c;从不同的视图进行观察&#xff0c;提高绘制效率。知道常用工具的快捷键 一、四种视图 1、顶视图&#xff08;T&#xff09; 2、前视图&#xff08;F&#xff09; 3、左视图&#xff08;L&#xff09; 4、透…

学计算机的桌面,三个软件,干净你的电脑桌面,让你更高效工作学习!

文 | 谦行公子 首发 | 谦行公子 今天向大家推荐三个软件&#xff0c;为了就是让大家都拥有一个干净整洁的桌面&#xff0c;从此高效地学习生活&#xff5e;至于哪三个&#xff0c;接着看 相信很多人都有这样的经历&#xff0c;连续工作好几天甚至好几周&#xff0c;桌面上堆满…

小Q书桌 - 最完美纯净的任务栏Bins

虽然&#xff0c;TX 在众多网友的 眼中 都是山寨的代名词&#xff0c;都曾经很BS之。 诚然&#xff0c;鄙人也是对其某些作品不太满意。 但是&#xff0c;TX 仍有那么一些人再默默坚持着&#xff0c;给我们纯净的软件&#xff0c;纯净的视觉盛宴。 ……………………………………

【电脑管家之小Q书桌】

前言&#xff1a; 生活之中处处有知识&#xff0c;前几天&#xff0c;自己电脑无意间弹出了广告&#xff0c;心想&#xff0c;难道是最近重装了系统&#xff0c;电脑管家防广告功能关闭了&#xff0c;于是就去看了电脑管家&#xff0c;一切设置好后&#xff0c;一个好奇心又引导…

小Q书桌的下载、安装和使用

最近&#xff0c;无意之间&#xff0c;在某大牛电脑里&#xff0c;使用到了这款软件。感谢&#xff01; 确实&#xff0c;挺实用和方便的&#xff0c;强烈推荐&#xff01;&#xff01;&#xff01; 1、 下载 http://qdesk.qq.com/ 2、 安装 3、 使用 多么方便啊&#xff01…

腾讯小Q书桌图标怎么实现的啊?

Win7&#xff1a; 红色区域&#xff1a;类名是Shell_TrayWnd的容器 黄色区域&#xff1a;类名是ReBarWindow32的二级容器 绿色区域&#xff1a;类名是MSTaskSwWClass的窗口 WinXP&#xff1a; 红色区域&#xff1a;红色区域——类名是Shell_TrayWnd的容器…

小Q书桌支持WIN10完美运行 关于win10不兼容小q书桌

原文出处: https://zhuanlan.zhihu.com/p/62378877 背景&#xff1a; 小Q书桌是一款简洁易用的桌面图标管理工具&#xff0c;几年前就开始使用。 由于win10的普及&#xff0c;目前更换为win10系统&#xff0c;但由于小Q书桌已经很多年没更新&#xff0c;导致出现以下兼容问题&a…

小i机器人伴侣_【数据分析】2020年3月全国工业机器人产量统计数据分析

前 言 据中商产业研究院数据库显示&#xff0c;2020年1季度全国工业机器人产量波动幅度较小&#xff0c;2020年3月全国工业机器人产量为17241套&#xff0c;同比增长12.9%。2020年1季度全国工业机器人产量为34645.3套&#xff0c;同比下降8.2%。 数据来源&#xff1a;中商产业…

一个眼神 比亚迪车载机器人为你点歌

无论是通过触摸屏还是语音控制&#xff0c;车载系统的目的都是为了提供更多驾驶乐趣。在北京车展上&#xff0c;比亚迪推出“秦”电动车&#xff0c;其仪表台上配备的“i”机器人可通过表情、动作和语音和驾驶者互动&#xff0c;提供多种服务。 这个小机器人采用了一个微笑的卡…

聊天机器人的“高情商”炼成术

聊天机器人&#xff0c;是一种通过自然语言模拟人类进行对话的程序。通常运行在特定的软件平台上&#xff0c;如PC平台或者移动终端设备平台&#xff0c;而类人的硬件机械体则不是必需的承载设备。 聊天机器人的研究源于图灵(Alan M. Turing)在1950年《Mind》上发表的文章《Com…

中国机器人市场增速震惊全世界!这6大机器人你听过几个?

人工智能的火爆&#xff0c;让机器人创业的浪潮广泛引起了企业的关注&#xff0c;很多企业选择了或投资或自己研发的方式加入这场狂欢&#xff0c;这对于行业整体的发展来说是良性的&#xff0c;各大企业的加入&#xff0c;它们丰富的资源可以推动机器人行业的快速发展。 那么&…

机器人跟踪_使用手机和机器学习跟踪睡眠

机器人跟踪 The code project can be found on https://github.com/josephbima/sleep-tracker 该代码项目可在https://github.com/josephbima/sleep-tracker上找到 I’ve always wondered the exact time I actually spend sleeping at night. So when I needed ideas for the …

活动 | 腾讯×Nature Research:提问AI与机器人的未来

「 42. 」 这是科幻小说《银河系漫游指南》中智能计算机「Deep Thought&#xff08;深思&#xff09;」经过750万年运算&#xff0c;找到的「关于生命&#xff0c;宇宙及一切问题的终极答案」。 为什么是42&#xff1f;「深思」把这个问题交给了一台更高智能的电脑——地球来回…

机器人影视对接_机器学习对接会

机器人影视对接 A simple question like ‘How do you find a compatible partner?’ is what pushed me to try to do this project in order to find a compatible partner for any person in a population, and the motive behind this blog post is to explain my approac…

【AI视野·今日Robot 机器人论文速览 第十六期】Tue, 29 Jun 2021

AI视野今日CS.Robotics 机器人学论文速览 Tue, 29 Jun 2021 Totally 28 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Robotics Papers If you trust me, I will trust you: the role of reciprocity in human-robot trust Authors Joshua Zonca, Anna Folso, Ale…