Flutter : unable to reuse views in appdrawer - dart

File:homepage.dart
class _HomePageState extends State<HomePage> {
var _scaffoldBody;
var _scaffoldTitle;
#override
initState() {
_scaffoldTitle=new Text("Wall");
_scaffoldBody=new Center(child:CircularProgressIndicator());
}
#override
Widget build(BuildContext context) {
return Scaffold(
drawer: new Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: <Widget>[
DrawerHeader(
child: Text('Drawer Header'),
decoration: BoxDecoration(
color:Theme.of(context).accentColor,
),
),
ListTile(
title: Text('Home'),
onTap: () {
setState(() {
_scaffoldTitle=new Text("Home");
_scaffoldBody=new Text("Home Page");
});
Navigator.pop(context);
},
),
ListTile(
title: Text('MenuItem1'),
onTap: () {
setState(() {
_scaffoldTitle=new Text("1st Menu");
_scaffoldBody=new TestPage("Page 1");
});
Navigator.pop(context);
},
),
ListTile(
title: Text('MenuItem2'),
onTap: () {
setState(() {
_scaffoldTitle=new Text("2nd Item");
_scaffoldBody=new TestPage("Page 2");
});
Navigator.pop(context);
},
),
],
),
),
appBar: new AppBar(
title: _scaffoldTitle,
elevation: 2.0,
actions: <Widget>[
],
),
body:_scaffoldBody,
);
}
file: TestPage.dart
import 'package:flutter/material.dart';
class TestPage extends StatefulWidget{
final String rollNumber;
TestPage(this.rollNumber);
#override
TestPageState createState() => new TestPageState(rollNumber);
}
class TestPageState extends State<TestPage>{
String rollNumber;
TestPageState(this.rollNumber);
#override
Widget build(BuildContext context) {
return new Text(rollNumber);
}
}
Output:
When I chose : "Home" from drawer it shows "Home Page"
Then I chose : "MenuItem1" it showed "Page 1"
Then I chose : "MenuItem2" it showed same "Page 1" (unexpected)
Then I chose : "Home" it showed "Home Page"
Then I chose : "MenuItem2" it showed correctly as "Page 2"
Then I chose : "MenuItem1" it showed "Page 2" (unexpected)
unable to solve this.Stuck!! Any solutions are appreciated. Thanks in advance!!

Update your TestPart.dart as follow:
import 'package:flutter/material.dart';
class TestPage extends StatefulWidget{
final String rollNumber;
TestPage(this.rollNumber);
#override
TestPageState createState() => new TestPageState();
}
class TestPageState extends State<TestPage>{
#override
Widget build(BuildContext context) {
return new Text(widget.rollNumber);
}
}

My StudentPage Class
import 'package:flutter/material.dart';
import 'package:firebase_database/firebase_database.dart';
import 'calendar_utils.dart';
import 'dart:async';
final mainReference = FirebaseDatabase.instance.reference();
class StudentPage extends StatefulWidget{
final String rollNumber;
StudentPage(this.rollNumber);
#override
StudentPageState createState() => new StudentPageState(rollNumber);
}
class StudentPageState extends State<StudentPage>{
final String currentRoll,currentYear="2018-19";
StudentPageState(this.currentRoll);
List<String> academicMonth=["June","July","August","September","October","November","December",
"January","February","March","April","May"];
int firstHalfYear=2018,secondHalfYear=2019;
List<Widget> _monthListArray=[new ListTile(title:new Text("Academic Year",style: new TextStyle(fontWeight: FontWeight.bold,fontSize: 20.0),),)];
List<Widget> _listView;
int _no_of_working=0;
int _no_of_present=0;
#override
void initState() {
// TODO: implement initState
_listView=[new Center(
child: new CircularProgressIndicator(),
)];
_loadMonths();
}
#override
Widget build(BuildContext context) {
return new RefreshIndicator(child: new ListView(
children: _listView,
), onRefresh: _loadMonths);
}
Future<Null> _loadMonths() async {
_listView.clear();
await mainReference.child("XXXX").child("attendance").child(
widget.rollNumber).child(currentYear).once().then((
DataSnapshot dataSnapshot) {
try {
int monthIndex=5; //monthIndex starts from June
for(var month in academicMonth){
debugPrint("Month:"+month);
monthIndex=(monthIndex+1)%12; //month index cycles throughout 1-12
if(monthIndex==0) monthIndex=12;
List<Widget> _daysList=[];
_monthListArray.add(new Padding(padding: EdgeInsets.all(16.0),child: new Text(month+" "+(monthIndex<6?secondHalfYear:firstHalfYear).toString(),style: new TextStyle(color: Colors.black87,fontWeight: FontWeight.bold,fontSize: 20.0),),)); //initializing the month
_monthListArray.add(new Padding(padding: EdgeInsets.only(top: 10.0,bottom: 10.0),child:
new Row(children: <Widget>[
new Expanded(
child: new Center(child: new Text("S",style: new TextStyle(fontWeight: FontWeight.bold),),),
),
new Expanded(
child: new Center(child: new Text("M",style: new TextStyle(fontWeight: FontWeight.bold),),),
),
new Expanded(
child: new Center(child: new Text("T",style: new TextStyle(fontWeight: FontWeight.bold),),),
),
new Expanded(
child: new Center(child: new Text("W",style: new TextStyle(fontWeight: FontWeight.bold),),),
),
new Expanded(
child: new Center(child: new Text("T",style: new TextStyle(fontWeight: FontWeight.bold),),),
),
new Expanded(
child: new Center(child: new Text("F",style: new TextStyle(fontWeight: FontWeight.bold),),),
),
new Expanded(
child: new Center(child: new Text("S",style: new TextStyle(fontWeight: FontWeight.bold),),),
),
],),));
debugPrint(monthIndex.toString());
int freeSpace=CalendarUtils(1,monthIndex,monthIndex<6?secondHalfYear:firstHalfYear).getDayFromDate();
debugPrint("FreeSpace---"+freeSpace.toString());
if(freeSpace!=0){
for (var i = 0; i < freeSpace; i++) {
_daysList.add(new Text(""));
}
}
debugPrint(monthIndex.toString());
var year=monthIndex<6?secondHalfYear:firstHalfYear;
debugPrint("Year"+year.toString());
debugPrint("Forloop limit:"+CalendarUtils(1,monthIndex,monthIndex<6?firstHalfYear:secondHalfYear).numberOfDays().toString());
for(var day=1;day<=CalendarUtils(1,monthIndex,monthIndex<6?secondHalfYear:firstHalfYear).numberOfDays();day++){
try {
//debugPrint(day.toString()+":"+dataSnapshot.value[month][day].toString());
if (CalendarUtils(day, monthIndex,
monthIndex < 6 ? secondHalfYear: firstHalfYear)
.getDayFromDate() != 0){
if (dataSnapshot.value[month][day].toString() == "1") {
_no_of_working++;
_no_of_present++;
_daysList.add(
new Padding(padding: EdgeInsets.only(left: 10.0,right: 10.0,top: 2.0,bottom: 2.0),
child: new Container(
alignment: Alignment.center,
width: 30.0,
height: 30.0,
decoration: new BoxDecoration(
borderRadius: new BorderRadius.all(new Radius.circular(50.0)),
color: Colors.green),
child: new Text(
day.toString(),
style: new TextStyle(color: Colors.white),
),
),
)
);
}
else if (dataSnapshot.value[month][day].toString() == "0"){
_no_of_working++;
_daysList.add(
new Padding(padding: EdgeInsets.only(left: 10.0,right: 10.0,top: 2.0,bottom: 2.0),
child: new Container(
alignment: Alignment.center,
width: 30.0,
height: 30.0,
decoration: new BoxDecoration(
borderRadius: new BorderRadius.all(new Radius.circular(50.0)),
color: Colors.redAccent),
child: new Text(
day.toString(),
style: new TextStyle(color: Colors.white),
),
),
)
);
}
else {
_daysList.add(
new Padding(padding: EdgeInsets.only(left: 10.0,right: 10.0,top: 2.0,bottom: 2.0),
child: new Container(
alignment: Alignment.center,
width: 30.0,
height: 30.0,
decoration: new BoxDecoration(
borderRadius: new BorderRadius.all(new Radius.circular(50.0)),
),
child: new Text(
day.toString(),
style: new TextStyle(color: Colors.black),
),
),
)
);
}
}else {
_daysList.add(
new Center(child: new Text(day.toString(), style:
new TextStyle(color: Colors.black45),)));
}
}catch (e){
_daysList.add(new Center(child:new Text(day.toString(),style:
new TextStyle(color: Colors.black),) ));
}
}
Widget _daysGrid=new GridView.count(crossAxisCount: 7,
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
childAspectRatio: 1.5,
children: _daysList,
);
_monthListArray.add(_daysGrid);
}
}catch(e){}
_monthListArray.add(new Text((_no_of_present/_no_of_working).toString()));
});
this.setState((){
_listView=_monthListArray;
});
}
}

My HomePage.dart
import 'package:flutter/material.dart';
import 'package:smart_school_parent/TestPage.dart';
import 'package:smart_school_parent/attendance.dart';
import 'package:smart_school_parent/post.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:smart_school_parent/auth.dart';
import 'dart:async';
class HomePage extends StatefulWidget {
final BaseAuth auth;
final VoidCallback onSignOut;
HomePage({Key key, this.auth, this.onSignOut}) : super(key: key);
#override
_HomePageState createState() => new _HomePageState(this.auth);
}
class _HomePageState extends State<HomePage> {
final mainReference = FirebaseDatabase.instance.reference();
List<PostData> post_list = new List();
var _scaffoldBody;
var _loading;
var _currentYear;
var _scaffoldTitle;
List<Widget> _childrenList=[new Text("Profiles",textAlign: TextAlign.left,style: new TextStyle(fontWeight: FontWeight.bold),)];
BaseAuth auth;
_HomePageState(this.auth);
#override
initState() {
//_children=updateChildren();
_updateChildren();
getList();
_loading=true ;
_scaffoldTitle=new Text("Wall");
_scaffoldBody=new Center(child:CircularProgressIndicator());
}
#override
Widget build(BuildContext context) {
return Scaffold(
drawer: new Drawer(
child: ListView(
// Important: Remove any padding from the ListView.
padding: EdgeInsets.zero,
children: <Widget>[
DrawerHeader(
child: Text('XXXXx'),
decoration: BoxDecoration(
color:Theme.of(context).accentColor,
),
),
ListTile(
title: Text('Wall'),
onTap: () {
setState(() {
_scaffoldTitle=new Text("Wall");
_scaffoldBody=new RefreshIndicator(child: _loadWall(), onRefresh: getList);
});
Navigator.pop(context);
},
),
Column(
children: _childrenList,
),
],
),
),
appBar: new AppBar(
title: _scaffoldTitle,
elevation: 2.0,
actions: <Widget>[
],
),
body:_scaffoldBody,
);
}
Future <Null> getList() async {
await mainReference.child("NISE-Coimbatore").child("posts").once().then((DataSnapshot dataSnapshot) {
this.setState(() {
post_list.clear();
if(dataSnapshot.value!=null){
for (var value in dataSnapshot.value.values) {
post_list.add(new PostData.fromJson(value));
//debugPrint(value.toString());
}
}else{
this.setState((){
});
}
});
});
setState(() {
_scaffoldBody=new RefreshIndicator(child: _loadWall(), onRefresh: getList);
});
}
Widget _loadWall(){
return Stack(
children: <Widget>[
new ListView.builder(itemBuilder: (BuildContext context,int index){
return new Post(post_list[index].image,post_list[index].title,post_list[index].content);
},
itemCount: post_list == null ? 0 : post_list.length,)
],
);
}
_updateChildren() async {
_currentYear= await mainReference.child("attendance").child("currentYear").once();
await auth.currentUser().then((String userId) async{
mainReference.child("NISE-Coimbatore").child("parents").child(userId).child('children').once().then((DataSnapshot dataSnapshot){
for (var value in dataSnapshot.value){
this.setState((){
_childrenList.add(
new Padding(
padding: EdgeInsets.only(left: 25.0),
child: ListTile(
title: Text(value.toString()),
onTap: () {
super.setState(() {
_scaffoldTitle=new Text(value.toString());
this._scaffoldBody=new StudentPage(value.toString());
});
Navigator.pop(context);
},
),
),
);
});
//debugPrint("Childrrncount::"+value.toString());
}
});
});
}
}
class PostData{
String title;
String content;
String image;
PostData(this.title, this.content, this.image);
PostData.fromJson(var value) {
this.title = value['title'];
this.content = value['content'];
this.image = value['image'];
}
}
_childrenList has two elements. The datasnapshot.values has [15505,15501] two roll numbers
Both rollnumbers from firebase appear on the drawer box and on tap it is expected to show StudentPage(15501.tostring()) or StudentPage(15505.tostring())
it works as expected if select "Wall" from drawer and then any of the "rollNumbers"
it is not working if i switch from one of the rollNumbers to other rollNumber in the drawer.
Similar to my first post. Only the _scaffoldTitle changes accordingly.

Related

Flutter. Scan QR Code, redirect to Screen

I would like to create my own QR Code, Print it and whenever I want to scan it with my flutter app, it should redirect me to a screen of the app.
Is this possible?
import the qr_flutter package on pub.dev, this is the code to use below
import 'dart:developer';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:qr_code_scanner/qr_code_scanner.dart';
void main() => runApp(MaterialApp(home: MyHome()));
class MyHome extends StatelessWidget {
const MyHome({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Flutter Demo Home Page')),
body: Center(
child: ElevatedButton(
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => QRViewExample(),
));
},
child: Text('qrView'),
),
),
);
}
}
class QRViewExample extends StatefulWidget {
#override
State<StatefulWidget> createState() => _QRViewExampleState();
}
class _QRViewExampleState extends State<QRViewExample> {
Barcode? result;
QRViewController? controller;
final GlobalKey qrKey = GlobalKey(debugLabel: 'QR');
// In order to get hot reload to work we need to pause the camera if the platform
// is android, or resume the camera if the platform is iOS.
#override
void reassemble() {
super.reassemble();
if (Platform.isAndroid) {
controller!.pauseCamera();
}
controller!.resumeCamera();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: <Widget>[
Expanded(flex: 4, child: _buildQrView(context)),
Expanded(
flex: 1,
child: FittedBox(
fit: BoxFit.contain,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
if (result != null)
Text(
'Barcode Type: ${describeEnum(result!.format)} Data: ${result!.code}')
else
Text('Scan a code'),
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
margin: EdgeInsets.all(8),
child: ElevatedButton(
onPressed: () async {
await controller?.toggleFlash();
setState(() {});
},
child: FutureBuilder(
future: controller?.getFlashStatus(),
builder: (context, snapshot) {
return Text('Flash: ${snapshot.data}');
},
)),
),
Container(
margin: EdgeInsets.all(8),
child: ElevatedButton(
onPressed: () async {
await controller?.flipCamera();
setState(() {});
},
child: FutureBuilder(
future: controller?.getCameraInfo(),
builder: (context, snapshot) {
if (snapshot.data != null) {
return Text(
'Camera facing ${describeEnum(snapshot.data!)}');
} else {
return Text('loading');
}
},
)),
)
],
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
margin: EdgeInsets.all(8),
child: ElevatedButton(
onPressed: () async {
await controller?.pauseCamera();
},
child: Text('pause', style: TextStyle(fontSize: 20)),
),
),
Container(
margin: EdgeInsets.all(8),
child: ElevatedButton(
onPressed: () async {
await controller?.resumeCamera();
},
child: Text('resume', style: TextStyle(fontSize: 20)),
),
)
],
),
],
),
),
)
],
),
);
}
Widget _buildQrView(BuildContext context) {
// For this example we check how width or tall the device is and change the scanArea and overlay accordingly.
var scanArea = (MediaQuery.of(context).size.width < 400 ||
MediaQuery.of(context).size.height < 400)
? 150.0
: 300.0;
// To ensure the Scanner view is properly sizes after rotation
// we need to listen for Flutter SizeChanged notification and update controller
return QRView(
key: qrKey,
onQRViewCreated: _onQRViewCreated,
overlay: QrScannerOverlayShape(
borderColor: Colors.red,
borderRadius: 10,
borderLength: 30,
borderWidth: 10,
cutOutSize: scanArea),
onPermissionSet: (ctrl, p) => _onPermissionSet(context, ctrl, p),
);
}
void _onQRViewCreated(QRViewController controller) {
setState(() {
this.controller = controller;
});
controller.scannedDataStream.listen((scanData) {
setState(() {
result = scanData;
});
});
}
void _onPermissionSet(BuildContext context, QRViewController ctrl, bool p) {
log('${DateTime.now().toIso8601String()}_onPermissionSet $p');
if (!p) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('no Permission')),
);
}
}
#override
void dispose() {
controller?.dispose();
super.dispose();
}
}
Use the qr_flutter package on pub.dev.

How to pass down data from Stateful classes to another Stateful class that exists in another file?

I'm having trouble passing the data that's been filled in a textformfields and selected in a dropdown menu.
I'm trying to use the Map function to pass down String values so that I can also pass down all types of values in the future (ex. int, bool, double etc.), however it's not working so I need someone to check it out.
main.dart
import 'package:flutter/material.dart';
import 'package:workoutapp/auth/auth.dart';
import 'package:workoutapp/auth/root_page.dart';
import 'package:workoutapp/inheritedWigets/auth_provider.dart';
void main(List<String> args) {
runApp(
WorkoutManager(),
);
}
class WorkoutManager extends StatelessWidget {
#override
Widget build(BuildContext context) {
return AuthProvider(
auth: Auth(),
child: MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Workout Manager',
home: RootPage(),
theme: ThemeData(
primaryColor: Colors.indigo,
primarySwatch: Colors.indigo,
accentColor: Colors.indigoAccent,
hintColor: Colors.indigo,
brightness: Brightness.dark,
),
),
);
}
}
HomePage
import 'package:flutter/material.dart';
import 'package:workoutapp/inheritedWigets/auth_provider.dart';
import './profile_account_page.dart';
import './routines_create_page.dart';
import '../objects/Routines/routines_manager.dart';
import '../tools/custom_drawer.dart';
class HomePage extends StatelessWidget {
final VoidCallback onSignedOut;
final List<Map<String, String>> routines;
HomePage({Key key, this.onSignedOut, this.routines}) : super(key: key);
void _signedOut(BuildContext context) async {
try {
var auth = AuthProvider.of(context).auth;
await auth.signOut();
onSignedOut();
} catch (e) {
print(e);
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Workout Manager', style: TextStyle(color: Colors.white)),
centerTitle: false,
actions: <Widget>[
FlatButton(
child: Text('Logout'),
onPressed: () {
return _signedOut(context);
},
),
IconButton(
icon: Icon(Icons.account_box),
tooltip: 'Profile Account',
color: Colors.white,
onPressed: () {
return Navigator.push(context,
MaterialPageRoute(builder: (BuildContext context) {
return ProfileAccountPage();
}));
},
),
],
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
Navigator.push(context,
MaterialPageRoute(builder: (BuildContext context) {
return RoutinesPageCreate();
}));
},
),
body: RoutinesManager(),
drawer: CustomDrawer(),
);
}
}
RoutineManager
import 'package:flutter/material.dart';
import 'package:workoutapp/objects/routines/routines.dart';
class RoutinesManager extends StatefulWidget {
final Map<String, String> startingRoutine;
RoutinesManager({this.startingRoutine});
#override
_RoutinesManagerState createState() => _RoutinesManagerState();
}
class _RoutinesManagerState extends State<RoutinesManager> {
List<Map<String, String>> _routines = [];
#override
void initState() {
if (widget.startingRoutine != null) {
_routines.add(widget.startingRoutine);
}
super.initState();
}
#override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Expanded(
child: Routines(_routines),
)
],
);
}
}
RoutinesCreatePage
import 'package:flutter/material.dart';
import 'package:workoutapp/pages/home_page.dart';
class RoutinesPageCreate extends StatefulWidget {
#override
_RoutinesPageCreateState createState() => _RoutinesPageCreateState();
}
class _RoutinesPageCreateState extends State<RoutinesPageCreate> {
final formKey = GlobalKey<FormState>();
List<Map<String, String>> _routines = [];
String _routineName, _routineDescription;
var _routineNameController = TextEditingController();
var _routineDescriptionController = TextEditingController();
List<DropdownMenuItem<String>> _dropdownListBodyPartMenuItem = [];
List<String> _dropdownListBodyPart = [
'Chest',
'Back',
'Leg',
'Shoulder',
'Abs',
];
String _selectedBodyPart;
List<DropdownMenuItem<String>> _dropdownListDayOfWeekMenuItem = [];
List<String> _dropdownListDayOfWeek = [
'Monday',
'Tuesday',
'Wednesday',
'Thursday',
'Friday',
'Saturday',
'Sunday',
];
String _selectedDayOfWeek;
void loadBodyPartData() {
_dropdownListBodyPartMenuItem = [];
_dropdownListBodyPartMenuItem = _dropdownListBodyPart.map((val) {
return DropdownMenuItem<String>(
child: Text(val),
value: val,
);
}).toList();
}
void loadDayOfWeekData() {
_dropdownListDayOfWeekMenuItem = [];
_dropdownListDayOfWeekMenuItem = _dropdownListDayOfWeek.map((val) {
return DropdownMenuItem<String>(
child: Text(val),
value: val,
);
}).toList();
}
final _scaffoldState = GlobalKey<ScaffoldState>();
void _showSnakBarReset() {
_scaffoldState.currentState.showSnackBar(
SnackBar(
backgroundColor: Theme.of(context).accentColor,
content: Text('Showing SnackBar TEST'),
),
);
}
void _showSnakBarCreateWorkoutRoutine() {
_scaffoldState.currentState.showSnackBar(
SnackBar(
backgroundColor: Theme.of(context).accentColor,
content: Text('Workout Routine has been created'),
),
);
}
void _addRoutine(Map<String, String> routine) {
setState(() {
_routines.add(routine);
});
}
#override
Widget build(BuildContext context) {
loadBodyPartData();
loadDayOfWeekData();
return Scaffold(
key: _scaffoldState,
appBar: AppBar(
title: Text('Create Routines'),
),
body: Container(
padding: EdgeInsets.all(15.0),
child: Form(
key: formKey,
child: ListView(children: buildInputs() + buildCreateButtons()),
),
),
);
}
List<Widget> buildInputs() {
TextStyle textStyle = Theme.of(context).textTheme.title;
return [
TextFormField(
controller: _routineNameController,
validator: (value) {
if (value.length > 20) {
return 'Not a valid Routine Name';
}
},
onSaved: (value) {
return _routineName = value;
},
decoration: InputDecoration(
labelStyle: textStyle,
labelText: 'Routine Name',
hintText: 'Enter the Routine Name for this day',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5.0),
))),
Padding(padding: EdgeInsets.all(7.0)),
TextFormField(
controller: _routineDescriptionController,
validator: (value) {
if (value.length > 50) {
return 'Invalid: The Description must be 50 characters or less.';
}
},
onSaved: (value) {
return _routineDescription = value;
},
decoration: InputDecoration(
labelStyle: textStyle,
labelText: 'Description',
hintText: 'Enter the description of the Routine.',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5.0),
))),
Padding(padding: const EdgeInsets.all(7.0)),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
DropdownButtonHideUnderline(
child: DropdownButton(
value: _selectedBodyPart,
items: _dropdownListBodyPartMenuItem,
hint: Text('Select Body Part', style: textStyle),
onChanged: (value) {
setState(() {
_selectedBodyPart = value;
});
})),
Padding(
padding: const EdgeInsets.all(1.0),
),
DropdownButtonHideUnderline(
child: DropdownButton(
value: _selectedDayOfWeek,
items: _dropdownListDayOfWeekMenuItem,
hint: Text('Select Day of Week', style: textStyle),
onChanged: (value) {
setState(() {
_selectedDayOfWeek = value;
});
},
),
),
Padding(
padding: const EdgeInsets.all(4.0),
)
],
),
];
}
List<Widget> buildCreateButtons() {
return [
Padding(
padding: const EdgeInsets.all(5.0),
child: Row(
children: <Widget>[
Expanded(
child: RaisedButton(
textColor: Theme.of(context).primaryColorDark,
color: Theme.of(context).accentColor,
child: Text('Create Workout Routine'),
onPressed: () {
if (formKey.currentState.validate()) {
_showSnakBarCreateWorkoutRoutine();
formKey.currentState.save();
_addRoutine({
'routineName': 'Chest Workout',
'description': 'Heavy',
'bodyPart': 'Chest',
'week': 'Monday',
});
Navigator.push(context,
MaterialPageRoute(builder: (BuildContext context) {
return HomePage();
}));
} else {
return null;
}
}),
),
Expanded(
child: RaisedButton(
textColor: Theme.of(context).primaryColorLight,
color: Theme.of(context).primaryColorDark,
child: Text('Reset'),
onPressed: () {
setState(() {
_showSnakBarReset();
formKey.currentState.reset();
_selectedBodyPart = null;
_selectedDayOfWeek = null;
});
},
),
),
],
),
),
];
}
}
Routines
import 'package:flutter/material.dart';
import 'package:workoutapp/objects/routines/routines_detail.dart';
class Routines extends StatelessWidget {
final List<Map<String, String>> routines;
Routines(this.routines);
Widget _buildRoutinesItem(BuildContext context, int index) {
TextStyle textStyle = Theme.of(context).textTheme.title;
return Expanded(
child: Card(
margin: EdgeInsets.all(5.0),
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(5.0),
child: Text(routines[index]['routineName'], style: textStyle)),
Padding(
padding: const EdgeInsets.all(5.0),
child: Text(routines[index]['description'], style: textStyle)),
Padding(
padding: const EdgeInsets.all(5.0),
child: Text(routines[index]['bodyPart'], style: textStyle)),
Padding(
padding: const EdgeInsets.all(5.0),
child: Text(routines[index]['week'], style: textStyle)),
Padding(
padding: const EdgeInsets.all(5.0),
child: ButtonBar(
alignment: MainAxisAlignment.center,
children: <Widget>[
FlatButton(
child: Text('Details'),
onPressed: () {
return Navigator.push(context,
MaterialPageRoute(builder: (BuildContext context) {
return RoutinesDetail(
routines[index]['routineName'],
routines[index]['description'],
routines[index]['bodyPart'],
routines[index]['week']);
}));
},
)
],
),
)
],
),
),
);
}
Widget _buildRoutinesList(context) {
TextStyle textStyle = Theme.of(context).textTheme.title;
Widget routinesCards = Container(
child: Container(
child: Center(
child: Text("No routines found, please add some.", style: textStyle),
),
),
);
if (routines.length > 0 || routines.length <= 7) {
ListView.builder(
itemBuilder: _buildRoutinesItem,
itemCount: routines.length,
);
}
return routinesCards;
}
#override
Widget build(BuildContext context) {
return _buildRoutinesList(context);
}
}
RoutineDetailPage
import 'package:flutter/material.dart';
class RoutinesDetail extends StatelessWidget {
final String routineName, description, bodyPart, week;
RoutinesDetail(this.routineName, this.description, this.bodyPart, this.week);
#override
Widget build(BuildContext context) {
TextStyle textStyle = Theme.of(context).textTheme.title;
return Scaffold(
appBar: AppBar(
title: Text(routineName),
centerTitle: true,
),
body: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(5.0),
child: Text(routineName, style: textStyle)),
Padding(
padding: const EdgeInsets.all(5.0),
child: Text(description, style: textStyle)),
Padding(
padding: const EdgeInsets.all(5.0),
child: Text(bodyPart, style: textStyle)),
Padding(
padding: const EdgeInsets.all(5.0),
child: Text(week, style: textStyle)),
Container(
padding: EdgeInsets.all(5.0),
child: RaisedButton(
child: Text('Delete'),
onPressed: () {
Navigator.pop(context);
},
),
),
],
),
),
);
}
}
As you can see, I'm trying to separate the code into multiple files as much as possible, so it's more "readable" and make it easy for myself to make changes to the code whenever I have to in the future.
The problem is, it's quite spit up, I don't understand how to use the data and pass it down or up to the pages or widgets as there are multiple stateful and stateless widgets that are suppose to work together to make this app possible.
You'll notice on the HomePage file (StatelessWidget), I'm trying to show the Scaffold body argument with the RoutinesManager StatefulWidget, which is in a different file. At the same time in the HomePage file, I have a Scaffold floatingActionButton argument that will take you to the RoutinesCreatePage StatefulWidget to create a List of Cards (StatelessWidget) using the ListView.builder(). However, no Card gets created under the HomePage after the "Create Workout Routine" RaisedButton gets pressed in the RoutinesCreatePage and no data gets passed.
Can someone please help me out here as I am totally clueless. Also, I'm fairly a beginner regarding flutter/dart so a solution with a relatively easy to understand explanation would be very helpful.
Note: I do have other files that contribute to this app, however I don't think they're part of the problem so I left them out intentionally.
If more information is needed, please do let me know.
Thanks you!
it looks like you misunderstand what state in Flutter is. To explain in short, state is the internal status/data/... that belongs that that specific widget. StatefulWidget has state to determine if UI should be re-rendered on its own state change. External widgets never know about other widgets' states.
So it means, any state change happening inside RoutinesCreatePage widget, only that RoutinesCreatePage knows and reacts. Unless, you inform other widgets to know something has changed.
Alright, so talking about navigation, it works like a stack structure. HomePage trigger a push to RoutinesCreatePage, then to return, you need to pop, not another push.
Here a quick fix for your code, you can try.
HomePage
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
handleNewRoutine(); <--- this is to handle navigation and retrieve returning data from pop
},
),
Future handleNewRoutine() async {
var newRoutine = await Navigator.push(
context,
MaterialPageRoute(builder: (context) => RoutinesPageCreate());
)
if (newRoutine == null) {
// nothing returns from RoutinesPageCreate widget
// so do nothing then
} else {
// add to routine list
// and trigger list re-rendering
setState(() {
this.routines.add(newRoutine);
});
}
}
RoutinesCreatePage: when clicking submit button, just populate all data from input fields, make object model and pop to return data to where this widget was pushed.
onPressed: () {
var newRoutine = .... // populate from UI to create new Routine model object.
Navigator.pop(context, newRoutine);
}
Also, take time to read the navigation guide from official Flutter documentation. It is very detailed on this part. https://flutter.io/docs/cookbook/navigation/returning-data
Some additional comments to your code:
in RoutinesCreatePage you don't need to know application level state, I mean _routines variable is unnecessary. You only need one object to store new routine to pop back to HomePage.
in Routines, this method Widget _buildRoutinesList(context) having unused ListView creation.
if (routines.length > 0 || routines.length <= 7) {
ListView.builder(
itemBuilder: _buildRoutinesItem,
itemCount: routines.length,
);
}

Destruct and Construct cards in Flutter dynamically

I'm new to Flutter,
I want to destruct cards created initially and construct them again as per data provided in API call.
Basically when I tap on button in UI, it should call APIs and based on data from API call, if it is different from the data I already have, I want to destruct cards and construct them again.
How I can achieve this?
The cards will auto update their content when you make the call again, it is like refreshing your data.
I have made a simple example with a single card that shows data from this JSON Where I am calling the API first time in initState and then repeating the call each time I press on the FAB.
I am adding the index variable just to show you the updates (updating my single card with the next item in the list)
Also it is worth noting that I am handling the null or empty values poorly for the sake of time.
Also forget about the UI overflow ¯_(ツ)_/¯
class CardListExample extends StatefulWidget {
#override
_CardListExampleState createState() => new _CardListExampleState();
}
class _CardListExampleState extends State<CardListExample> {
Map cardList = {};
int index = 0;
#override
void initState() {
_getRequests();
super.initState();
}
_getRequests() async {
String url = "https://jsonplaceholder.typicode.com/users";
var httpClinet = createHttpClient();
var response = await httpClinet.get(
url,
);
var data = JSON.decode(response.body);
//print (data);
setState(() {
this.cardList = data[index];
this.index++;
});
print(cardList);
print(cardList["name"]);
}
#override
Widget build(BuildContext context) {
return new Scaffold(
floatingActionButton:
new FloatingActionButton(onPressed: () => _getRequests()),
appBar: new AppBar(
title: new Text("Card List Example"),
),
body: this.cardList != {}
? new ListView(children: <Widget>[
new Card(
child: new Column(
children: <Widget>[
new Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
new Text(
cardList["name"] ?? '',
style: Theme.of(context).textTheme.display1,
),
new Text(
this.cardList['email'] ?? '',
maxLines: 50,
),
],
),
new Text(cardList["website"] ?? '')
],
),
),
])
: new Center(child: new CircularProgressIndicator()),
);
}
}
Yes, Answer from Aziza works.
Though I used the code as below :
void main() =>
runApp(new MaterialApp(
onGenerateRoute: (RouteSettings settings) {
switch (settings.name) {
case '/about':
return new FromRightToLeft(
builder: (_) => new _aboutPage.About(),
settings: settings,
);
}
},
home : new HomePage(),
theme: new ThemeData(
fontFamily: 'Poppins',
primarySwatch: Colors.blue,
),
));
class HomePage extends StatefulWidget{
#override
HomePageState createState() => new HomePageState();
}
class HomePageState extends State<HomePage>{
List data;
Future<String> getData() async{
var response = await http.get(
Uri.encodeFull(<SOMEURL>),
headers: {
"Accept" : "application/json"
}
);
this.setState((){
data = JSON.decode(response.body);
});
return "Success";
}
#override
void initState() {
// TODO: implement initState
super.initState();
this.getData();
}
#override
Widget build(BuildContext context){
return new Scaffold(
appBar : new AppBar(
title : new Text("ABC API"),
actions: <Widget>[
new IconButton( // action button
icon: new Icon(Icons.cached),
onPressed: () => getData(),
)],
),
drawer: new Drawer(
child: new ListView(
children: <Widget> [
new Container(
height: 120.0,
child: new DrawerHeader(
padding: new EdgeInsets.all(0.0),
decoration: new BoxDecoration(
color: new Color(0xFFECEFF1),
),
child: new Center(
child: new FlutterLogo(
colors: Colors.blueGrey,
size: 54.0,
),
),
),
),
new ListTile(
leading: new Icon(Icons.chat),
title: new Text('Support'),
onTap: () {
Navigator.pop(context);
Navigator.of(context).pushNamed('/support');
}
),
new ListTile(
leading: new Icon(Icons.info),
title: new Text('About'),
onTap: () {
Navigator.pop(context);
Navigator.of(context).pushNamed('/about');
}
),
new Divider(),
new ListTile(
leading: new Icon(Icons.exit_to_app),
title: new Text('Sign Out'),
onTap: () {
Navigator.pop(context);
}
),
],
)
),
body: this.data != null ?
new ListView.builder(
itemCount: data.length,
itemBuilder: (BuildContext context, int index){
return new Container(
padding: new EdgeInsets.fromLTRB(8.0,5.0,8.0,0.0),
child: new Card(
child: new Padding(
padding: new EdgeInsets.fromLTRB(10.0,12.0,8.0,0.0),
child: new Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
new ListTile(
enabled: data[index]['active'] == '1' ? true : false,
title: new Text(data[index]['header'],
style:Theme.of(context).textTheme.headline,
),
subtitle: new Text("\n" + data[index]['description']),
),
new ButtonTheme.bar(
child: new ButtonBar(
children: <Widget>[
new FlatButton(
child: new Text(data[index]['action1']),
onPressed: data[index]['active'] == '1' ? _launchURL :null,
),
],
),
),
],
),
),
),
);
},
)
:new Center(child: new CircularProgressIndicator()),
);
}
}
_launchURL() async {
const url = 'http://archive.org';
if (await canLaunch(url)) {
await launch(url);
} else {
throw 'Could not launch $url';
}
}
class FromRightToLeft<T> extends MaterialPageRoute<T> {
FromRightToLeft({ WidgetBuilder builder, RouteSettings settings })
: super(builder: builder, settings: settings);
#override
Widget buildTransitions(
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child) {
if (settings.isInitialRoute)
return child;
return new SlideTransition(
child: new Container(
decoration: new BoxDecoration(
boxShadow: [
new BoxShadow(
color: Colors.black26,
blurRadius: 25.0,
)
]
),
child: child,
),
position: new Tween(
begin: const Offset(1.0, 0.0),
end: const Offset(0.0, 0.0),
)
.animate(
new CurvedAnimation(
parent: animation,
curve: Curves.fastOutSlowIn,
)
),
);
}
#override Duration get transitionDuration => const Duration(milliseconds: 400);
}
The above code includes Navigation drawer, page navigation animation and also answer to the above question.

How to read data from Flutter elements

I've the below code for entering some data, I do not know how to handle it!
i.e. What shall I write at the onPressed for the IconButton so that the data is read from all the elements (name, birthday, ...)? and how to display it in Dialog to check if read correctly?
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.deepOrange,
),
home: new MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
var _value=false;
double _bodyHeight=0.0;
void onchange(bool value) {
setState(() {
_value = value;
this._bodyHeight = (value == true) ? 400.0 : 0.0;
});
}
#override
Widget build(BuildContext context) {
return new Scaffold(
backgroundColor: Colors.grey[500],
appBar: new AppBar(
title: new Text(widget.title),
),
body: new SingleChildScrollView(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Card(
child: new Container(
height: 50.0,
child: new Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
new Text("Select me pls"),
new Switch(value: _value, onChanged: (bool value) => onchange(value)),
],
),
),
),
new Card(
child: new AnimatedContainer(
child: new ListView(
children: <Widget>[
new ListTile(
leading: const Icon(Icons.person),
title: new TextField(
decoration: new InputDecoration(
hintText: "Name",
),
),
),
new ListTile(
leading: const Icon(Icons.phone),
title: new TextField(
decoration: new InputDecoration(
hintText: "Phone",
),
),
),
new ListTile(
leading: const Icon(Icons.email),
title: new TextField(
decoration: new InputDecoration(
hintText: "Email",
),
),
),
const Divider(
height: 1.0,
),
new ListTile(
leading: const Icon(Icons.label),
title: const Text('Nick'),
subtitle: const Text('None'),
),
new ListTile(
leading: const Icon(Icons.today),
title: const Text('Birthday'),
subtitle: const Text('February 20, 1980'),
),
new IconButton(icon: const Icon(Icons.save),
onPressed: null
/*
*
* What shall I write here to read the data in the elements
*
*
*
* */
),
],
),
curve: Curves.easeInOut,
duration: const Duration(milliseconds: 500),
height: _bodyHeight,
// color: Colors.red,
),
),
],
),
),
);
}
}
One way is that TextFields take a property called TextEditingController which allow you to access the value of the TextField.
And to show a dialog you can just call showDialog() function.
class TextFieldExample extends StatefulWidget {
#override
_TextFieldExampleState createState() => new _TextFieldExampleState();
}
class _TextFieldExampleState extends State<TextFieldExample> {
TextEditingController c1;
TextEditingController c2;
#override
void initState() {
c1 = new TextEditingController();
c2 = new TextEditingController();
super.initState();
}
#override
Widget build(BuildContext context) {
return new Scaffold(
body: new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new TextField (
controller: c1,
),
new TextField(
controller: c2,
),
new OutlineButton(onPressed: () {
showDialog(child: new AlertDialog(
content: new Text("You entered ${c1.text} ${c2.text} ")
),
context: context
);
},
child: new Text("Show Dialog"),
)
],
),
),
);
}
}

Check if an application is on its first run with Flutter

Basically, I want to have a screen/view that will open when the user opens up the app for the first time. This will be a login screen type of thing.
Use Shared Preferences Package. You can read it with FutureBuilder, and you can check if there is a bool named welcome for example. This is the implementation I have in my code:
return new FutureBuilder<SharedPreferences>(
future: SharedPreferences.getInstance(),
builder:
(BuildContext context, AsyncSnapshot<SharedPreferences> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
case ConnectionState.waiting:
return new LoadingScreen();
default:
if (!snapshot.hasError) {
#ToDo("Return a welcome screen")
return snapshot.data.getBool("welcome") != null
? new MainView()
: new LoadingScreen();
} else {
return new ErrorScreen(error: snapshot.error);
}
}
},
);
Above code work fine but for beginners I make it little bit simple
main.dart
import 'package:flutter/material.dart';
import 'package:healthtic/IntroScreen.dart';
import 'package:healthtic/user_preferences.dart';
import 'login.dart';
import 'profile.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
#override
State<StatefulWidget> createState() {
// TODO: implement createState
return MyAppState();
}
}
class MyAppState extends State<MyApp> {
// This widget is the root of your application.
bool isLoggedIn = false;
MyAppState() {
MySharedPreferences.instance
.getBooleanValue("isfirstRun")
.then((value) => setState(() {
isLoggedIn = value;
}));
}
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
//if true return intro screen for first time Else go to login Screen
home: isLoggedIn ? Login() : IntroScreen());
}
}
then share preferences
MySharedPreferences
import 'package:shared_preferences/shared_preferences.dart';
class MySharedPreferences {
MySharedPreferences._privateConstructor();
static final MySharedPreferences instance =
MySharedPreferences._privateConstructor();
setBooleanValue(String key, bool value) async {
SharedPreferences myPrefs = await SharedPreferences.getInstance();
myPrefs.setBool(key, value);
}
Future<bool> getBooleanValue(String key) async {
SharedPreferences myPrefs = await SharedPreferences.getInstance();
return myPrefs.getBool(key) ?? false;
}
}
then create two dart files IntroScreen and Login
Intro Screen will apear just once when user run application for first time usless the app is removed or caches are cleard
IntroScreen
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:healthtic/SliderModel.dart';
import 'package:healthtic/login.dart';
import 'package:healthtic/user_preferences.dart';
import 'package:shared_preferences/shared_preferences.dart';
class IntroScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: "Healthtic",
home: IntorHome(),
debugShowCheckedModeBanner: false,
);
}
}
class IntorHome extends StatefulWidget {
#override
_IntorHomeState createState() => _IntorHomeState();
}
class _IntorHomeState extends State<IntorHome> {
List<SliderModel> slides=new List<SliderModel>();
int currentIndex=0;
PageController pageController=new PageController(initialPage: 0);
#override
void initState() {
// TODO: implement initState
super.initState();
slides=getSlides();
}
Widget pageIndexIndicator(bool isCurrentPage) {
return Container(
margin: EdgeInsets.symmetric(horizontal: 2.0),
height: isCurrentPage ? 10.0 : 6.0,
width: isCurrentPage ? 10.0 :6.0,
decoration: BoxDecoration(
color: isCurrentPage ? Colors.grey : Colors.grey[300],
borderRadius: BorderRadius.circular(12)
),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: PageView.builder(
controller: pageController,
onPageChanged: (val){
setState(() {
currentIndex=val;
});
},
itemCount: slides.length,
itemBuilder: (context,index){
return SliderTile(
ImageAssetPath: slides[index].getImageAssetPath(),
title: slides[index].getTile(),
desc: slides[index].getDesc(),
);
}),
bottomSheet: currentIndex != slides.length-1 ? Container(
height: Platform.isIOS ? 70:60,
padding: EdgeInsets.symmetric(horizontal: 20),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
GestureDetector(
onTap: (){
pageController.animateToPage(slides.length-1, duration: Duration(
microseconds: 400,
), curve: Curves.linear);
},
child: Text("Skip")
),
Row(
children: <Widget>[
for(int i=0;i<slides.length;i++) currentIndex == i ?pageIndexIndicator(true): pageIndexIndicator(false)
],
),
GestureDetector(
onTap: (){
pageController.animateToPage(currentIndex+1, duration: Duration(
microseconds: 400
), curve: Curves.linear);
},
child: Text("Next")
),
],
),
) : Container(
alignment: Alignment.center,
width: MediaQuery.of(context).size.width,
height: Platform.isIOS ? 70:60,
color: Colors.blue,
child:
RaisedButton(
child: Text("Get Started Now",style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w300
),
),
onPressed: (){
MySharedPreferences.instance
.setBooleanValue("isfirstRun", true);
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (_) => Login()),
);
},
),
),
);
}
}
class SliderTile extends StatelessWidget {
String ImageAssetPath, title, desc;
SliderTile({this.ImageAssetPath, this.title, this.desc});
#override
Widget build(BuildContext context) {
return Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Image.asset(ImageAssetPath),
SizedBox(height: 20,),
Text(title),
SizedBox(height: 12,),
Text(desc),
],
)
,
);
}
}
final step Login
import 'package:flutter/material.dart';
import 'package:healthtic/user_preferences.dart';
import 'profile.dart';
class Login extends StatefulWidget {
#override
State<StatefulWidget> createState() {
// TODO: implement createState
return LoginState();
}
}
class LoginState extends State<Login> {
TextEditingController controllerEmail = new TextEditingController();
TextEditingController controllerUserName = new TextEditingController();
TextEditingController controllerPassword = new TextEditingController();
#override
Widget build(BuildContext context) {
final formKey = GlobalKey<FormState>();
// TODO: implement build
return SafeArea(
child: Scaffold(
body: SingleChildScrollView(
child: Container(
margin: EdgeInsets.all(25),
child: Form(
key: formKey,
autovalidate: false,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Text("Email Id:", style: TextStyle(fontSize: 18)),
SizedBox(width: 20),
Expanded(
child: TextFormField(
controller: controllerEmail,
decoration: InputDecoration(
hintText: "Please enter email",
),
keyboardType: TextInputType.emailAddress,
validator: (value) {
if (value.trim().isEmpty) {
return "Email Id is Required";
}
},
),
)
],
),
SizedBox(height: 60),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Text("UserName:", style: TextStyle(fontSize: 18)),
SizedBox(width: 20),
Expanded(
child: TextFormField(
decoration: InputDecoration(
hintText: "Please enter username",
),
validator: (value) {
if (value.trim().isEmpty) {
return "UserName is Required";
}
},
controller: controllerUserName),
)
],
),
SizedBox(height: 60),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Text("Password:", style: TextStyle(fontSize: 18)),
SizedBox(width: 20),
Expanded(
child: TextFormField(
decoration: InputDecoration(
hintText: "Please enter password",
),
obscureText: true,
validator: (value) {
if (value.trim().isEmpty) {
return "Password is Required";
}
},
controller: controllerPassword),
)
],
),
SizedBox(height: 100),
SizedBox(
width: 150,
height: 50,
child: RaisedButton(
color: Colors.grey,
child: Text("Submit",
style: TextStyle(color: Colors.white, fontSize: 18)),
onPressed: () {
if(formKey.currentState.validate()) {
var getEmail = controllerEmail.text;
var getUserName = controllerUserName.text;
var getPassword = controllerPassword.text;
MySharedPreferences.instance
.setBooleanValue("loggedin", true);
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (_) => Profile()),
);
}
},
),
)
],
),
),
),
)),
);
}
}
Can be possible with this pakage : https://pub.dev/packages/is_first_run
Usage :
bool firstRun = await IsFirstRun.isFirstRun();

Resources