自定义主题无法正常工作. [扑] [英] Custom theme not working properly. [Flutter]
问题描述
我为我的应用创建了以下主题:
ThemeData _buildDarkTheme() {
final baseTheme = ThemeData(fontFamily: "Sunflower",);
return baseTheme.copyWith(
brightness: Brightness.dark,
primaryColor: Colors.grey[800],
accentColor: Colors.grey[850]);
}
然后我将其应用到我的应用程序,如下所示:
class MyApp extends StatelessWidget {
MyApp({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return new MaterialApp(
theme: _buildDarkTheme(),
home: new Scaffold(
appBar: _buildAppBar(),
body: new Container(
color: Theme.of(context).accentColor,
height: double.infinity,
child: new ListView.builder(...
但是,当我尝试访问容器(或其他位置)内部的强调色而不是预期的Colors.grey [850]时,它默认为蓝色.另外,尝试使用自定义字体Sunflower字体系列不起作用,但是当我改用
时new Text("Hello World", style: new TextStyle(fontFamily: "Sunflower"))
字体正确显示.
我是扑扑和飞镖的新手,所以解决这些问题的任何帮助将不胜感激.
这与context
和Theme.of
的工作方式有关.
来自Theme类源代码:
static ThemeData of(BuildContext context, { bool shadowThemeOnly = false }) {
final _InheritedTheme inheritedTheme =
context.inheritFromWidgetOfExactType(_InheritedTheme);
if (shadowThemeOnly) {
if (inheritedTheme == null || inheritedTheme.theme.isMaterialAppTheme)
return null;
return inheritedTheme.theme.data;
}
final ThemeData colorTheme = (inheritedTheme != null) ? inheritedTheme.theme.data : _kFallbackTheme;
final MaterialLocalizations localizations = MaterialLocalizations.of(context);
final TextTheme geometryTheme = localizations?.localTextGeometry ?? MaterialTextGeometry.englishLike;
return ThemeData.localize(colorTheme, geometryTheme);
}
Theme.of
(以及Navigator.of(),...
.of()等),查看传递它们的上下文,然后向上遍历小部件树,以查找指定类型的小部件. /p>
现在,查看您的代码
Widget build(BuildContext context) {
return new MaterialApp(
theme: _buildDarkTheme(),
home: new Scaffold(
appBar: _buildAppBar(),
body: new Container(
color: Theme.of(context).accentColor,
您可以看到,传递给Theme.of
的context
实际上是所创建主题上方的上下文.因此,它将找不到您的主题,并将恢复为默认主题.这是因为窗口小部件树看起来类似于以下内容(忽略所有中间层,箭头指向您正在使用的上下文.
MyApp - context <--------
MaterialApp
Theme
Scaffold
有两种方法可以解决此问题;第一种是使用 Builder
类在其中构建小部件具有主题下方上下文的闭包.看起来像这样:
class MyApp extends StatelessWidget {
MyApp({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return new MaterialApp(
theme: _buildDarkTheme(),
home: new Scaffold(
appBar: _buildAppBar(),
body: new Builder(builder: (context) => new Container(
color: Theme.of(context).accentColor,
height: double.infinity,
child: new ListView.builder(...
))
这将使一棵树看起来像这样:
MyApp - context
MaterialApp
Theme
Scaffold
Builder - context <---------
另一个(首选)选项是将构建器的代码拆分为自己的类-StatelessWidget
继承的类或StatefulWidget
和State
对.
I have created the following theme for my app:
ThemeData _buildDarkTheme() {
final baseTheme = ThemeData(fontFamily: "Sunflower",);
return baseTheme.copyWith(
brightness: Brightness.dark,
primaryColor: Colors.grey[800],
accentColor: Colors.grey[850]);
}
I then apply it to my app as follows:
class MyApp extends StatelessWidget {
MyApp({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return new MaterialApp(
theme: _buildDarkTheme(),
home: new Scaffold(
appBar: _buildAppBar(),
body: new Container(
color: Theme.of(context).accentColor,
height: double.infinity,
child: new ListView.builder(...
However, when I try to access the accent color inside the container (or anywhere else) instead of it being the expected, Colors.grey[850], it instead defaults to blue. Also, trying to use the custom font Sunflower font family does not work, but when I instead use
new Text("Hello World", style: new TextStyle(fontFamily: "Sunflower"))
The font appears correctly.
I am new to flutter and dart so any help resolving these issues would be appreciated.
This is to do with how context
and Theme.of
work.
From the Theme class source code:
static ThemeData of(BuildContext context, { bool shadowThemeOnly = false }) {
final _InheritedTheme inheritedTheme =
context.inheritFromWidgetOfExactType(_InheritedTheme);
if (shadowThemeOnly) {
if (inheritedTheme == null || inheritedTheme.theme.isMaterialAppTheme)
return null;
return inheritedTheme.theme.data;
}
final ThemeData colorTheme = (inheritedTheme != null) ? inheritedTheme.theme.data : _kFallbackTheme;
final MaterialLocalizations localizations = MaterialLocalizations.of(context);
final TextTheme geometryTheme = localizations?.localTextGeometry ?? MaterialTextGeometry.englishLike;
return ThemeData.localize(colorTheme, geometryTheme);
}
Theme.of
(and Navigator.of(), ...
.of() etc), look at the context you pass them and then iterate upwards through the tree of widgets looking for a widget of the type specified.
Now, looking at your code
Widget build(BuildContext context) {
return new MaterialApp(
theme: _buildDarkTheme(),
home: new Scaffold(
appBar: _buildAppBar(),
body: new Container(
color: Theme.of(context).accentColor,
you can see that the context
you're passing into Theme.of
is actually the context above the theme you're creating. So it won't find your theme and will revert to the default. This is because the widget tree looks somewhat like the following (ignoring all the intermediate layers, with the arrow pointing to the context you're using.
MyApp - context <--------
MaterialApp
Theme
Scaffold
There are two ways to fix this; the first is to use a Builder
class to build your widget within a closure that has the context below the theme. That would look something like this:
class MyApp extends StatelessWidget {
MyApp({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return new MaterialApp(
theme: _buildDarkTheme(),
home: new Scaffold(
appBar: _buildAppBar(),
body: new Builder(builder: (context) => new Container(
color: Theme.of(context).accentColor,
height: double.infinity,
child: new ListView.builder(...
))
And it would make a tree that looks somewhat like this:
MyApp - context
MaterialApp
Theme
Scaffold
Builder - context <---------
The other (preferable) option is to split out the code for your builder into its own class - either a StatelessWidget
-inherited class or a StatefulWidget
and State
pair.
这篇关于自定义主题无法正常工作. [扑]的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!