Call a method from one statefulWidget in tab page in Flutter - flutter

I have two widgets - one is the main page with tabs and buttons and the second one is - Page with some TextFields. I would like to clean all TextFields after the button click. I tried to use
GlobalKey<_Page1> _key = GlobalKey<_Page1>(); and _key.currentState!.CleanAll(); but I received an error - Unhandled Exception: Null check operator used on a null value
Do you have any other ideas on how to do this?
class MyTabs extends StatefulWidget {
const MyTabs({Key? key}) : super(key: key);
#override
_MyTabsState createState() => _MyTabsState();
}
class _MyTabsState extends State<MyTabs> {
#override
Widget build(BuildContext context) {
return Column(
children: [
DefaultTabController(
length: 1, // length of tabs
initialIndex: 0,
child: Column(
children: <Widget>[
const TabBar(
labelColor: Colors.green,
unselectedLabelColor: Colors.blueGrey,
tabs: [
Tab(text: 'Page 1'),
],
),
SizedBox(
height: 200,
child: TabBarView(
children: <Widget>[
Page1(),
]
),
),
],
),),
ElevatedButton(
onPressed: () {
// <- clean all TextField in Page1
},
child: Text('Clean')
),
],
);
}
}
class Page1 extends StatefulWidget {
const Page1({Key? key}) : super(key: key);
#override
_Page1State createState() => _Page1State();
}
class _Page1State extends State<Page1> {
TextEditingController text1 = TextEditingController();
TextEditingController text2 = TextEditingController();
void CleanAll() {
text1.clear();
text2.clear();
}
#override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextField(
controller: text1,
),
TextField(
controller: text2,
),
],
);
}
}

You can use a ValueNotifier that will listen on Page1. then we will override initState on Page1 and clear the controlles.
class _MyTabsState extends State<MyTabs> {
final ValueNotifier<bool> clearNotifier = ValueNotifier(false);
pass it to the Page1
Page1(
clearCallback: clearNotifier,
),
to notify the listener we are just switching the value. bool value does not matter, we just need to update it.
onPressed: () {
clearNotifier.value = !clearNotifier.value;
},
and on Page1
class Page1 extends StatefulWidget {
final ValueNotifier clearCallback;
const Page1({Key? key, required this.clearCallback}) : super(key: key);
#override
_Page1State createState() => _Page1State();
}
class _Page1State extends State<Page1> {
#override
void initState() {
super.initState();
widget.clearCallback.addListener(() {
CleanAll();
});
}
Test snippet
class MyTabs extends StatefulWidget {
const MyTabs({Key? key}) : super(key: key);
#override
_MyTabsState createState() => _MyTabsState();
}
class _MyTabsState extends State<MyTabs> {
final ValueNotifier<bool> clearNotifier = ValueNotifier(false);
#override
Widget build(BuildContext context) {
return Column(
children: [
DefaultTabController(
length: 1, // length of tabs
initialIndex: 0,
child: Column(
children: <Widget>[
const TabBar(
labelColor: Colors.green,
unselectedLabelColor: Colors.blueGrey,
tabs: [
Tab(text: 'Page 1'),
],
),
SizedBox(
height: 200,
child: TabBarView(children: <Widget>[
Page1(
clearCallback: clearNotifier,
),
]),
),
],
),
),
ElevatedButton(
onPressed: () {
clearNotifier.value = !clearNotifier.value;
},
child: Text('Clean')),
],
);
}
}
class Page1 extends StatefulWidget {
final ValueNotifier clearCallback;
const Page1({Key? key, required this.clearCallback}) : super(key: key);
#override
_Page1State createState() => _Page1State();
}
class _Page1State extends State<Page1> {
#override
void initState() {
super.initState();
widget.clearCallback.addListener(() {
CleanAll();
});
}
TextEditingController text1 = TextEditingController();
TextEditingController text2 = TextEditingController();
void CleanAll() {
text1.clear();
text2.clear();
}
#override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextField(
controller: text1,
),
TextField(
controller: text2,
),
],
);
}
}

Related

Save reorderable grid with GetStorage

I've some trouble when I try to save the reorderable grid after I've changed it.
It seem to work good but when i open again the app is only a grey screen.I've added some snackbar that print the list before and after been saved with GetStorage but they are in the right order as you can see in this screenshot
imagePaths before being saved
imagePaths loaded from GetStorage
grey screen when I reopening the app
import 'package:flutter/material.dart';
import 'package:reorderable_grid_view/reorderable_grid_view.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:get/get.dart';
import 'package:get_storage/get_storage.dart';
void main() async {
await GetStorage.init();
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return GetMaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final box = GetStorage();
List<String> imagePaths = GetStorage().read('imagePaths') ?? [
'remote',
'timelapse',
'video',
'hdr',
'star',
'lightning',
'drop',
'vibrate',
];
#override
Widget build(BuildContext context) {
return Scaffold(
body: ReorderableGridView.count(
crossAxisCount: 2,
childAspectRatio: 1,
children: imagePaths
.map((String path) => Card(
key: ValueKey(path),
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(path),
SvgPicture.asset(
'assets/$path.svg',
color: Colors.red,
),
],
),
),
))
.toList(),
onReorder: (oldIndex, newIndex) async {
String path = imagePaths.removeAt(oldIndex);
imagePaths.insert(newIndex, path);
setState(() {
Get.snackbar(
'before GetStorage:',
'${imagePaths.toString()}',
snackPosition: SnackPosition.BOTTOM,
);
box.remove('imagePaths');
box.write('imagePaths', imagePaths);
Get.snackbar(
'from GetStorage:',
'${box.read('imagePaths').toString()}',
snackPosition: SnackPosition.BOTTOM,
);
});
},
),
);
}
}
I solved your problem like here:
class MyHomePage extends StatefulWidget {
const MyHomePage({Key key}) : super(key: key);
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List imagePaths = [
'remote',
'timelapse',
'video',
'hdr',
'star',
'lightning',
'drop',
'vibrate'
];
final box = GetStorage();
final String key = 'imagePaths';
#override
void initState() {
imagePaths = box.read(key);
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: ReorderableGridView.count(
crossAxisCount: 2,
childAspectRatio: 1,
children: imagePaths
.map((path) => Card(
key: ValueKey(path),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(path),
SvgPicture.asset(
'assets/$path.svg',
color: Colors.red,
),
],
),
))
.toList(),
onReorder: (oldIndex, newIndex) async {
String path = imagePaths.removeAt(oldIndex);
imagePaths.insert(newIndex, path);
setState(() {
box.remove(key);
box.write(key, imagePaths);
});
},
),
);
}
}

Flutter web tabbar scroll issue with non primary scrollcontroller

In continuation with question
The solution provided above is good. But hard for me to implement in my project.
Expected results:
I've created two tabs.
In each tab I have SingleChildScrollView wrapped with Scrollbar.
I can not have the primary scrollcontroller in both the tabs, because that throws me exception: "ScrollController attached to multiple scroll views."
For Tab ONE I use primary scrollcontroller, for Tab TWO I created Scrollcontroller and attached it.
Widgets in both the tabs should be scrollabale using keyboard and mouse.
Actual results:
For Tab ONE with primary scrollcontroller I can scroll both by keyboard and dragging scrollbar.
But for Tab TWO with non primary scrollcontroller, I have to scroll only by dragging scrollbar. This tab doesn't respond to keyboard page up /down keys.
When keyboard keys are used in Tab TWO actually contents of tab ONE are getting scrolled.
Check code:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
home: TabExample(),
);
}
}
class TabExample extends StatefulWidget {
const TabExample({Key key}) : super(key: key);
#override
_TabExampleState createState() => _TabExampleState();
}
class _TabExampleState extends State<TabExample> {
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
bottom: TabBar(
tabs: [
Tab(icon: Text('Tab ONE')),
Tab(icon: Text('Tab TWO')),
],
),
title: Text('Tabs Demo'),
),
body: TabBarView(
children: [
WidgetC(),
WidgetD(),
],
),
),
);
}
}
class WidgetC extends StatefulWidget {
const WidgetC({Key key}) : super(key: key);
#override
_WidgetCState createState() => _WidgetCState();
}
class _WidgetCState extends State<WidgetC>
with AutomaticKeepAliveClientMixin<WidgetC> {
List<Widget> children;
#override
void initState() {
children = [];
for (int i = 0; i < 20; i++) {
children.add(
Padding(
padding: EdgeInsets.symmetric(vertical: 16),
child: Container(
height: 100,
width: double.infinity,
color: Colors.blue,
child: Center(child: Text('$i')),
),
),
);
}
super.initState();
}
#override
Widget build(BuildContext context) {
super.build(context);
return Scrollbar(
key: PageStorageKey('WidgetC'),
isAlwaysShown: true,
showTrackOnHover: true,
child: SingleChildScrollView(
child: Column(
children: children,
),
),
);
}
#override
bool get wantKeepAlive => true;
}
class WidgetD extends StatefulWidget {
const WidgetD({Key key}) : super(key: key);
#override
_WidgetDState createState() => _WidgetDState();
}
class _WidgetDState extends State<WidgetD>
with AutomaticKeepAliveClientMixin<WidgetD> {
List<Widget> children;
ScrollController _scrollController;
#override
void initState() {
_scrollController = ScrollController();
children = [];
for (int i = 0; i < 20; i++) {
children.add(
Padding(
padding: EdgeInsets.symmetric(vertical: 16),
child: Container(
height: 100,
width: double.infinity,
color: Colors.green,
child: Center(child: Text('$i')),
),
),
);
}
super.initState();
}
#override
void dispose() {
_scrollController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
super.build(context);
return Scrollbar(
key: PageStorageKey('WidgetD'),
isAlwaysShown: true,
showTrackOnHover: true,
controller: _scrollController,
child: SingleChildScrollView(
controller: _scrollController,
child: Column(
children: children,
),
),
);
}
#override
bool get wantKeepAlive => true;
}
This has been accepted as a bug in flutter.
Pl follow for progress here: https://github.com/flutter/flutter/issues/83711
Note for other developers facing same issue.
To overcome the mentioned problem, I changed my design layout. Instead of tabbar view I used Navigationrail widget. This solved my problem.
NavigationRail widget allowed me to attach primary scroll controller to multiple widgets without giving me exception: "ScrollController attached to multiple scroll views."
Sample code.
import 'dart:math';
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
/// This is the main application widget.
class MyApp extends StatelessWidget {
const MyApp({Key key}) : super(key: key);
static const String _title = 'Flutter Code Sample';
#override
Widget build(BuildContext context) {
return const MaterialApp(
title: _title,
home: MyStatefulWidget(),
);
}
}
/// This is the stateful widget that the main application instantiates.
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({Key key}) : super(key: key);
#override
State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}
/// This is the private State class that goes with MyStatefulWidget.
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
int _selectedIndex = 0;
WidgetC _widgetC = WidgetC();
WidgetD _widgetD = WidgetD();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('NavigationRail Demo'), centerTitle: true),
body: Row(
children: <Widget>[
NavigationRail(
elevation: 8.0,
selectedIndex: _selectedIndex,
onDestinationSelected: (int index) {
setState(() {
_selectedIndex = index;
});
},
labelType: NavigationRailLabelType.all,
groupAlignment: 0.0,
destinations: const <NavigationRailDestination>[
NavigationRailDestination(
icon: Icon(Icons.favorite_border),
selectedIcon: Icon(Icons.favorite),
label: Text('Tab ONE'),
),
NavigationRailDestination(
icon: Icon(Icons.bookmark_border),
selectedIcon: Icon(Icons.book),
label: Text('Tab TWO'),
),
],
),
const VerticalDivider(thickness: 1, width: 1),
// This is the main content.
Expanded(
child: _getPageAtIndex(_selectedIndex),
)
],
),
);
}
Widget _getPageAtIndex(int index) {
switch (index) {
case 0:
return _widgetC;
case 1:
return _widgetD;
}
return Container();
}
}
class WidgetC extends StatefulWidget {
const WidgetC({Key key}) : super(key: key);
#override
_WidgetCState createState() => _WidgetCState();
}
class _WidgetCState extends State<WidgetC>
with AutomaticKeepAliveClientMixin<WidgetC> {
List<Widget> children;
#override
void initState() {
children = [];
for (int i = 0; i < 20; i++) {
children.add(
Padding(
padding: EdgeInsets.symmetric(vertical: 16),
child: Container(
height: 100,
width: double.infinity,
color: Colors.primaries[Random().nextInt(Colors.primaries.length)],
child: Center(child: Text('$i')),
),
),
);
}
super.initState();
}
#override
Widget build(BuildContext context) {
super.build(context);
return Scrollbar(
key: PageStorageKey('WidgetC'),
isAlwaysShown: true,
showTrackOnHover: true,
child: SingleChildScrollView(
child: Column(
children: children,
),
),
);
}
#override
bool get wantKeepAlive => true;
}
class WidgetD extends StatefulWidget {
const WidgetD({Key key}) : super(key: key);
#override
_WidgetDState createState() => _WidgetDState();
}
class _WidgetDState extends State<WidgetD>
with AutomaticKeepAliveClientMixin<WidgetD> {
List<Widget> children;
// ScrollController _scrollController;
#override
void initState() {
// _scrollController = ScrollController();
children = [];
for (int i = 0; i < 20; i++) {
children.add(
Padding(
padding: EdgeInsets.symmetric(vertical: 16),
child: Container(
height: 100,
width: double.infinity,
color: Colors.primaries[Random().nextInt(Colors.primaries.length)],
child: Center(child: Text('$i')),
),
),
);
}
super.initState();
}
#override
void dispose() {
// _scrollController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
super.build(context);
return Scrollbar(
key: PageStorageKey('WidgetD'),
isAlwaysShown: true,
showTrackOnHover: true,
// controller: _scrollController,
child: SingleChildScrollView(
// controller: _scrollController,
child: Column(
children: children,
),
),
);
}
#override
bool get wantKeepAlive => true;
}

Call function of StatefulWidget from StatelessWidget in Flutter

I want to call a function from my StatefulWidget when a button in my StatelessWidget is pressed. In the following code you can see what I'm trying to do. I'm not really sure how it works, so maybe you can help me.
StatelessWidget - Button should call function from StatefulWidget
class HomeWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
child: Column(
children: [
SafeArea(child: Column(
children: [
Padding(
padding: EdgeInsets.all(10),
child: ProgressButton.icon(iconedButtons: {not needed}
onPressed: addUser,
state: ButtonState.idle),
),
],
)),
],
),
);
}
}
Statefulwidget - addUser() should be called by StatelessWidget
class HomeStateful extends StatefulWidget {
#override
_HomeStatefulState createState() => _HomeStatefulState();
}
class _HomeStatefulState extends State<HomeStateful> {
final firestoreInstance = FirebaseFirestore.instance;
CollectionReference users = FirebaseFirestore.instance.collection('users');
int _currentIndex = 0;
final List<Widget> _children = [
HomeWidget(),
MessageWidget(),
];
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: _children[_currentIndex],
bottomNavigationBar: BottomNavigationBar(
currentIndex: _currentIndex,
onTap: onTabTapped,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home),
title: Text("Home"),
backgroundColor: Colors.blue,
),
BottomNavigationBarItem(
icon: Icon(Icons.mail),
title: Text("Nachrichten"),
backgroundColor: Colors.blue,
),
]),
);
}
void onTabTapped(int index) {
setState(() {
_currentIndex = index;
});
}
void addUser() {
firestoreInstance.collection("users").add({
"vorname": prenameController,
"nachname": nameController,
"geburtstag": birthdayController,
"adresse": adressController,
"telefon": numberController,
"id": 0
});
}
}
You can use callback function in Stateless widget, Like this
class HomeWidget extends StatelessWidget {
const HomeWidget({Key key, #required this.addUser}) : super(key: key);
/// If you want to pass any value back, then you can use something
/// like this
/// final Function(User user) addUser;
/// VoidCallback as name speaks its a empty fn.
final VoidCallback addUser; // ==> Here is the answer.
#override
Widget build(BuildContext context) {
return Container(
child: Column(
children: [
SafeArea(
child: Column(
children: [
Padding(
padding: EdgeInsets.all(10),
child: RaisedButton(
onPressed: addUser, // Add User fun here
)),
],
)),
],
),
);
}
}
And in stateful/parent widget.
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final _list = <Widget>[
HomeWidget(addUser: addUser) // Wrong, You cannot access the addUser here.
];
final _childList = <Widget>[];// But you can initialize here and add the HomeWidget in initState.
#override
void initState() {
super.initState();
_childList.addAll([
HomeWidget(addUser: addUser),
HomeWidget(addUser: addUser),
///... Other children
]);
}
void addUser() {
// Do Somethign
}
#override
Widget build(BuildContext context) {
return Column(
children: [
HomeWidget(addUser: addUser),
],
);
}
}

How, using Flutter, to create a widget that includes a TabBar and a (Custom) BarWidget?

Can find many examples of how to create a tabbed Flutter application using the AppBar. Everything is clear here. But how to add TabBar and (CustomX) BarWidget to widget (Custom) BarWidget? Those. create widget "tab inside tab", pictured below:
I can add a TabBar to the widget, but I don't know how add (CustomX) BarWidget:
The code:
class ElementTabbedPage extends StatefulWidget {
//ElementTabbedPage({Key key}) : super(key: key);
IGUIBridge _element;
ElementTabbedPage(this._element);
#override
_ElementTabbedPageState createState() => _ElementTabbedPageState();
}
class _ElementTabbedPageState extends State<ElementTabbedPage> with TickerProviderStateMixin {
List<String> _tabsContainer = ['P1', 'P2', 'P3'];
TabController _tabController;
#override
void initState() {
super.initState();
_tabController =
new TabController(vsync: this, length: _tabsContainer.length);
}
#override
void dispose() {
_tabController.dispose();
super.dispose();
}
Widget build(context) {
print ('_ElementTabbedPageState.build->${widget._element.name()}');
return
Container(
child: Column(
children: <Widget>[
TabBar(
controller: _tabController,
isScrollable: true,
tabs: _tabsContainer
.map((x) => Container(
width: 60.0,
child: Tab(text: x,
//icon: Icon(Icons.favorite),
),
)).toList(),
),
//PanelBarWidget(tabController: _tabController, tabsContainer: _tabsContainer),
]
)
);
}
}
class PanelBarWidget extends StatefulWidget {
const PanelBarWidget({
Key key,
#required TabController tabController,
#required List<String> tabsContainer,
})
: _tabController = tabController,
_tabsContainer = tabsContainer,
super(key: key);
#override
_PanelBarWidgetState createState() => new _PanelBarWidgetState();
final TabController _tabController;
final List<String> _tabsContainer;
}
class _PanelBarWidgetState extends State<PanelBarWidget> {
#override
Widget build(BuildContext context) {
return new TabBarView(
controller: widget._tabController,
children: widget._tabsContainer.map(createView).toList());
}
Container createView(x) {
List<String> list = ["A 11", "A 12", "A 13"];
return Container(child:
Text(x),
);
}
}
The problem can be solved as follows:
import 'package:flutter/material.dart';
import 'dart:async';
import '../manageables/IManageable.dart';
import '../singletons/GuiAdapter.dart';
import '../bridge/IGUIBridge.dart';
class ElementTabbedPage extends StatefulWidget {
//ElementTabbedPage({Key key}) : super(key: key);
IGUIBridge _element;
ElementTabbedPage(this._element);
#override
_ElementTabbedPageState createState() => _ElementTabbedPageState();
}
class _ElementTabbedPageState extends State<ElementTabbedPage>
with TickerProviderStateMixin {
List<String> _tabsContainer = ['P1', 'P2', 'P3'];
TabController _tabController;
#override
void initState() {
super.initState();
_tabController =
new TabController(vsync: this, length: _tabsContainer.length);
}
#override
void dispose() {
_tabController.dispose();
super.dispose();
}
Widget build(context) {
print('_ElementTabbedPageState.build->${widget._element.name()}');
return Column(children: <Widget>[
TabBar(
controller: _tabController,
isScrollable: true,
unselectedLabelColor: Colors.black38,
indicatorSize: TabBarIndicatorSize.tab,
indicator: BoxDecoration(
borderRadius: BorderRadius.circular(8), color: Colors.black38),
tabs: _tabsContainer
.map((x) => Container(
width: 60.0,
child: Tab(
text: x,
//icon: Icon(Icons.favorite),
),
))
.toList(),
),
Container(
child: Expanded(
child: PanelBarWidget(
tabController: _tabController, tabsContainer: _tabsContainer),
),
)
]);
}
}
class PanelBarWidget extends StatefulWidget {
const PanelBarWidget({
Key key,
#required TabController tabController,
#required List<String> tabsContainer,
}) : _tabController = tabController,
_tabsContainer = tabsContainer,
super(key: key);
#override
_PanelBarWidgetState createState() => new _PanelBarWidgetState();
final TabController _tabController;
final List<String> _tabsContainer;
}
class _PanelBarWidgetState extends State<PanelBarWidget> {
#override
Widget build(BuildContext context) {
return new TabBarView(
controller: widget._tabController,
children: widget._tabsContainer.map(createView).toList());
}
Container createView(x) {
return Container(
color: Colors.lightGreen,
child: Center(
child: Text(x),
),
);
}
}
But maybe can exists a different solution?

How to send simple data from `secondpage` to `mainpage` (stateful to stateful)

i found a lot of solution passing data between stateless and stateful widget, but not between two stateful widgets
EDIT: i edited the code to show more details
MainPage
class MainPage extends StatefulWidget {
final String name;
MainPage({Key key, this.name}) : super(key: key);
#override
_MainPageState createState() => _MainPageState();
}
class _MainPageState extends State<MainPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text("Text from 2nd page -> "), //should return "Text from 2nd page -> BATMAN"
FloatingActionButton(
child: Icon(Icons.android),
onPressed: (){
Navigator.push(context, MaterialPageRoute(
builder: (context) => SecondPage()
));
},
),
],
),
),
);
}
}
SecondPage:
class SecondPage extends StatefulWidget {
SecondPage({Key key}) : super(key: key);
#override
_SecondPageState createState() => _SecondPageState();
}
class _SecondPageState extends State<SecondPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
...
Text("I choose ${_selectedMethod.name}"), // this returned "I choose BATMAN"
...
}
So basically i want to pass ${_selectedMethod.name} from 2ndPage to MainPage. sorry im so bad at explaining :(
You can pass variables back to a previous Page in the Navigator stack by sending it through the .pop() method and expecting them in the previous page with the .then() method:
class MainPage60643815 extends StatefulWidget {
#override
_MainPage60643815State createState() => _MainPage60643815State();
}
class _MainPage60643815State extends State<MainPage60643815> {
String displayTextFromSecondPage = '';
#override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('Test from second page: '),
Text(displayTextFromSecondPage),
],
),
RaisedButton(
onPressed: goToSecondPage,
child: Text('Go to 2nd Page'),
),
],
),
);
}
void goToSecondPage(){
Navigator.of(context).push(MaterialPageRoute(
builder: (context) {
return SecondPage60643815(text: displayTextFromSecondPage);
}
)).then((valueFromSecondPage){
setState(() {
displayTextFromSecondPage = valueFromSecondPage;
});
});
}
}
class SecondPage60643815 extends StatefulWidget {
final String text;
SecondPage60643815({this.text});
#override
_SecondPage60643815State createState() => _SecondPage60643815State();
}
class _SecondPage60643815State extends State<SecondPage60643815> {
TextEditingController _textEditingController;
#override
void initState() {
_textEditingController = TextEditingController(
text: widget.text,
);
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_back),
onPressed: goToFirstPage,
),
),
body: Center(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
TextFormField(
controller: _textEditingController,
autofocus: true,
),
],
),
),
),
);
}
void goToFirstPage(){
Navigator.of(context).pop(_textEditingController.text);
}
}
I assume that you have a SecondPage-Widget. So you can do something like:
class _MainPageState extends State<MainPage> {
#override
Widget build(BuildContext context) {
return Container(
child: SecondPage('BATMAN'),
);
}
}
This might print the desired "BATMAT" Text.
EDIT
This might be your SecondPage Widget:
class SecondPage extends StatefulWidget {
final String selection;
SecondPage(this.selection);
#override
_SecondPageState createState() => _SecondPageState();
}
class _SecondPageState extends State<SecondPage> {
#override
Widget build(BuildContext context) {
return Container(
child: Text(widget.selection),
);
}
}