When I use TextEditingController in CupertinoTextField, and change to another widget(page) and return, the previous state in that page is lost.
When I uncomment //controller: textController, everything works fine.
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'test',
home: DefaultTabController(
length: 2,
child: Scaffold(
body: TabBarView(
children: [new Search(), new Setting(),
],
),
bottomNavigationBar: Container(
height: 60,
child: new TabBar(
tabs: [
Tab(icon: new Icon(Icons.search)),
Tab(icon: new Icon(Icons.settings)),
],
labelColor: Colors.blue,
unselectedLabelColor: Colors.grey,
),
)
),
),
);
}
}
class Setting extends StatelessWidget {
#override
Widget build(BuildContext context) {
return IconButton(
icon: Icon(Icons.check),
onPressed: () {
Navigator.push(context, CupertinoPageRoute(
builder: (context) =>
new Scaffold(
appBar: AppBar(title: Text('3'),),
)));
});
}
}
class Search extends StatefulWidget {
#override
createState() => new SearchState();
}
class SearchState extends State<Search> {
String currentWord = '';
final TextEditingController textController = new TextEditingController();
#override
void dispose() {
textController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Row(
children: <Widget>[
new Expanded(
child: new CupertinoTextField(
style: TextStyle(color: Colors.white),
cursorColor: Colors.white,
//controller: textController,
maxLines: 1,
clearButtonMode: OverlayVisibilityMode.editing,
onChanged: (text) {
setState(() {
currentWord = text;
});
},
),
),
],
),
),
body: ListView.builder(
itemCount: 5,
itemBuilder: (context, i) {
return Text(currentWord);
})
);
}
}
The expected result(without controller set):get back and the state keeps the same.
Actual results(with controller set): get back and the state lost
The explanation for the observed behavior is the following:
CupertinoTextField uses an internal TextEditingController for which the framework automatically sets an AutomaticKeepAlive. This keepAlive is responsible for keeping the state.
If you use your own controller, you are in charge of attaching the AutomaticKeepAlive because the framework doesn't do it for you.
The following snippet adds the keepAlive to your code:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'test',
home: DefaultTabController(
length: 2,
child: Scaffold(
body: TabBarView(
children: [
new Search(),
new Setting(),
],
),
bottomNavigationBar: Container(
height: 60,
child: new TabBar(
tabs: [
Tab(icon: new Icon(Icons.search)),
Tab(icon: new Icon(Icons.settings)),
],
labelColor: Colors.blue,
unselectedLabelColor: Colors.grey,
),
)),
),
);
}
}
class Setting extends StatelessWidget {
#override
Widget build(BuildContext context) {
return IconButton(
icon: Icon(Icons.check),
onPressed: () {
Navigator.push(
context,
CupertinoPageRoute(
builder: (context) => new Scaffold(
appBar: AppBar(
title: Text('3'),
),
)));
});
}
}
class Search extends StatefulWidget {
#override
createState() => new SearchState();
}
class SearchState extends State<Search> with AutomaticKeepAliveClientMixin {
String currentWord = '';
final TextEditingController textController = new TextEditingController();
#override
void initState() {
super.initState();
textController?.addListener(updateKeepAlive);
}
#override
void dispose() {
textController?.removeListener(updateKeepAlive);
textController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
super.build(context); // See AutomaticKeepAliveClientMixin.
return new Scaffold(
appBar: new AppBar(
title: new Row(
children: <Widget>[
new Expanded(
child: new CupertinoTextField(
style: TextStyle(color: Colors.white),
cursorColor: Colors.white,
controller: textController,
maxLines: 1,
clearButtonMode: OverlayVisibilityMode.editing,
onChanged: (text) {
setState(() {
currentWord = text;
});
},
),
),
],
),
),
body: ListView.builder(
itemCount: 5,
itemBuilder: (context, i) {
return Text(currentWord);
}));
}
#override
bool get wantKeepAlive => textController?.text?.isNotEmpty == true;
}
Related
I have an app with a page that has a ListView.builder().
Each row of the list is a stateful widget (match_chat_row.dart).
When you click on that stateful widget, it's navigating to another stateful widget (chat_screen.dart).
chat_screen.dart has a TextField.
The problem is that last few widgets(match_chat_row.dart) of the ListView are being disposed when the keyboard pops up on one of the first match_chat_row's chat_screen.dart.
I made this simple app to demonstrate it:
main.dart
import 'package:flutter/material.dart';
import 'match_chat_row.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final String _pageName = "Screen";
List<String> _chats = ["A","B","C","D","E","F","G","H","I","J"];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: _body()
);
}
_body(){
return ListView.builder(
itemCount: _chats.length,
itemBuilder: (_, index) => _buildRow(_chats[index]),
);
}
Widget _buildRow(String chat) {
return
Column(
key: ValueKey<String>('chat-$chat'),
children: [
Center(
child:
MatchChatRow(
content: chat,
),
),
Divider(color: Colors.grey.withOpacity(0.20), thickness: 0.8, height: 0.0,)
],
);
}
}
match_chat_row.dart
import 'package:flutter/material.dart';
import 'chat_screen.dart';
class MatchChatRow extends StatefulWidget {
final String content;
const MatchChatRow({required this.content});
#override
_MatchChatRowState createState() => _MatchChatRowState();
}
class _MatchChatRowState extends State<MatchChatRow> {
#override
void dispose(){
print("Disposed ROW! ${widget.content}");
super.dispose();
}
#override
Widget build(BuildContext context) {
final rowHeight = 100.0;
final rowPadding = 10.0;
return
InkWell(
onTap: () =>
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ChatScreen(
key: ValueKey(widget.content),
),
),
),
child:
Container(
height: rowHeight,
padding: EdgeInsets.all(rowPadding),
child: Row(
children: <Widget>[
SizedBox(
width: 20.0,
),
Expanded(
child:
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(widget.content),
Text("_buildSubtitle()"),
],
)
),
],
),
)
);
}
}
chat_screen.dart
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class ChatScreen extends StatefulWidget {
const ChatScreen({required Key key,}): super(key: key);
#override
_ChatScreenState createState() => _ChatScreenState();
}
class _ChatScreenState extends State<ChatScreen> with TickerProviderStateMixin {
final TextEditingController _messageController = TextEditingController();
bool _isComposingMessage = false;
bool _isChatExist = false;
bool _isLoading = false;
bool _isSending = false;
#override
void initState() {
super.initState();
}
#override
void dispose(){
print("disposed chat! ${widget.key}");
super.dispose();
}
Container _buildMessageTF() {
return Container(
margin: const EdgeInsets.only(left: 8, right: 8, bottom: 8),
decoration: BoxDecoration(
border:
Border.all(color: Theme.of(context).accentColor.withOpacity(0.3)),
borderRadius: BorderRadius.circular(30)),
child: Row(
children: <Widget>[
Expanded(
child:
TextField(
minLines: 1,
maxLines: 4,
controller: _messageController,
textCapitalization: TextCapitalization.sentences,
onChanged: (messageText) {
setState(() => _isComposingMessage = messageText.isNotEmpty);
},
decoration: InputDecoration(
focusedBorder: InputBorder.none,
enabledBorder: InputBorder.none,
hintText: 'Message...'),
),
),
],
),
);
}
#override
Widget build(BuildContext context) {
return
WillPopScope(
onWillPop: () {
return Future.value(true);
},
child:
SafeArea(
child: Scaffold(
appBar: AppBar(
title: Text("Hi")
),
body:
SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
if (!_isChatExist && !_isLoading) SizedBox.shrink(),
_buildMessageTF(),
],
),
),
),
)
);
}
}
And whenever I click on the TextField and the Keyboard pops up the below widgets are being disposed (this is my debug console):
I/flutter (23372): Disposed ROW! I
I/flutter (23372): Disposed ROW! J
I/flutter (23372): Disposed ROW! H
update your _body from main
_body(){
return SingleChildScrollView(
child: ListView.builder(
shrinkWrap: true,
physics: ScrollPhysics(),
itemCount: _chats.length,
itemBuilder: (_, index) => _buildRow(_chats[index]),
),
);
}
I'm trying to make an application like Instagram. But I can't fully view the zoomed picture because of other pictures.
Codes:
List colors = [
Colors.green,
Colors.blue,
Colors.red,
];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Demo"),
),
body: ListView.builder(
itemCount: 3,
itemBuilder: (_, int index) {
TransformationController controller = TransformationController();
return Container(
child: InteractiveViewer(
transformationController: controller,
onInteractionEnd: (_) {
setState(() {
controller.toScene(Offset.zero);
});
},
child: ColorFiltered(
colorFilter: ColorFilter.mode(colors[index], BlendMode.color),
child: FlutterLogo(),
),
),
height: 200,
width: 200,
);
},
),
);
}
Note: I can't use widgets like stack because of listview.builder
You could either use Visibility widget or Opacity widget to change the visibility of images not being currently panned. Please see the code below I'm using AnimatedOpacity just so that the disappearance of the images does not look too sudden, but you may use Opacity widget as well.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text("Flutter Demo")),
body: MyStatefulWidget(),
),
);
}
}
class MyStatefulWidget extends StatefulWidget {
#override
_MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
static List colors = [
Colors.green,
Colors.blue,
Colors.red,
];
final List<double> _opacity = List.generate(colors.length, (index) => 1);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Demo"),
),
body: ListView.builder(
itemCount: 3,
itemBuilder: (_, int index) {
final TransformationController controller =
TransformationController();
return AnimatedOpacity(
opacity: _opacity[index],
duration: const Duration(milliseconds: 100),
child: Container(
child: InteractiveViewer(
transformationController: controller,
onInteractionStart: (details) {
for (int i = 0; i < _opacity.length; i++) {
_opacity[i] = i == index ? 1 : 0;
}
setState(() {});
},
onInteractionEnd: (_) {
setState(() {
_opacity.fillRange(0, _opacity.length, 1);
controller.toScene(Offset.zero);
});
},
child: ColorFiltered(
colorFilter: ColorFilter.mode(colors[index], BlendMode.color),
child: const FlutterLogo(),
),
),
height: 200,
width: 200,
),
);
},
),
);
}
}
I have an app which has two tabs. One of the which is the "SAVED ITEMS" tab. When I save the items (from a different screen of ALL ITEMS LIST) it gets saved and on even switching the tabs works fine. But when I close the app and reopen it, the "SAVED ITEMS" list is empty and I've to select the items again. I've used the AutomaticKeepAliveClientMixin but its not helping. Any idea on how to solve this folks?
My code:
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> with AutomaticKeepAliveClientMixin {
#override
Widget build(BuildContext context) {
super.build(context);
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
primaryColor: Colors.blue,
accentColor: Colors.white,
),
home: DefaultTabController(
length: 2,
child: Scaffold(
drawer: Drawer(),
backgroundColor: Colors.blueAccent,
appBar: AppBar(
backgroundColor: Colors.blueAccent,
title: Text('AIO'),
bottom: TabBar(
tabs: <Widget>[
Tab(icon: Icon(Icons.search)),
Tab(icon: Icon(Icons.favorite)),
],
),
),
body: TabBarView(
children: <Widget>[
gridView,
SecondPage(),
],
),
),
),
);
}
#override
bool get wantKeepAlive => true;
}
SecondTab code:
Set<int> favorites = {};
class SecondPage extends StatefulWidget {
#override
_SecondPageState createState() => _SecondPageState();
}
class _SecondPageState extends State<SecondPage>
with AutomaticKeepAliveClientMixin {
#override
bool get wantKeepAlive => true;
#override
Widget build(BuildContext context) {
super.build(context);
return Stack(
fit: StackFit.expand,
children: <Widget>[
_getFavoriteList(),
Align(
alignment: Alignment.bottomRight,
child: Padding(
padding: const EdgeInsets.all(20.0),
child: FloatingActionButton(
child: Icon(
Icons.add,
color: Colors.blue,
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => EditFavorites(),
),
).then((updatedFavorites) {
if (updatedFavorites != null)
// setState(() {
favorites = updatedFavorites;
// });
});
},
),
),
)
],
);
}
Add shared_preferences dependency in pubspec.yaml
Update your main()
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
SharedPreferences pref = await SharedPreferences.getInstance();
pref.getStringList("favorites")?.forEach((fav){
favorites.add(int.tryParse(fav));
});
runApp(MyApp());
}
then update your SecondPage
Set<int> favorites = {};
class SecondPage extends StatefulWidget {
#override
_SecondPageState createState() => _SecondPageState();
}
class _SecondPageState extends State<SecondPage> {
Future<void> _upDateFavorites(Set<int> updatedFavorites) async {
print("secong: u$updatedFavorites");
SharedPreferences pref = await SharedPreferences.getInstance();
List<String> favoritesAsString =
updatedFavorites.map((fav) => fav.toString()).toList(); //TODO: Change `favorites` to `updatedFavorites`
print(favoritesAsString);
await pref.setStringList("favorites", favoritesAsString); //TODO: await here to store it completely
favorites = updatedFavorites;
setState(() {});
}
#override
Widget build(BuildContext context) {
return Stack(
fit: StackFit.expand,
children: <Widget>[
_getFavoriteList(),
Align(
alignment: Alignment.bottomRight,
child: Padding(
padding: const EdgeInsets.all(20.0),
child: FloatingActionButton(
child: Icon(
Icons.add,
color: Colors.blue,
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => EditFavorites(),
),
).then((updatedFavorites) async {
if (updatedFavorites != null)
// setState(() {
_upDateFavorites(updatedFavorites);
// });
});
},
),
),
)
],
);
}
Widget _getFavoriteList() {
if (favorites?.isNotEmpty == true)
return _FavoriteList();
else
return _EmptyFavoriteList();
}
}
Don't forget to import 'package:shared_preferences/shared_preferences.dart'; where you use SharedPreferences
Avoid storing widget in a vaiable, if it needs to be rebuild.
So delete var favGridView = GridView.builder( ....
class _FavoriteList extends StatelessWidget {
#override
Widget build(BuildContext context) {
return GridView.builder(
itemCount: favorites.length,
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3),
itemBuilder: (BuildContext context, int index) {
print("kkkkkkkkkkk: ${favorites.elementAt(index)}");
return InkWell(
child: Card(
elevation: 10,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(10),
child: Container(
child: Image.asset(
'lib/images/${images[favorites.elementAt(index)]}'), //TODO: Change this
// child: SizedBox(child: Text('yashjha'),),
// decoration: BoxDecoration(
// image: DecorationImage(
// image: AssetImage('lib/images/${images[index]}'),
// fit: BoxFit.fitWidth,
// alignment: Alignment.topCenter,
// ),
// ),
),
),
Text(nameOfSite[favorites.elementAt(index)]), //TODO: Change This
],
),
),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Text("dsadsa")),
);
},
);
},
);
}
}
I also recommend using actions instead of FloatingButton in _EditFavoritesState. Because the floating button hides last item. which makes it unable to add to favorites
AutomaticKeepAliveClientMixin is used to retain the data when the app is running and you need to retain data while switching between tabs, pages etc.
I would suggest you use SharedPreferences to easily save data to your memory that can be retrieved when the app is started again.
SharedPreferences: https://pub.dev/packages/shared_preferences
Currently, I have write codes for making up the counter app with two buttons. 1 raised button to reset and one fab button for increment counter.
is it possible to add the countdown timer to implement on FAB button? When FAB button clicks 20-second countdown timer start.
Also, I have found below thread for the same type of function implement. But I don't where to put codes in my app to implement countdown work on FAB button.
How to make a countdown in flutter?
import 'package:flutter/material.dart';
import 'dart:ui';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Counter App',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Counter App'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
int _counter = 0;
AnimationController controller;
bool _isButtonDisabled;
Duration get duration => controller.duration * controller.value;
bool get expired => duration.inSeconds == 0;
#override
void initState() {
controller = AnimationController(
vsync: this,
duration: Duration(seconds: 20),
);
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'number $_counter added',
),
AnimatedBuilder(
animation: controller,
builder: (BuildContext context, Widget child) {
return new Text(
'${duration.inSeconds}',
style: new TextStyle(
fontWeight: FontWeight.bold,
fontSize: 50.0,
),
);
}),
new Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
new RaisedButton(
padding: const EdgeInsets.all(15.0),
textColor: Colors.white,
color: Colors.redAccent,
onPressed: () {
setState(() {
controller.reset();
_counter = 0;
});
},
child: new Text("Reset"),
),
new RaisedButton(
onPressed: () => setState(() {
controller.reverse(from: 1);
}),
textColor: Colors.white,
color: Colors.purple,
padding: const EdgeInsets.all(15.0),
child: new Text(
"Start",
),
),
],
),
],
),
),
bottomNavigationBar: BottomAppBar(
child: Container(
height: 50.0,
),
),
floatingActionButton: FloatingActionButton(
onPressed: () => setState(() {
_counter++;
}),
tooltip: 'Increment Counter',
child: Icon(Icons.add),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
);
}
}
you can use anywhere this code.
Timer(Duration(seconds: 30), () {
//checkFirstSeen(); your logic
});
try the following:
import 'package:flutter/material.dart';
import 'dart:ui';
import 'dart:async';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Counter App',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Counter App'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
int _counter = 0;
AnimationController controller;
Duration get duration => controller.duration * controller.value;
bool get expired => duration.inSeconds == 0;
#override
void initState() {
controller = AnimationController(
vsync: this,
duration: Duration(seconds: 20),
);
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
AnimatedBuilder(
animation: controller,
builder: (BuildContext context, Widget child) {
return new Text(
'${duration.inSeconds}',
style: new TextStyle(
fontWeight: FontWeight.bold,
fontSize: 50.0,
),
);
}),
new Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
new RaisedButton(
padding: const EdgeInsets.all(15.0),
textColor: Colors.white,
color: Colors.redAccent,
onPressed: () {
setState(() {
controller.reset();
});
},
child: new Text("Reset"),
),
],
),
],
),
),
bottomNavigationBar: BottomAppBar(
child: Container(
height: 50.0,
),
),
floatingActionButton: FloatingActionButton(
onPressed: () => setState(() {
controller.reverse(from: 1);
}),
tooltip: 'Increment Counter',
child: Icon(Icons.add),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
);
}
}
I am trying to get a dropdownlist to navigate to another screen once one of the items in the list is pressed via the dropdownbutton. I have tried using Navigator.push straight into onChanged but that doesnt work. And i have tried creating a new button in set state in onChanged. How can I do this because I do not know how?
import 'package:flutter/material.dart';
void main() => runApp(new HomeNavigator());
class HomeNavigator extends StatefulWidget {
#override
_HomeNavigator createState() => _HomeNavigator();
}
class _HomeNavigator extends State<HomeNavigator> {
List<DropdownMenuItem<String>> listMunicipalities = [];
String selected = null;
void loadData() {
listMunicipalities = [];
listMunicipalities.add(new DropdownMenuItem(
child: new Text('Port Moody'),
value: 'Port Moody',
));
listMunicipalities.add(new DropdownMenuItem(
child: new Text('Vancouver Downtown'),
value: 'Vancouver Downtown',
));
listMunicipalities.add(new DropdownMenuItem(
child: new Text('Coquitlam'),
value: 'Coquitlam',
));
}
#override
Widget build(BuildContext context) {
loadData();
Color gradientStart = Colors.deepOrange[700];
Color gradientEnd = Colors.purple[500];
return new MaterialApp(
home: new Scaffold(
body: new Container(
decoration: new BoxDecoration(
gradient: new LinearGradient(
colors: [gradientEnd, gradientStart],
begin: new FractionalOffset(0.0, 0.5),
end: new FractionalOffset(0.5, 0.0),
stops: [0.0, 1.0]),
),
child: Stack(children: [
Container(
child: Text('',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 30.0,
fontFamily: 'College-Block',
color: Colors.white.withOpacity(0.7))),
alignment: Alignment(0.0, -0.5)),
Padding(
padding: const EdgeInsets.all(8.0),
child: new Center(
child: new Container(
alignment: Alignment(0.0, 0.05),
child: Container(
width: 350.0,
child: DropdownButtonHideUnderline(
child: new DropdownButton(
value: selected,
items: listMunicipalities,
hint: Text(
'Select City',
textAlign: TextAlign.center,
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.white.withOpacity(0.5)),
),
onChanged: (value){
}),
)),
)))
]))));
}
}
class HomePage extends StatefulWidget{
#override
_HomePage createState() => _HomePage();
}
class _HomePage extends State<HomePage> {
Widget build(BuildContext context){
return Scaffold(
appBar: AppBar(
title: Text('')
),
);
}
}
you can just use simple switch case over there. refer below example to clear idea.
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
title: 'Navigation Basics',
home: FirstScreen(),
));
}
class FirstScreen extends StatelessWidget {
String _selectedGender=null;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('First Screen'),
),
body: Column(
children: <Widget>[
DropdownButton(
value: _selectedGender,
items: _dropDownItem(),
onChanged: (value){
_selectedGender=value;
switch(value){
case "Male" :
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecondScreen()),
);
break;
case "Others" :
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecondScreen()),
);
break;
case "Female" :
Navigator.push(
context,
MaterialPageRoute(builder: (context) => third()),
);
break;
}
},
hint: Text('Select Gender'),
),
],
),
);
}
List<DropdownMenuItem<String>> _dropDownItem() {
List<String> ddl = ["Male", "Female", "Others"];
return ddl.map(
(value) =>
DropdownMenuItem(
value: value,
child: Text(value),
)
).toList();
}
}
class SecondScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Second Screen"),
),
body: Center(
child: RaisedButton(
onPressed: () {
Navigator.pop(context);
},
child: Text('Go back!'),
),
),
);
}
}
class third extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("tgird Screen"),
),
body: Center(
child: RaisedButton(
onPressed: () {
Navigator.pop(context);
},
child: Text('Go back!'),
),
),
);
}
}
for detail go to document https://flutter.io/cookbook/navigation/navigation-basics/
Add below line in your code for Navigation
onChanged: (value){
Navigator.push(context,MaterialPageRoute(builder: (context) =>
YourScreenInstance()),);
}
Navigator.popAndPushNamed(context, "/YourScreenInstance");
Navigator.of(context).pushNamed('/NewPage');