Passing stateless widget from one screen to another screen in Flutter - flutter

I am trying to create a form builder, In one screen I want have small container with icon and text with gesture detector, when I tap on the container it should contruct a new DatePicker Widget. I know how to do it in the same screen, but onTap I want construct the Datepicker in another screen.
This is Form Component Class.
class FormComponents extends StatefulWidget {
#override
_FormComponentsState createState() => _FormComponentsState();
}
class _FormComponentsState extends State<FormComponents> {
final GlobalKey<FormBuilderState> _fbKey = GlobalKey<FormBuilderState>();
int _count = 0;
final formData = FormWidgetData(widget: DatePicker());
#override
Widget build(BuildContext context) {
List<Widget> datePicker = List.generate(_count, (index) => DatePicker());
return Scaffold(
appBar: AppBar(
title: Text('Form Components'),
),
body: Container(
margin: EdgeInsets.all(8.0),
child: Column(
children: <Widget>[
FormBuilder(
key: _fbKey,
initialValue: {
'date': DateTime.now(),
'accept_terms': false,
},
autovalidate: true,
child: Column(
children: <Widget>[
Builder(
builder: (BuildContext context) {
return GestureDetector(
onTap: () {
setState(() {
_count = _count + 1;
});
Scaffold.of(context).showSnackBar(
SnackBar(
content: Text('Date Picker'),
duration: Duration(seconds: 2),
),
);
},
child: Container(
margin: EdgeInsets.all(16.0),
padding: EdgeInsets.all(8.0),
height: 100.0,
width: 120.0,
color: Colors.black,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Icon(
Icons.date_range,
color: Colors.white,
),
Text(
'Date Picker',
style: TextStyle(
color: Colors.white, fontSize: 18.0),
),
],
),
),
);
},
),
Container(
height: 200.0,
margin: EdgeInsets.all(8.0),
child: Expanded(
child: ListView(
children: datePicker,
),
),
),
],
),
),
],
),
),
);
}
}
This is my Date Picker Class
class DatePicker extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
child: FormBuilderDateTimePicker(
attribute: 'date',
inputType: InputType.date,
format: DateFormat('yyyy-MM-dd'),
decoration: InputDecoration(labelText: 'AppointmentTime'),
),
);
}
}
This is my Form Builder Class, How to do I Construct the above Date Picker class here.
class MyFormBuilder extends StatefulWidget {
final FormWidgetData data;
MyFormBuilder({this.data});
#override
_MyFormBuilderState createState() => _MyFormBuilderState();
}
class _MyFormBuilderState extends State<MyFormBuilder> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Form Builder'),
),
body: Container(
height: 300.0,
margin: EdgeInsets.all(8.0),
child: Expanded(
child: ListView(
children: <Widget>[],
),
),
),
);
}
}

Related

Navigate the page

I am new to Flutter. I know how to navigate from a page to another page, but the problem is, my navigation does not work. In my short experience, I realized that you cannot navigate from the stateless to the stateful widget or the opposite one.
I will share my code below. So could you please tell me what kind of mistake I am making?
Thank you. :)
Actually I was planning to remove the button because this page could be the intro page like it could show the image and text I want and after 3 seconds it could go to the MainApp() page. Maybe if you have any idea how to do it. I would like to hear that too.:)
void main() {
runApp(Intro());
}
class Intro extends StatefulWidget {
#override
_IntroState createState() => _IntroState();
}
class _IntroState extends State<Intro> {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.yellow.shade300,
body: SafeArea(
child: (Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Expanded(
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Image.asset(
'assets/dinoapp2.png',
height: 200.0,
width: 200.0,
),
),
),
Expanded(
child: Padding(
padding: const EdgeInsets.only(top: 40.0),
child: Text(
'Big Title',
textAlign: TextAlign.center,
style: TextStyle(
fontFamily: 'Russo One Regular',
fontSize: 30.0,
color: Colors.blueAccent),
),
),
),
Container(
margin: EdgeInsets.fromLTRB(120.0, 20, 120, 100),
child: RaisedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => MainApp()),
);
},
padding: EdgeInsets.all(20.0),
textColor: Colors.black,
color: Colors.white,
child: Text(
"Start",
style: TextStyle(fontSize: 20.0),
),
),
)
],
)),
),
),
);
}
}
class MainApp extends StatefulWidget {
#override
_MainAppState createState() => _MainAppState();
}
class _MainAppState extends State<MainApp> {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.blue,
body: SafeArea(
child: Center(
child: Text('This page I want to go after I press Start button'),
),
),
),
);
}
}
Try This
void main() {
runApp(MaterialApp(
home: Intro(),
));
}
class Intro extends StatefulWidget {
#override
_IntroState createState() => _IntroState();
}
class _IntroState extends State<Intro> {
#override
void initState() {
Future.delayed(Duration(seconds: 3), () {
Route route = MaterialPageRoute(builder: (context) => MainApp());
Navigator.push(context, route);
});
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.yellow.shade300,
body: SafeArea(
child: (Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Expanded(
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Image.asset(
'assets/dinoapp2.png',
height: 200.0,
width: 200.0,
),
),
),
Expanded(
child: Padding(
padding: const EdgeInsets.only(top: 40.0),
child: Text(
'Big Title',
textAlign: TextAlign.center,
style: TextStyle(
fontFamily: 'Russo One Regular',
fontSize: 30.0,
color: Colors.blueAccent),
),
),
),
Center(
child: CircularProgressIndicator(),
)
],
)),
),
);
}
}
class MainApp extends StatefulWidget {
#override
_MainAppState createState() => _MainAppState();
}
class _MainAppState extends State<MainApp> {
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.blue,
body: SafeArea(
child: Center(
child: Text('This page I want to go after I press Start button'),
),
),
);
}
}
Just Add this function in your intro class
#override
void initState() {
super.initState();
Future.delayed(const Duration(seconds: 2), () {
Navigator.push( context, MaterialPageRoute(builder: (context) =>
MainApp()),
); });
}
I don't know why but I copied your code into Intro class. It didn't work. :(

Change String value from one stateful widget to another stateful widget

I have a Stateful widget:
class PractiseInterview extends StatefulWidget {
#override
_PractiseInterviewState createState() => _PractiseInterviewState();
}
class _PractiseInterviewState extends State<PractiseInterview> {
String outputText = '0';
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Practise'),
),
body: Container(
child: Column(
children: <Widget>[
Text(
outputText, //**outputText is here**
),
Expanded(
child: Divider(),
),
Column(
children: <Widget>[
Row(
children: <Widget>[
ChnageText(text: 'changed',),
],
),
],
)
],
),
),
);
}
}
NOTICE that my outputText = '0' here.
Then I have a stateless widget for my OutlineButton in stateful widget:
class ChnageText extends StatelessWidget {
const ChnageText({ this.text});
final String text;
buttonPressed(String text) {
if (text == 'changed') {
//TODO: change outputText value to 'changed' at the click of this button
}
}
#override
Widget build(BuildContext context) {
return Expanded(
child: OutlineButton(
onPressed: () {
buttonPressed(text);
},
child: Padding(
padding: const EdgeInsets.all(24.0),
child: Text(
text,
style: TextStyle(
fontSize: 15.0,
fontWeight: FontWeight.bold,
),
),
),
),
);
}
}
I have mentioned TODO in my stateless widget, there at the click of the button I want to change outputText = '0' to outputText = 'changed'. I don't know how to do this
I am new to flutter and I am not able to understand this. Basically I am making a calculator where when a button is clicked, then the value of the button should be displayed.
Pass a callback to ChnageText from the parent that changes outputText and calls setState.
class ChnageText extends StatelessWidget {
const ChnageText({this.text, this.callback});
final String text;
final VoidCallback callback;
buttonPressed(String text) {
if (text == 'changed') {
callback();//Call callback here
}
}
#override
Widget build(BuildContext context) {
return Expanded(
child: OutlineButton(
onPressed: () {
buttonPressed(text);
},
child: Padding(
padding: const EdgeInsets.all(24.0),
child: Text(
text,
style: TextStyle(
fontSize: 15.0,
fontWeight: FontWeight.bold,
),
),
),
),
);
}
}
class _PractiseInterviewState extends State<PractiseInterview> {
String outputText = '0';
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Practise'),
),
body: Container(
child: Column(
children: <Widget>[
Text(
outputText, //**outputText is here**
),
Expanded(
child: Divider(),
),
Column(
children: <Widget>[
Row(
children: <Widget>[
ChnageText(text: 'changed', callback: () {setState((){outputText = 'changed';});}),// Pass callback here
],
),
],
)
],
),
),
);
}
}
Ideally, you wouldn't have to do this at all. What's in ChnageText doesn't need to be in its own StatelessWidget. Putting all of that directly in the parent removes this problem.
class _PractiseInterviewState extends State<PractiseInterview> {
String outputText = '0';
buttonPressed(String text) {
if (text == 'changed') {
setState(() {
outputText = 'changed';
});
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Practise'),
),
body: Container(
child: Column(
children: <Widget>[
Text(
outputText, //**outputText is here**
),
Expanded(
child: Divider(),
),
Column(
children: <Widget>[
Row(
children: <Widget>[
//Put ChnageText directly into the build of the parent
Expanded(
child: OutlineButton(
onPressed: () {
buttonPressed('changed');
},
child: Padding(
padding: const EdgeInsets.all(24.0),
child: Text(
'changed',
style: TextStyle(
fontSize: 15.0,
fontWeight: FontWeight.bold,
),
),
),
),
),
],
),
],
)
],
),
),
);
}
}

Flutter/Dart: update some variables but not others when using setState()

I'm trying to improve my understanding of Flutter, and am struggling with an issue. I am trying to create an app that presents a list of cards which pull data from a list. There is a button on the bottom that creates a new card when the user clicks it.
I am trying to get each card to display a unique 'Round number'. So for example each time the user clicks the button, a card will be added that displays sequential numbers next to the word 'Round'. Round 1 > Round 2 > Round 3 and so on.
Right now everything works except that every time the button is pressed all the cards are updated with the latest number. And so instead of getting a sequential list of cards, every card is updated to the latest round number.
What am I doing wrong? Thank you.
Here is my code:
import 'package:flutter/material.dart';
class Round {
int roundNumber;
int firstNumber;
int secondNumber;
Round({ this.roundNumber, this.firstNumber, this.secondNumber, });
}
int uid = 1;
List<Round> roundsList = [
Round(roundNumber: uid, firstNumber: 1, secondNumber: 2),
];
class createLevels extends StatefulWidget {
#override
_createLevelsState createState() => _createLevelsState();
}
class _createLevelsState extends State<createLevels> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text("Create Rounds",)
),
body: Padding(
padding: const EdgeInsets.fromLTRB(20, 20, 20.0, 20),
child: Container(
child: Column(
children: <Widget>[
Expanded(
child: ListView.builder(
itemCount: roundsList.length,
itemBuilder: (BuildContext context, int whatIsThisVariable) {
return roundCard(Round(roundNumber: uid, firstNumber: 2, secondNumber: 3,));
}
),
),
Text("$roundsList"),
RaisedButton(
onPressed: () {
uid++;
roundsList.add(Round(roundNumber: uid));
setState(() {});
},
child: Text("Add Round"),
),
],
),
),
),
);
}
}
class roundCard extends StatelessWidget {
final Round round;
roundCard(this.round);
// roundsList.add(Round(roundNumber: 1));
#override
Widget build(BuildContext context) {
return Container(
child: Card(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Spacer(
flex: 1,
),
Expanded(
child: Text('Round ${round.roundNumber}:'),
flex: 12,
),
Expanded(
child: TextFormField(
textAlign: TextAlign.center,
decoration: InputDecoration(
hintText: '${round.firstNumber}',
),
),
flex: 3,
),
Spacer(
flex: 1,
),
Expanded(
child: TextFormField(
textAlign: TextAlign.center,
decoration: InputDecoration(
hintText: '${round.secondNumber}',
),
),
flex: 3,
),
],
),
)
),
);
}
}
You can copy paste run full code below
You need to pass index not uid
You can adjust first and second number you want
code snippet
itemBuilder: (BuildContext context, int index) {
return roundCard(roundsList[index]);
}),
...
onPressed: () {
uid++;
firstNumber++;
secondNumber++;
roundsList.add(
Round(roundNumber: uid, firstNumber: firstNumber, secondNumber: secondNumber));
setState(() {});
}
working demo
full code
import 'package:flutter/material.dart';
class Round {
int roundNumber;
int firstNumber;
int secondNumber;
Round({
this.roundNumber,
this.firstNumber,
this.secondNumber,
});
}
int uid = 1;
int firstNumber = 2;
int secondNumber = 3;
List<Round> roundsList = [
Round(roundNumber: uid, firstNumber: 1, secondNumber: 2),
];
class createLevels extends StatefulWidget {
#override
_createLevelsState createState() => _createLevelsState();
}
class _createLevelsState extends State<createLevels> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text(
"Create Rounds",
)),
body: Padding(
padding: const EdgeInsets.fromLTRB(20, 20, 20.0, 20),
child: Container(
child: Column(
children: <Widget>[
Expanded(
child: ListView.builder(
itemCount: roundsList.length,
itemBuilder: (BuildContext context, int index) {
return roundCard(roundsList[index]);
}),
),
Text("$roundsList"),
RaisedButton(
onPressed: () {
uid++;
firstNumber++;
secondNumber++;
roundsList.add(
Round(roundNumber: uid, firstNumber: firstNumber, secondNumber: secondNumber));
setState(() {});
},
child: Text("Add Round"),
),
],
),
),
),
);
}
}
class roundCard extends StatelessWidget {
final Round round;
roundCard(this.round);
// roundsList.add(Round(roundNumber: 1));
#override
Widget build(BuildContext context) {
return Container(
child: Card(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Spacer(
flex: 1,
),
Expanded(
child: Text('Round ${round.roundNumber}:'),
flex: 12,
),
Expanded(
child: TextFormField(
textAlign: TextAlign.center,
decoration: InputDecoration(
hintText: '${round.firstNumber}',
),
),
flex: 3,
),
Spacer(
flex: 1,
),
Expanded(
child: TextFormField(
textAlign: TextAlign.center,
decoration: InputDecoration(
hintText: '${round.secondNumber}',
),
),
flex: 3,
),
],
),
)),
);
}
}
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: createLevels(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.display1,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}

How to animate hiding AppBar in Flutter?

I need help with animating my AppBar.
My AppBar hides on DoubleTap, but there's no animation in it, it hides immediately. I want it to be animated. I tried to wrap my AppBar with SlideTransition and AnimatedContainer widget, but none of these work, because the error says I need a PreferredSize widget.
I would be extremely glad, if someone helped me!
I already checked out this answer, but the guy, who answered to this question, has the same problem. There's no animation. Show (slide in) or hide (slide out) flutter AppBar on screen tap
Here's the video of my AppBar:
https://streamable.com/it7ib
Here's the photo how my AppBar looks like:
Code:
import 'package:flutter/material.dart';
class GeneratedCouponScreen extends StatefulWidget {
#override
_GeneratedCouponScreenState createState() => _GeneratedCouponScreenState();
}
class _GeneratedCouponScreenState extends State<GeneratedCouponScreen> {
bool showAppBar = true;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: showAppBar ? AppBar() : null ,
backgroundColor: Colors.white,
body: GestureDetector(
onDoubleTap: () {
if (showAppBar) {
setState(() {
showAppBar = false;
});
}
else {
setState(() {
showAppBar = true;
});
}
},
child: SafeArea(
child: Container(
padding: EdgeInsets.all(16.0),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('DATA WYDANIA:', style: TextStyle(color: Colors.black),),
Text('10/09/2019', style: TextStyle(color: Colors.black))
],
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('UNIKALNY KOD:', style: TextStyle(color: Colors.black)),
Text('e-86-tC-9', style: TextStyle(color: Colors.black))
],
)
],
),
Column(
children: [
SizedBox(height: 8.0),
Image.asset('assets/images/coupon_hamburger.png',)
],
)
],
)
),
)));
}
}
One way of doing it is by using stack and AnimatedBuilder.
class GeneratedCouponScreen extends StatefulWidget {
#override
_GeneratedCouponScreenState createState() => _GeneratedCouponScreenState();
}
class _GeneratedCouponScreenState extends State<GeneratedCouponScreen>
with SingleTickerProviderStateMixin {
AnimationController _controller;
#override
void initState() {
super.initState();
_controller = AnimationController(
vsync: this,
duration: Duration(milliseconds: 300),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: SafeArea(
child: AnimatedBuilder(
animation: _controller,
builder: (context, child) => Stack(
children: <Widget>[
Transform.translate(
offset: Offset(0, -_controller.value * 64),
child: Container(
height: 56.0,
child: AppBar(
title: Text('Title'),
leading: Icon(
Icons.arrow_back,
),
),
),
),
GestureDetector(
onDoubleTap: () {
if (_controller.isCompleted) {
_controller.reverse();
} else {
_controller.forward();
}
},
child: Container(
margin: const EdgeInsets.only(top: 56.0),
padding: EdgeInsets.all(16.0),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'DATA WYDANIA:',
style: TextStyle(color: Colors.black),
),
Text('10/09/2019',
style: TextStyle(color: Colors.black))
],
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('UNIKALNY KOD:',
style: TextStyle(color: Colors.black)),
Text('e-86-tC-9',
style: TextStyle(color: Colors.black))
],
)
],
),
Column(
children: [
SizedBox(height: 8.0),
Image.network(
'http://via.placeholder.com/640x360',
)
],
)
],
),
),
),
],
),
),
),
);
}
}
First you have to create a new class
class MyAppBar extends StatefulWidget implements PreferredSizeWidget {
num height = 70.0;
#override
_MyAppBarState createState() => _MyAppBarState();
#override
Size get preferredSize => Size.fromHeight(height);
}
class _MyAppBarState extends State<MyAppBar> {
#override
Widget build(BuildContext context) {
return Container(
child: GestureDetector(
onDoubleTap: () {
// Your logic here
// You can do any stuff like animating your this appBar
//e.g: using Opacitiy or Transform and any other Widget depending on what kind of animation you want
// You can also descrease height by calling widget.height
},
child: AppBar(
//Your logic here
),
),
);
}
}
Then call it like this
return Scaffold(
appBar: MyAppBar(),);

How to center AppBar and how to reduce leading icon size in PrefrerredSize?

How to center whole AppBar and how to reduce leading icon?
I tried with Center widget and Column with mainAxisAlignment.center not working.
And I tried add width and height to leading icon container.but nothing is working
appBar: PreferredSize(
child: AppBar(
leading: Container(
decoration: BoxDecoration(..),
child: Icon(..),
),
title: TextFormField(
...
),
actions: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
...
),
CupertinoSwitch(
...
)
],
)
],
),
preferredSize: Size.fromHeight(80.0)),
As shown here.
as an option
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AwesomeAppBar(height: 80),
),
);
}
}
class AwesomeAppBar extends PreferredSize {
final double height;
const AwesomeAppBar({Key key, #required this.height});
#override
Widget build(BuildContext context) {
return LayoutBuilder(builder: (context, snapshot) {
return Container(
padding: EdgeInsets.only(top: MediaQuery.of(context).padding.top),
height: height,
color: Theme.of(context).primaryColor,
child: Row(
children: <Widget>[
Container(
padding: EdgeInsets.all(16),
child: Icon(
Icons.arrow_back,
color: Colors.white,
),
),
Expanded(
child: Container(
height: 32,
alignment: Alignment.centerLeft,
padding: EdgeInsets.symmetric(horizontal: 16),
margin: EdgeInsets.only(right: 16),
decoration: ShapeDecoration(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
color: Colors.white,
),
child: Text('Search'),
),
),
SwitchWithText(),
SizedBox(width: 16),
],
),
);
});
}
#override
Size get preferredSize => Size.fromHeight(height);
}
class SwitchWithText extends StatefulWidget {
#override
_SwitchWithTextState createState() => _SwitchWithTextState();
}
class _SwitchWithTextState extends State<SwitchWithText> {
#override
Widget build(BuildContext context) {
return Row(
children: <Widget>[
Text('Online', style: TextStyle(color: Colors.white)),
CupertinoSwitch(
value: true,
onChanged: (b) {},
activeColor: Colors.lightBlueAccent,
),
],
);
}
}