The setState function isn't updating the text in the List even though the variable isn't declared in the build method.
I'm trying to make the text change in the first and second tab of the bottomNavigationBar.
Here is the code:
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
static const String _title = 'Flutter Code Sample';
@override
Widget build(BuildContext context) {
return const MaterialApp(
title: _title,
home: MyStatefulWidget(),
);
}
}
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({super.key});
@override
State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
int _selectedIndex = 0;
static const TextStyle optionStyle =
TextStyle(fontSize: 30, fontWeight: FontWeight.bold);
int _volume = 0;
void changeVolume(){
_volume = 1;
}
late final List<Widget> _widgetOptions = <Widget>[
Row(
children: <Widget>[
IconButton(
icon: const Icon(Icons.volume_up),
tooltip: 'Increase volume by 1',
onPressed: (){
setState(() {
changeVolume();
});
},
),
Expanded(
child: Text('Volume : $_volume'),
),
Expanded(
child: FittedBox(
child: FlutterLogo(),
),
),
],
),
Text('Volume : $_volume'),
Text(
'Index 2: School',
style: optionStyle,
),
];
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('BottomNavigationBar Sample'),
),
body: Center(
child: _widgetOptions.elementAt(_selectedIndex),
),
bottomNavigationBar: BottomNavigationBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Home',
),
BottomNavigationBarItem(
icon: Icon(Icons.business),
label: 'Business',
),
BottomNavigationBarItem(
icon: Icon(Icons.school),
label: 'School',
),
],
currentIndex: _selectedIndex,
selectedItemColor: Colors.amber[800],
onTap: _onItemTapped,
),
);
}
}
Most of the times this problem comes up on this site it is because someone declared the variable in the build method but I'm not doing that here, so I'm not sure why the text isn't updating.
CodePudding user response:
setState
will re-run the build
method, so if you declare _widgetOptions
outside the build
method, it's content won't change. setState
on _selectedIndex
will work because it just selects one item in _widgetOptions
.
So remove late final
and move the declaration of _widgetOptions
into the build method:
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
static const String _title = 'Flutter Code Sample';
@override
Widget build(BuildContext context) {
return const MaterialApp(
title: _title,
home: MyStatefulWidget(),
);
}
}
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({super.key});
@override
State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
int _selectedIndex = 0;
static const TextStyle optionStyle =
TextStyle(fontSize: 30, fontWeight: FontWeight.bold);
int _volume = 0;
void changeVolume() {
_volume = 1;
}
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
});
}
@override
Widget build(BuildContext context) {
List<Widget> _widgetOptions = <Widget>[
Row(
children: <Widget>[
IconButton(
icon: const Icon(Icons.volume_up),
tooltip: 'Increase volume by 1',
onPressed: () {
setState(() {
changeVolume();
});
},
),
Expanded(
child: Text('Volume : $_volume'),
),
Expanded(
child: FittedBox(
child: FlutterLogo(),
),
),
],
),
Text('Volume : $_volume'),
Text(
'Index 2: School',
style: optionStyle,
),
];
return Scaffold(
appBar: AppBar(
title: const Text('BottomNavigationBar Sample'),
),
body: Center(
child: _widgetOptions.elementAt(_selectedIndex),
),
bottomNavigationBar: BottomNavigationBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Home',
),
BottomNavigationBarItem(
icon: Icon(Icons.business),
label: 'Business',
),
BottomNavigationBarItem(
icon: Icon(Icons.school),
label: 'School',
),
],
currentIndex: _selectedIndex,
selectedItemColor: Colors.amber[800],
onTap: _onItemTapped,
),
);
}
}
Of course you can optimize it but the above code works in DartPad as expected.
(By the way, late
marks a member variable that has no value assigned to it when you declare, but you make sure it will have a value before any part of your code accesses it. So in fact it has no real meaning when you assign a non-null value to the variable.)