How to pass data from card to new page in flutter - dart

I want to pass the data from card to new page,the data has two names START and at below STOP on card.When the user clicks on card the "START" data should pass to new page.Below is the code
class MyList extends StatefulWidget {
#override
_MyListState createState() => _MyListState();
}
class _MyListState extends State<MyList> {
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: Text("List"),
),
body: new Container(
padding: new EdgeInsets.only(left: 5.0,top: 20.0,right: 5.0),
child: new Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
GestureDetector(
onTap: (){
},
child: new Card(
child:
new Column(
children: <Widget>[
new Text('START'),
new Text('STOP')
],
),
),
),
New page
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("New page"),
),
body:Container(
child:Center(
new Text('textview'))

Your new page MyHomePage should accept the required inputs as arguments, like
class MyHomePage extends StatefulWidget {
final String startText;
final String stopText;
MyHomePage(this.startText, this.stopText);
....
}
.....
onTap should create new instance of MyHomePage with this data and launch the page like
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => MyHomePage("start", "stop"),
),
);

Related

How to remove null text on the screen in flutter

I build an app in which there are two pages(screens),the first page receives the data from second page.But the problem is that before getting the data from second page it is showing "null" on the first page screen.Below are the codes of these two pages.Note:The first page screen is the main launcher screen.
First Page
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
String value;
MyHomePage({Key key,this.value}):super(key:key);
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Flutter"),
),
body:Center(
child:new Text("${widget.value}") )
}
Second Page
class _List extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: MyList(),
);
}
}
class MyList extends StatefulWidget {
#override
_MyListState createState() => _MyListState();
}
class _MyListState extends State<MyList> {
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: Text("List"),
),
body: new Container(
padding: new EdgeInsets.only(left: 5.0,top: 20.0,right: 5.0),
child: new Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
GestureDetector(
onTap: (){
var route=new MaterialPageRoute(builder: (BuildContext context)=>new MyHomePage(value: "Apple",),
);
Navigator.of(context).push(route);
},
child: new Card(
child:
new Column(
children: <Widget>[
new Text('Apple'),
new Text('Banana')
],
),
),
),
);
}
}
You can use a blank Container() widget instead of Text() widget like the code below :
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Flutter"),
),
body:Center(
child: widget.value==null ? Container() : new Text("${widget.value}")
)
);
}
}

Material app in Column with regular sized navigation bar

I want to display an Image on top of my entire app. So I Placed an image and my dashboard in a column in Main.dart file
My main.dart file.
void main() => runApp(new MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Scaffold(
body: new SafeArea(
child: Column(
children: <Widget>[
new Image.asset('assets/ads.png'),
new Expanded(
child: Dashboard(),
)
],
),
),
),
);
}
}
and Dashboard.dart
import 'package:flutter/material.dart';
class Dashboard extends StatefulWidget {
#override
_DashboardState createState() => _DashboardState();
}
class _DashboardState extends State<Dashboard> {
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new Scaffold(
appBar: new AppBar(title: new Text('Books')),
body: new Container(
child: new Center(
child: new Text('data'),
),
),
),
);
}
}
Now, this code generates output like this.
I need regular sized Appar. This AppBar is really big. Can someone suggest what's wrong here?
Do Like This :-
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
Widget build(BuildContext context) {
return new MaterialApp(
debugShowCheckedModeBanner: false,
home: new Scaffold(
body: new SafeArea(
child: Column(
children: <Widget>[
new Image.network("https://via.placeholder.com/350x100"),
new Expanded(
child: Dashboard(),
)
],
),
),
),
);
}
}
class Dashboard extends StatefulWidget {
#override
_DashboardState createState() => _DashboardState();
}
class _DashboardState extends State<Dashboard> {
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(title: new Text('Books')),
body: new Container(
child: new Center(
child: new Text('data'),
),
),
);
}
}

Emit the data to parent Widget in Flutter

I'm trying to set the text from child widget to parent widget. But the text is not reflecting in parent widget.
Tried to use setState() also but still unable to get expected result.
Following is my code:
void main() => runApp(new TestApp());
class TestApp extends StatefulWidget {
#override
_TestState createState() => new _TestState();
}
class _TestState extends State<TestApp>{
String abc = "";
#override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Scaffold(
body: new Column(
children: <Widget>[
new Text("This is text $abc"),
TestApp2(abc)
],
),
),
);
}
}
class TestApp2 extends StatefulWidget {
String abc;
TestApp2(this.abc);
#override
_TestState2 createState() => new _TestState2();
}
class _TestState2 extends State<TestApp2>{
#override
Widget build(BuildContext context) {
return new Container(
width: 150.0,
height: 30.0,
margin: EdgeInsets.only(top: 50.0),
child: new FlatButton(
onPressed: (){
setState(() {
widget.abc = "RANDON TEXT";
});
},
child: new Text("BUTTON"),
color: Colors.red,
),
);
}
}
Am i missing something ?
In your example, a few assumptions were made. I will try to remove one by one.
You pass abc from parent to child and you mutated the child value on press on button. As primitive types are pass by value in dart, change in the value of abc in child will not change the value of parent abc. Refer the below snippet.
void main() {
String abc = "oldValue";
changeIt(abc);
print(abc); // oldValue
}
void changeIt(String abc) {
abc = "newValue";
print(abc); //newValue
}
Let's assume the first one is wrong(for understanding purpose). Then changing the value of abc in child will change the value of abc in parent. But without calling that inside setState of parent, parent will not reflect the change. In your case if you change the code as below, it will change the button text alone on click (as setState of child is called).
new FlatButton(
onPressed: () {
setState(
() {
widget.abc = "RANDON TEXT";
},
);
},
child:
new Text(widget.abc), // setting the text based on abc
color: Colors.red,
),
Instead of using globalState which will be very difficult to maintain/debug as app grows, I would recommend using callbacks. Please refer the below code.
void main() => runApp(new TestApp());
class TestApp extends StatefulWidget {
#override
_TestState createState() => new _TestState();
}
class _TestState extends State<TestApp> {
String abc = "bb";
callback(newAbc) {
setState(() {
abc = newAbc;
});
}
#override
Widget build(BuildContext context) {
var column = new Column(
children: <Widget>[
new Text("This is text $abc"),
TestApp2(abc, callback)
],
);
return new MaterialApp(
home: new Scaffold(
body: new Padding(padding: EdgeInsets.all(30.0), child: column),
),
);
}
}
class TestApp2 extends StatefulWidget {
String abc;
Function(String) callback;
TestApp2(this.abc, this.callback);
#override
_TestState2 createState() => new _TestState2();
}
class _TestState2 extends State<TestApp2> {
#override
Widget build(BuildContext context) {
return new Container(
width: 150.0,
height: 30.0,
margin: EdgeInsets.only(top: 50.0),
child: new FlatButton(
onPressed: () {
widget.callback("RANDON TEXT"); //call to parent
},
child: new Text(widget.abc),
color: Colors.red,
),
);
}
}
To write the very precise answer. Just use the call back like the above answer use this.
So you want to call the state of ParentScreen from the another function/widget/class. Just follow this code
import 'package:showErrorMessage.dart';
class ParentScreen extends StatefulWidget {
ParentScreen({Key key}) : super(key: key);
#override
_ParentScreenState createState() => _ParentScreenState();
}
class _ParentScreenState extends State<ParentScreen> {
callback() {
setState(() {});
}
#override
Widget build(BuildContext context) {
String message = "hello";
return Container(
child: showErrorMessage(message, callback);,
);
}
}
And here is the child widget/function/class
import 'package:flutter/material.dart';
showErrorMessage(message, Function callback) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
message,
style: TextStyle(color: Colors.white, fontSize: 16),
),
GestureDetector(
onTap: () {
callback(); // ------ this will change/rebuild the state of its parent class
},
child: Icon(
Icons.refresh,
size: 30,
color: Colors.white,
)),
],
));
}
The point that you are missing is your setState method call. You call the setState of the TestState2.
For fixing that, there are two ways.
First way is to create a GlobalKey(https://docs.flutter.io/flutter/widgets/GlobalKey-class.html) and pass it as a parameter to the child widget.
And the second way is to create a global variable for the parent state and use it in the child state.
I modified the code below with the second approach.
_TestState _globalState = new _TestState();
class TestApp extends StatefulWidget {
#override
_TestState createState() => _globalState;
}
class _TestState extends State<TestApp>{
String abc = "";
#override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Scaffold(
body: new Column(
children: <Widget>[
new Text("This is text $abc"),
TestApp2()
],
),
),
);
}
}
class TestApp2 extends StatefulWidget {
TestApp2();
#override
_TestState2 createState() => new _TestState2();
}
class _TestState2 extends State<TestApp2>{
#override
Widget build(BuildContext context) {
return new Container(
width: 150.0,
height: 30.0,
margin: EdgeInsets.only(top: 50.0),
child: new FlatButton(
onPressed: (){
_globalState.setState((){
_globalState.abc = "Button clicked";
});
},
child: new Text("BUTTON"),
color: Colors.red,
),
);
}
}

Flutter - Stateful Widget Doesn't Save Counter State When Switching Tabs

I am learning flutter and I am working with tabBars and I am having an issue with saving the state. I have put a small working example of my issue below. Basically, there is a button and a stateful counter. When I click the button, I see the text field update correctly. But, when I switch to a different tab and come back, the text field is back to zero.
I have found if i move the following line outside of _CounterState so its defined at the top level of the file, then, it works correctly. When I switch tabs, the counter stays at the correct count when I switch back
int _counter = 0;
I don't feel like this is the appropriate way to do this and all of the examples I have seen have the variable inside of the class. Can anyone give me any insights? Why would it reset if it is inside the class? Am I supposed to keep it outside the class? Below is the simplified full example.
import 'package:flutter/material.dart';
void main() {
runApp(new TabBarDemo());
}
class TabBarDemo extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
home: new DefaultTabController(
length: 3,
child: new Scaffold(
appBar: new AppBar(
bottom: new TabBar(
tabs: [
new Tab(icon: new Icon(Icons.directions_car)),
new Tab(icon: new Icon(Icons.directions_transit)),
new Tab(icon: new Icon(Icons.directions_bike)),
],
),
title: new Text('Tabs Demo'),
),
body: new TabBarView(
children: [
new Counter(),
new Icon(Icons.directions_transit),
new Icon(Icons.directions_bike),
],
),
),
),
);
}
}
class Counter extends StatefulWidget {
#override
_CounterState createState() => new _CounterState();
}
class _CounterState extends State<Counter> {
int _counter = 0;
void _increment() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return new Row(
children: <Widget>[
new RaisedButton(
onPressed: _increment,
child: new Text('Increment'),
),
new Text('Count: $_counter'),
],
);
}
}
Below is the example with the counter moved outside of the class
import 'package:flutter/material.dart';
void main() {
runApp(new TabBarDemo());
}
class TabBarDemo extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
home: new DefaultTabController(
length: 3,
child: new Scaffold(
appBar: new AppBar(
bottom: new TabBar(
tabs: [
new Tab(icon: new Icon(Icons.directions_car)),
new Tab(icon: new Icon(Icons.directions_transit)),
new Tab(icon: new Icon(Icons.directions_bike)),
],
),
title: new Text('Tabs Demo'),
),
body: new TabBarView(
children: [
new Counter(),
new Icon(Icons.directions_transit),
new Icon(Icons.directions_bike),
],
),
),
),
);
}
}
class Counter extends StatefulWidget {
#override
_CounterState createState() => new _CounterState();
}
int _counter = 0; //<-- MOVED OUTSIDE THE _CounterState CLASS
class _CounterState extends State<Counter> {
void _increment() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return new Row(
children: <Widget>[
new RaisedButton(
onPressed: _increment,
child: new Text('Increment'),
),
new Text('Count: $_counter'),
],
);
}
}
As _CounterState widget is built everytime you go to the given TabView you'll need to put _counter variable in the state configuration class (Counter).
class Counter extends StatefulWidget {
int _counter = 0;
#override
_CounterState createState() => new _CounterState();
}
class _CounterState extends State<Counter> {
void _increment() {
setState(() {
widget._counter++;
});
}
#override
Widget build(BuildContext context) {
return new Row(
children: <Widget>[
new RaisedButton(
onPressed: _increment,
child: new Text('Increment'),
),
new Text('Count: ${widget._counter}'),
],
);
}
}
As I used one solution AutomaticKeepAliveClientMixin
You need to use this mixin with your state class of StateFullWidget.
you need to pass true to wantKeepAlive getter method.
class SampleWidget extends StatefulWidget {
#override
_SampleWidgetState createState() => _SampleWidgetState();
}
class _SampleWidgetState extends State<SampleWidget> with AutomaticKeepAliveClientMixin{
#override
Widget build(BuildContext context) {
super.build(context);
return Container();
}
#override
// TODO: implement wantKeepAlive
bool get wantKeepAlive => true;
}
This will save your state and stop your widget to recreate again. I have used it with Tabbar and PageView and it's working fine.
put the variable in that statefulwidget and then call it every time as "widget.variable_name"

Transparent sticky footer in Flutter

I was following this Stack Overflow post for making a sticky footer. The footer performs like it needs to, but is there a way to add transparency so the items in the list behind the footer can be visible?
Solid footer
Transparent footer
Here is all the code for making the solid footer
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
home: new MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage();
#override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return new Scaffold(
body: new Column(
children: <Widget>[
new Expanded(
child: new ListView.builder(
itemCount: 200,
itemBuilder: (context, index) {
return new ListTile(
title: new Text("title $index"),
);
},
),
),
new Container(
height: 40.0,
color: Colors.red,
),
],
),
);
}
}
You can use Stack to display widgets on the top of each others.
new Scaffold(
body: new Stack(
alignment: Alignment.bottomCenter,
children: [
new ListView(...),
new Container(height: 40.0, color: Colors.red),
],
),
),

Resources