前言

Color类中颜色以一个int值保存,显示器颜色是由红、绿、蓝三基色组成,每种颜色占8比特,存储结构如下:

Bit(位) 颜色
0-7 蓝色
8-15 绿色
16-23 红色
24-31 Alpha(不透明度)

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

接口描述

factory ThemeData({
// 深色还是浅色
Brightness brightness,
// 主题颜色样本
MaterialColor primarySwatch,
// 主色,决定导航栏颜色
Color primaryColor,
Brightness primaryColorBrightness,
Color primaryColorLight,
Color primaryColorDark,
// 次级色,决定大多数Widget的颜色,如进度条、开关等
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,
ToggleButtonsThemeData toggleButtonsTheme,
Color secondaryHeaderColor,
Color textSelectionColor,
// 输入框光标颜色
Color cursorColor,
Color textSelectionHandleColor,
Color backgroundColor,
// 对话框背景颜色
Color dialogBackgroundColor,
Color indicatorColor,
Color hintColor,
Color errorColor,
Color toggleableActiveColor,
// 文字字体
String fontFamily,
// 字体主题,包括标题、body等文字样式
TextTheme textTheme,
TextTheme primaryTextTheme,
TextTheme accentTextTheme,
InputDecorationTheme inputDecorationTheme,
// Icon的默认样式
IconThemeData iconTheme,
IconThemeData primaryIconTheme,
IconThemeData accentIconTheme,
SliderThemeData sliderTheme,
TabBarTheme tabBarTheme,
TooltipThemeData tooltipTheme,
CardTheme cardTheme,
ChipThemeData chipTheme,
// 指定平台,应用特定平台控件风格
TargetPlatform platform,
MaterialTapTargetSize materialTapTargetSize,
bool applyElevationOverlayColor,
PageTransitionsTheme pageTransitionsTheme,
AppBarTheme appBarTheme,
BottomAppBarTheme bottomAppBarTheme,
ColorScheme colorScheme,
DialogTheme dialogTheme,
FloatingActionButtonThemeData floatingActionButtonTheme,
Typography typography,
CupertinoThemeData cupertinoOverrideTheme,
SnackBarThemeData snackBarTheme,
BottomSheetThemeData bottomSheetTheme,
PopupMenuThemeData popupMenuTheme,
MaterialBannerThemeData bannerTheme,
DividerThemeData dividerTheme,
ButtonBarThemeData buttonBarTheme,
}) {
brightness ??= Brightness.light;
final bool isDark = brightness == Brightness.dark;
primarySwatch ??= Colors.blue;
primaryColor ??= isDark ? Colors.grey[900] : primarySwatch;
primaryColorBrightness ??= estimateBrightnessForColor(primaryColor);
primaryColorLight ??= isDark ? Colors.grey[500] : primarySwatch[100];
primaryColorDark ??= isDark ? Colors.black : primarySwatch[700];
final bool primaryIsDark = primaryColorBrightness == Brightness.dark;
toggleableActiveColor ??= isDark ? Colors.tealAccent[200] : (accentColor ?? primarySwatch[600]);
accentColor ??= isDark ? Colors.tealAccent[200] : primarySwatch[500];
accentColorBrightness ??= estimateBrightnessForColor(accentColor);
final bool accentIsDark = accentColorBrightness == Brightness.dark;
canvasColor ??= isDark ? Colors.grey[850] : Colors.grey[50];
scaffoldBackgroundColor ??= canvasColor;
bottomAppBarColor ??= isDark ? Colors.grey[800] : Colors.white;
cardColor ??= isDark ? Colors.grey[800] : Colors.white;
dividerColor ??= isDark ? const Color(0x1FFFFFFF) : const Color(0x1F000000);

代码示例

// 颜色和主题(Theme)

import 'package:flutter/material.dart';

// 实现一个背景颜色和Title可以自定义的导航栏,并且背景色为深色时我们应该让Title显示为浅色;背景色为浅色时,Title显示为深色。
class NavBar extends StatelessWidget{
final String title;
// 背景颜色
final Color color; NavBar({
Key key,
this.color,
this.title,
}); @override
Widget build(BuildContext context){
return Container(
constraints: BoxConstraints(
minHeight: 52,
minWidth: double.infinity,
),
decoration: BoxDecoration(
color: color,
boxShadow: [
// 阴影
BoxShadow(
color: Colors.black26,
offset: Offset(0, 3),
blurRadius: 3,
),
],
),
child: Text(
title,
style: TextStyle(
fontWeight: FontWeight.bold,
// 根据背景色亮度来确定Title颜色
color: color.computeLuminance() < 0.5 ? Colors.white: Colors.black,
),
),
alignment: Alignment.center,
);
} } class NavBarTest extends StatelessWidget{ Widget build(BuildContext context){
return Scaffold(
appBar: AppBar(
title: Text("颜色"),
),
body: Column(
children: <Widget>[
// 背景色为蓝色,则title自动为白色
NavBar(color: Colors.blue, title: "标题",),
// 背景色为白色,则title自动为黑色
NavBar(color: Colors.white, title: "标题",)
],
)
);
}
} // 路由换肤
class ThemeTest extends StatefulWidget{ @override
_ThemeTestState createState() => _ThemeTestState();
} class _ThemeTestState extends State<ThemeTest>{
// 当前路由主颜色
Color _themeColor = Colors.teal; @override
Widget build(BuildContext context){
ThemeData themeData = Theme.of(context); return Theme(
data: ThemeData(
// 用于导航栏、FloatingActionButton的背景色
primarySwatch: _themeColor,
// 用于Icon颜色
iconTheme: IconThemeData(color: _themeColor),
),
child: Scaffold(
appBar: AppBar(
title: Text("主题测试"),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
// 第一行Icon使用主题中的iconTheme
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(Icons.favorite),
Icon(Icons.airport_shuttle),
Text("颜色跟随主题"),
],
),
// 为第二行Icon自定义颜色,固定为黑色
Theme(
data: themeData.copyWith(
iconTheme: themeData.iconTheme.copyWith(
color: Colors.black,
),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(Icons.favorite),
Icon(Icons.airport_shuttle),
Text("颜色固定黑色")
],
),
),
],
),
floatingActionButton: FloatingActionButton(
// 切换主题
onPressed: () => setState(
() => _themeColor = _themeColor == Colors.teal ? Colors.blue: Colors.teal,
),
child: Icon(Icons.palette),
),
),
);
}
}

总结

将颜色字符串转成Color对象

Color(0xffdc380d); //如果颜色固定可以直接使用整数值
//颜色是一个字符串变量
var c = "dc380d";
Color(int.parse(c,radix:16)|0xFF000000) //通过位运算符将Alpha设置为FF
Color(int.parse(c,radix:16)).withAlpha(255) //通过方法将Alpha设置为FF

MaterialColor

MaterialColor是实现Material Design中的颜色的类,它包含一种颜色的10个级别的渐变色。MaterialColor通过"[]"运算符的索引值来代表颜色的深度,有效的索引有:50,100,200,…,900,数字越大,颜色越深。MaterialColor的默认值为索引等于500的颜色。

换肤需要注意的问题

  • 可以通过局部主题覆盖全局主题,正如代码中通过Theme为第二行图标指定固定颜色(黑色)一样,这是一种常用的技巧,Flutter中会经常使用这种方法来自定义子树主题。那么为什么局部主题可以覆盖全局主题?这主要是因为widget中使用主题样式时是通过Theme.of(BuildContext context)来获取的。

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

// 简化代码,并非源码

return context.inheritFromWidgetOfExactType(_InheritedTheme).theme.data

}

context.inheritFromWidgetOfExactType 会在widget树中从当前位置向上查找第一个类型为_InheritedTheme的widget。所以当局部指定Theme后,其子树中通过Theme.of()向上查找到的第一个_InheritedTheme便是我们指定的Theme。
* 想要对整个应用换肤,则可以去修改MaterialApp的theme属性。

【Flutter】功能型组件之颜色和主题的更多相关文章

  1. flutter Container组件和Text组件

    在开始之前,我们先写一个最简单的入口文件:     后面,都是在这个结构的基础上面完成的. 由于Container组件和Text组件都是写在body里面的,所以下面,先将body抽离成一个组件的形式. ...

  2. Flutter InkWell - Flutter每周一组件

    Flutter Inkwell使用详解 该文章属于[Flutter每周一组件]系列,其它组件可以查看该系列下的文章,该系列会不间断更新:所有组件的demo已经上传值Github: https://gi ...

  3. Flutter ListTile - Flutter每周一组件

    该文章属于[Flutter每周一组件]系列,其它组件可以查看该系列下的文章,该系列会不间断更新:所有组件的demo已经上传值Github: https://github.com/xj124456/fl ...

  4. wpf/winform获取windows10系统颜色和主题色

    Windows10开始微软在系统颜色中添加了深色,对于UWP来说很轻松就能获取到系统当前的颜色和主题色,而对于Win32应用就没有那么直观了. 在wpf中,可以通过SystemParameters.W ...

  5. Flutter 父子组件传值

    Flutter 父子组件传值 一父传子: 父中: void onButtonChange(val1,val2,val3){ print('============================子向父 ...

  6. 如何在Vim中更改颜色和主题

    大家好,我是良许. Vim是我们在Linux中非常常用的一款文本编辑器.Vim 是一款免费.开源的文本编辑器,它的功能和许多其他的文本编辑器大致相同,比如 Sublime 和 Notepad++ .V ...

  7. 【Flutter】功能型组件之对话框详解

    前言 对话框本质上也是UI布局,通常一个对话框会包含标题.内容,以及一些操作按钮,为此,Material库中提供了一些现成的对话框组件来用于快速的构建出一个完整的对话框. 接口描述 // 1. Ale ...

  8. 【Flutter】功能型组件之数据共享

    前言   InheritedWidget提供了一种数据在widget树中从上到下传递.共享的方式,例如在应用的根widget中通过InheritedWidget共享了一个数据,那么便可以在子widge ...

  9. 【Flutter】功能型组件之异步UI更新

    前言 很多时候会依赖一些异步数据来动态更新UI,比如在打开一个页面时我们需要先从互联网上获取数据,在获取数据的过程中我们显示一个加载框,等获取到数据时我们再渲染页面:又比如想展示Stream(比如文件 ...

随机推荐

  1. 推荐系统实践 0x0d GBDT+LR

    前一篇文章我们介绍了LR->FM->FFM的整个演化过程,我们也知道,效果最好的FFM,它的计算复杂度已经达到了令人发指的\(n^2k\).其实就是这样,希望提高特征交叉的维度来弥补稀疏特 ...

  2. 【NOI2018】你的名字(SAM & 线段树合并)

    Description Hint Solution 不妨先讨论一下无区间限制的做法. 首先"子串"可以理解为"前缀的后缀",因此我们定义一个 \(\lim(i) ...

  3. js日期格式化-----总结

    1. // 对Date的扩展,将 Date 转化为指定格式的String // 月(M).日(d).小时(h).分(m).秒(s).季度(q) 可以用 1-2 个占位符, // 年(y)可以用 1-4 ...

  4. html文本域textarea高度自增、自动换行

    文本域自动换行.高度自增,采用以下方式: html: <textarea rows="1" class="answerTextArea" maxlengt ...

  5. STL——容器(Set & multiset)的概念和特点

    1. Set 和 multiset 的概念 set 和 multiset 是一个集合容器,其中 set 所包含的元素是唯一的,集合中的元素按一定的顺序排列.set 采用红黑树变体的数据结构实现,红黑树 ...

  6. STL—— 容器(vector)的数据写入、修改和删除

    1. 通过 push_back() 尾部增加一个元素 : vector 可以通过 "push_back " 写入数据,通过 push_back 可以将数据直接写入至 vector ...

  7. zstd c++ string 压缩&解压

    zstd 简介 维基百科定义: Zstandard(或Zstd)是由Facebook的Yann Collet开发的一个无损数据压缩算法.该名称也指其C语言的参考实现.第1版的实现于2016年8月31日 ...

  8. JavaSE01-概述

    1.1 Java语言发展史 语言:人与人交流沟通的表达方式 计算机语言:人与计算机之间进行信息交流沟通的一种特殊语言 Java语言是美国Sun公司(Stanford University Networ ...

  9. JAVA基础学习1

    一.JAVA是一种具有多种功能的高级语言:1,可以用于开发web页面上的小程序,桌面上运行的应用程序: 2,用于客户端服务器资源通讯的服务器端中间件: 3,还可以用于web服务器. 二.程序设计的5个 ...

  10. DRF类视图让你的代码DRY起来

    刚开始写views.py模块的代码,一般都是用def定义的函数视图,不过DRF更推荐使用class定义的类视图,这能让我们的代码更符合DRY(Don't Repeat Yourself)设计原则: 使 ...