Reputation: 1207
I have a function that builds a widget to be able to reuse it, and in that function I want to set the text theme. My problem is that to do that I need to access the BuildContext to do so. The only way I can think of is to pass it as a parameter in every function call, but it feels like there must be a simpler method. Or is this the best way to do it?
Here is the current code:
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:snapping_page_scroll/snapping_page_scroll.dart';
void main() => runApp(MaterialApp(
theme: ThemeData(
backgroundColor: Color(0xff121217),
textTheme: TextTheme(
headline: TextStyle(fontSize: 40)
)
),
home: SplashScreen(),
));
class SplashScreen extends StatefulWidget {
@override
_SplashScreenState createState() => _SplashScreenState();
}
class _SplashScreenState extends State<SplashScreen> {
@override
void initState() {
super.initState();
loadData();
}
//Simulates loading of data
Future<Timer> loadData() async {
return new Timer(Duration(seconds: 1), onDoneLoading);
}
onDoneLoading() async {
Navigator.of(context).push(MaterialPageRoute(builder: (context) => Home()));
}
@override
Widget build(BuildContext context) {
return Container(
color: Color(0xff121217),
child: Padding(
padding: const EdgeInsets.all(20),
child: Image.asset('assets/logo.png'),
),
);
}
}
class Home extends StatelessWidget {
Widget page(text, color, context){
return Container(
color: color,
child: Align(
alignment: Alignment(0, 0.5),
child: Text(text, style: Theme.of(context).textTheme.headline,),
),
);
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(),
body: SnappingPageScroll(
children: <Widget>[
page('Page 1', Colors.orange, context),
page('Page 2', Colors.green, context),
],
),
),
);
}
}
Upvotes: 13
Views: 17627
Reputation: 89
Wrap the function with a Builder, and you will have access to the BuildContext.
Upvotes: -1
Reputation: 41
The Theme
is usually an object that could be accessed from everywhere in your code to maintain uniform UI and consistency.
Assuming you have different themes for different parts of your app (via nested Navigator
s, etc.), I believe that's the only time where you need the widget's BuildContext
to find the Theme
it's located under. In that case, I agree with Filip's answer about using a Builder
widget.
I like to share another way to go about it is by using GlobalKey
s, supplying it to a nested Navigator
widget, and accessing declared key in the function. This is for those that need extra assurance that they're using the right theme. But in most cases (probably all), Flutter should be able to detect the right Theme
which the BuildContext
is under.
Upvotes: 0
Reputation: 11
Define a variable from the BuildContext class at the top (for example, its name is a). Sync variable a to context under build function You can use variable a anywhere you want.
Upvotes: 1
Reputation: 1075
You have access to BuildContext inside build method.
So you can move your place()
function inside build.
Widget build(BuildContext context) {
page(text, color) {
return Container(
color: color,
child: Align(
alignment: Alignment(0, 0.5),
child: Text(
text,
style: Theme.of(context).textTheme.headline,
),
),
);
}
return MaterialApp(
home: Scaffold(
appBar: AppBar(),
body: Column(
children: <Widget>[
page('Page 1', Colors.orange),
page('Page 2', Colors.green),
],
),
),
);
}
Also in cases like yours a good pattern would be to create your own reusable Page widget and pass your parameters via constructor.
class Home extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(),
body: Column(
children: <Widget>[
_Page(text: 'Page 1', color: Colors.orange),
_Page(text: 'Page 2', color: Colors.green),
],
),
),
);
}
}
class _Page extends StatelessWidget {
const _Page({
Key key,
@required this.color,
@required this.text,
}) : super(key: key);
final Color color;
final String text;
@override
Widget build(BuildContext context) {
return Container(
color: color,
child: Align(
alignment: Alignment(0, 0.5),
child: Text(
text,
style: Theme.of(context).textTheme.headline,
),
),
);
}
}
Upvotes: 3
Reputation: 1354
You can use builder widget. ... https://api.flutter.dev/flutter/widgets/Builder-class.html
Upvotes: 8