Reputation: 625
I need to inherit the theme on my custom ListTile.
I have created a custom ListTile without inherit from it, just a statefull series of widget. How can I make this inherit all the theme from ListTile?
Normally I will normally achieve this going on single widget and setting a specific value to Theme.of(context).whateverTheme.whateverValue
. Until now worked flowless but now I see that there is not a .ListViewTheme
or .ListTileTheme
to use even if list_tile.dart have it. It is probably not exposed.
This make me question myself if this is the right way to do this.
Look for the <= I want here
in the code
class CustomMenuTile extends StatefulWidget {
CustomMenuTile({Key key, this.selected, this.icon, this.text, this.routePage})
: super(key: key);
final bool selected;
final IconData icon;
final String text;
final Widget routePage;
@override
_CustomMenuTileState createState() => _CustomMenuTileState();
}
class _CustomMenuTileState extends State<CustomMenuTile> {
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
constraints: BoxConstraints.expand(height: 48),
child: Material(
color: widget.selected ? kPrimarySwatch[400].withAlpha(100) : null,
borderRadius: BorderRadius.all(Radius.circular(4)),
child: InkWell(
splashColor: Colors.grey.withAlpha(64),
highlightColor: Colors.grey.withAlpha(64),
borderRadius: BorderRadius.all(Radius.circular(4)),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0),
child: Row(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(right: 24),
child: Icon(widget.icon,
color: widget.selected
? Theme.of(context).accentColor
: null, <= I want here Theme.of(context).ListViewTheme.iconColor
)),
Text(widget.text,
style: TextStyle(
fontWeight: FontWeight.bold,
color: widget.selected
? Theme.of(context).accentColor
: null)),
],
),
),
onTap: () {
Navigator.pop(context);
Navigator.of(context)
.pushReplacement(_createFadeRoute(widget.routePage));
}),
),
);
}
}
Upvotes: 1
Views: 3832
Reputation: 10963
You could use ListTileTheme.of(context).textColor
or whatever property of ListTileTheme
.
If the app doesn't define a ListTileTheme
, all the properties returns null
. In that case, ListTile
define it's own values. You could look at the default values of ListTile
and use that if a property of ListTileTheme
is null
Upvotes: 1
Reputation: 625
Looking inside the list_tile.dart seems that the color is taking the color from the ListTileTheme but as soon as you don't wrap al your code in a ListTileTheme widget the app is behaving like it doesn't have one which in fact is true.
In this case so it just go for the hardcoded color Colors.black45 but this happen just for the icon of the ListTile not the normal Icon widget.
Color _iconColor(ThemeData theme, ListTileTheme tileTheme) {
if (!enabled)
return theme.disabledColor;
if (selected && tileTheme?.selectedColor != null)
return tileTheme.selectedColor;
if (!selected && tileTheme?.iconColor != null)
return tileTheme.iconColor;
switch (theme.brightness) {
case Brightness.light:
return selected ? theme.primaryColor : Colors.black45;
case Brightness.dark:
return selected ? theme.accentColor : null; // null - use current icon theme color
}
assert(theme.brightness != null);
return null;
}
There is an open issue on github about the missing TileListTheme on ThemeData. https://github.com/flutter/flutter/issues/31247
Here a complete example of the workaround:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ListTileTheme(
iconColor: Colors.blue,
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key}) : super(key: key);
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("ListTileTheme example"),
),
body: ListView(
children: <Widget>[
ListTile(
title: Text("ListTile IS inheriting the color"),
leading: Icon(Icons.list),
),
Row(
children: <Widget>[
Icon(Icons.list),
Text("Other Icon is NOT inheriting the color..."),
],
),
Row(
children: <Widget>[
Icon(Icons.list, color: ListTileTheme.of(context).iconColor),
Text("...unless you use ListTileTheme.of(context).iconColor"),
],
),
],
),
);
}
}
This code will generate this result:
Upvotes: 0
Reputation: 9264
I think null
does use the default. You may be looking for the textTheme
property.
Text(widget.text,
style: TextStyle(
fontWeight: FontWeight.bold,
color: widget.selected
? Theme.of(context).accentColor
: Theme.of(context).textTheme.body.color),
Upvotes: 0