Refactoring Dart Code into a separate file - flutter

I have this code where I have the sidebar (drawer) in my app. I have created a separate file drawer.dart which looks somewhat like this :
import 'package:flutter/material.dart';
class DrawerClass extends StatefulWidget {
#override
_DrawerClassState createState() => _DrawerClassState();
}
class _DrawerClassState extends State<DrawerClass> {
#override
Widget build(BuildContext context) {
return Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: [
DrawerHeader(
child: CircleAvatar(
backgroundColor: Theme.of(context).primaryColor,
radius: 30,
child: Icon(
Icons.pets,
size: 60,
color: Colors.white,
),
),
),
ListTile(
leading: Icon(Icons.home),
title: Text("Home"),
onTap: () {
Navigator.pushReplacementNamed(context, "/home");
},
),
ListTile(
leading: Icon(
Icons.report,
),
title: Text("Report"),
onTap: () {
Navigator.pushReplacementNamed(context, "/report");
},
),
ListTile(
leading: Icon(
Icons.settings,
),
title: Text("Settings"),
onTap: () {
Navigator.pop(context);
},
),
],
),
);
}
}
Now I have three different files: home.dart , report.dart, settings.dart. This refactored code will work perfectly when used in settings.dart but not in other two files. Example, if I use this in report.dart I'll have to change it's onTap status to Navigator.pop. I need to use drawer.dart in all the other 3 files changing only the onTap status in every file.
Any help will be appreciated:)

One way to do this is like so.
enum ScreenName {
Home,
Report,
Settings,
}
Use this enum as a property (parentScreen) of DrawerClass so it knows which screen it is in.
class DrawerClass extends StatefulWidget {
final ScreenName parentScreen;
const DrawerClass({#required this.parentScreen});
#override
_DrawerClassState createState() => _DrawerClassState();
}
class _DrawerClassState extends State<DrawerClass> {
#override
Widget build(BuildContext context) {
return Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: [
// other children,
ListTile(
leading: Icon(Icons.home),
title: Text("Home"),
onTap: () {
if (widget.parentScreen == ScreenName.Home)
Navigator.pop(context);
else
Navigator.pushReplacementNamed(context, "/home");
},
),
ListTile(
leading: Icon(Icons.report),
title: Text("Report"),
onTap: () {
if (widget.parentScreen == ScreenName.Report)
Navigator.pop(context);
else
Navigator.pushReplacementNamed(context, "/report");
},
),
ListTile(
leading: Icon(Icons.settings),
title: Text("Settings"),
onTap: () {
if (widget.parentScreen == ScreenName.Settings)
Navigator.pop(context);
else
Navigator.pushReplacementNamed(context, "/settings");
},
),
],
),
);
}
}
Then use DrawerClass like so. For example, for setting screen -
DrawerClass(parentScreen: ScreenName.Settings)

Related

How to keep drawer always open

I want to put a drawer like this in my Flutter app:
just like https://m3.material.io/develop/flutter
I'm using NavigationRail and it's said that a menu button can be added to open a navigation drawer. Does any knows how to add the menu button and the drawer?
menu button of NavigationRail
thanks.
It's a bit hard to use a regular Scaffold Drawer without the regular scaffold controls, as far as I can tell.
I came up with a solution for your problem, if I understood it correctly. Looks a lot like the spec site, needs a bit of styling.
Took the example from the NavigationRail documentation and added a Visibility widget. Now clicking on the destinations, you can show and hide their child widgets(drawer). No drawer animation though.
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
colorSchemeSeed: const Color(0xff6750a4), useMaterial3: true),
home: const NavRailExample(),
);
}
}
class NavRailExample extends StatefulWidget {
const NavRailExample({super.key});
#override
State<NavRailExample> createState() => _NavRailExampleState();
}
class _NavRailExampleState extends State<NavRailExample> {
int _selectedIndex = 0;
NavigationRailLabelType labelType = NavigationRailLabelType.all;
bool showLeading = false;
bool showTrailing = false;
double groupAligment = -1.0;
bool _isClosed = false;
Widget _getWidget(int index) {
switch (index) {
case 1:
return GestureDetector(
child: const Text('Tap!'),
onTap: () => setState(() {
_isClosed = true;
}),
);
case 2:
return const Text('empty');
default:
return ListView(
children: const [
ExpansionTile(
title: Text('whatev'),
children: [Text('1'), Text('2')],
),
ListTile(
title: Text('adfafdafaf'),
)
],
);
}
}
Widget _getPage(int index) {
switch (index) {
case 1:
return const Center(child: Text('sheeesh'));
case 2:
return const Center(child: Text('empty'));
default:
return const Center(child: Text('yolo'),);
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Row(
children: <Widget>[
NavigationRail(
selectedIndex: _selectedIndex,
groupAlignment: groupAligment,
onDestinationSelected: (int index) {
setState(() {
_isClosed = (_selectedIndex == index || _isClosed)
? !_isClosed
: _isClosed;
_selectedIndex = index;
});
},
labelType: labelType,
leading: showLeading
? FloatingActionButton(
elevation: 0,
onPressed: () {
// Add your onPressed code here!
},
child: const Icon(Icons.add),
)
: const SizedBox(),
trailing: showTrailing
? IconButton(
onPressed: () {
// Add your onPressed code here!
},
icon: const Icon(Icons.more_horiz_rounded),
)
: const SizedBox(),
destinations: const <NavigationRailDestination>[
NavigationRailDestination(
icon: Icon(Icons.favorite_border),
selectedIcon: Icon(Icons.favorite),
label: Text('First'),
),
NavigationRailDestination(
icon: Icon(Icons.bookmark_border),
selectedIcon: Icon(Icons.book),
label: Text('Second'),
),
NavigationRailDestination(
icon: Icon(Icons.star_border),
selectedIcon: Icon(Icons.star),
label: Text('Third'),
),
],
),
Visibility(
maintainState: false,
visible: !_isClosed,
child: Row(
children: [
const VerticalDivider(thickness: 1, width: 1),
SizedBox(
height: double.infinity,
width: 200,
child: _getWidget(_selectedIndex),
)
],
),
),
const VerticalDivider(thickness: 1, width: 1),
// This is the main content.
Expanded(
child: _getPage(_selectedIndex),
),
],
),
),
);
}
}

IconButton selectedIcon not toggling

The play button should toggle to a pause button when I press it. It is currently not doing that. I'm changing the state of the task isRecording attribute and it's printing to show that it is changing each time I press the button, but the selectedIcon is not showing. It's just showing the original icon.
class TestScreen extends StatefulWidget {
const TestScreen({super.key});
#override
State<TestScreen> createState() => _TestScreenState();
}
class _TestScreenState extends State<TestScreen> {
Task task = Task(name: 'Test Task', order: 0, isRecording: false);
#override
Widget build(BuildContext context) {
print(task.isRecording);
return Scaffold(
appBar: AppBar(
title: const Text('Test Screen'),
),
body: Center(
child: IconButton(
icon: const Icon(Icons.play_arrow),
isSelected: task.isRecording,
selectedIcon: const Icon(Icons.pause),
onPressed: () {
setState(() {
task.isRecording = !task.isRecording;
});
},
),
),
);
}
}
The selectedIcon feature is only available for Material3.
This property is only used if [ThemeData.useMaterial3] is true.
Solution:
Wrap the IconButton in a Theme and set inside the data the useMaterial3 to true.
return Scaffold(
appBar: AppBar(
title: const Text("Test Screen"),
),
body: Center(
child: Theme(
data: ThemeData(useMaterial3: true),
child: IconButton(
icon: Icon(Icons.play_arrow),
isSelected: !task.isRecording,
selectedIcon: Icon(Icons.pause),
onPressed: () {
setState(() {
task.isRecording = !task.isRecording;
});
},
),
),
),
);
Your IconButton should look like this
IconButton(
icon: task.isRecording ? Icon(Icons.play_arrow) : Icon(Icons.pause),
isSelected: task.isRecording,
selectedIcon: const Icon(Icons.pause),
onPressed: () {
setState(() {
task.isRecording = !task.isRecording;
});
},
),
The catch is that you have to change the icon every time you are setting the state.
Hope this helps!

How would I navigate to a new route inside a list widget? (Line 41: context,) is where the issue occurs

import 'dart:js';
import 'package:google_fonts/google_fonts.dart';
import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';
void main() => runApp(const MyApp());
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(),
);
}
}
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({Key? key}) : super(key: key);
#override
State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
int _selectedIndex = 0;
static const TextStyle optionStyle =
TextStyle(fontSize: 30, fontWeight: FontWeight.bold);
// ignore: prefer_final_fields
static List<Widget> _widgetOptions = <Widget>[
Container(
child: ElevatedButton(
child: const Text('Open route'),
onPressed: () {
Navigator.push(
**This is where the error occurs: I am unsure of how to access or use context within list widgets**
context, // ********THIS IS WHERE THE ERROR IS******
MaterialPageRoute(builder: (context) => const SecondRoute()),
);
},
),
),
Text(
'Index 1: Business',
style: optionStyle,
),
Text(
'Index 2: School',
style: optionStyle,
),
];
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('OBTAIN'),
),
body: Center(
child: _widgetOptions.elementAt(_selectedIndex),
),
drawer: Drawer(
// Add a ListView to the drawer. This ensures the user can scroll
// through the options in the drawer if there isn't enough vertical
// space to fit everything.
child: ListView(
// Important: Remove any padding from the ListView.
padding: EdgeInsets.zero,
children: [
const DrawerHeader(
decoration: BoxDecoration(
color: Colors.blue,
),
child: Text('Drawer Header'),
),
ListTile(
title: const Text('Item 1'),
onTap: () {
// Update the state of the app
// ...
// Then close the drawer
Navigator.pop(context);
},
),
ListTile(
title: const Text('Item 2'),
onTap: () {
// Update the state of the app
// ...
// Then close the drawer
Navigator.pop(context);
},
),
],
),
),
bottomNavigationBar: BottomNavigationBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Home',
),
BottomNavigationBarItem(
icon: Icon(Icons.business),
label: 'Business',
),
BottomNavigationBarItem(
icon: Icon(Icons.school),
label: 'School',
),
],
currentIndex: _selectedIndex,
selectedItemColor: Colors.amber[800],
onTap: _onItemTapped,
),
);
}
}
class SecondRoute extends StatelessWidget {
const SecondRoute({super.key});
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Second Route'),
),
body: Center(
child: ElevatedButton(
onPressed: () {
Navigator.pop(context);
},
child: const Text('Go back!'),
),
),
);
}
}
How would I navigate to a new route inside a list widget? (Line 41: context,) is where the issue occurs.
The issue is you are trying to get context direct under state class. There is trick can be done using late keyword or do inside initState. (You can't use static)
Also avoid using context like this when ever possible.
"It breaks the context chain, which means you're violating the build system's contract." - And this variable wont be responde to update untill you reintalize this variable inisde setState.
late List<Widget> _widgetOptions = <Widget>[
Container(
child: ElevatedButton(
child: const Text('Open route'),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const SecondRoute()),
);
},
),
),
Text(
'Index 1: Business',
style: optionStyle,
),
Text(
'Index 2: School',
style: optionStyle,
),
];

SetState not updating listview

Im trying to make it so when you press search it creates a listtile. It works but for it to work I have to click the button and then rebuild the app for it to appear. I was looking at some other posts but I could not find anything that worked. The main parts to look at is I have a function that adds a listtile. I have a button with an on press to create the tile. And I have the children of container at the bottom as the list of created listtiles.
class Home extends StatefulWidget {
const Home({Key? key}) : super(key: key);
#override
State<Home> createState() => _HomeState();
}
class _HomeState extends State<Home> {
List<Widget> _listOfWidgets = [];
#override
Widget build(BuildContext context) {
_addItemToList() {
List<Widget> tempList =
_listOfWidgets; // defining a new temporary list which will be equal to our other list
tempList.add(ListTile(
key: UniqueKey(),
leading: Icon(Icons.list),
trailing: FlatButton(
onPressed: () async {},
//Download Link
child: Text(
"Download",
style: TextStyle(color: Colors.green, fontSize: 15),
),
),
title: Text("")));
this.setState(() {
_listOfWidgets =
tempList; // this will trigger a rebuild of the ENTIRE widget, therefore adding our new item to the list!
});
}
return MaterialApp(
theme: ThemeData.light(),
darkTheme: ThemeData.dark(),
themeMode: currentTheme.currentTheme(),
home: Scaffold(
appBar: AppBar(
actions: [
IconButton(
onPressed: () {
setState(() {
currentTheme.switchTheme();
});
},
icon: Icon(Icons.wb_sunny),
),
IconButton(
onPressed: () async {
await FirebaseAuth.instance.signOut();
},
icon: Icon(Icons.exit_to_app),
),
],
backgroundColor: Colors.blue,
title: Text("Home"),
),
body: ListView(
children: [
ListTile(
leading: SizedBox(
width: 300,
child: TextField(
controller: search,
decoration: InputDecoration(
labelText: "Enter Manga Name",
),
),
),
trailing: ElevatedButton(
onPressed: () async {
_addItemToList();
},
child: Text("Search")),
),
Container(
margin: EdgeInsets.all(15),
width: 100,
height: 515,
color: Colors.black12,
child: ListView(
children: _listOfWidgets,
))
],
)));
}
}
try add below code
if you update status you need setState()
A better way to state management is to use a BLoC or Provider package.
...
onPressed: () {
setState(() {
_addItemToList();
});
},
...
Figured it out after a bit of tinkering. Fix for me was to add key: UniqueKey(), to my ListView. I had keys added to my ListTiles instead of the actual ListView.
onPressed: () {
setState(() {
_addItemToList();
});
},
The Problem Solution is :
List<Widget> tempList = <Widget>[];
_addItemToList() {
tempList.addAll(
_listOfWidgets); // defining a new temporary list which will be equal to our other list
tempList.add(ListTile(
key: UniqueKey(),
leading: Icon(Icons.list),
trailing: FlatButton(
onPressed: () async {},
//Download Link
child: Text(
"Download",
style: TextStyle(color: Colors.green, fontSize: 15),
),
),
title: Text("")));
this.setState(() {
_listOfWidgets =
tempList; // this will trigger a rebuild of the ENTIRE widget, therefore adding our new item to the list!
});
}

Getting Error while Home widget (MyHomepage) loading

I am getting The following error while Run my app default page (Homepage) .
════════ Exception caught by widgets library ═══════════
The following ArgumentError was thrown building MyHomePage(dirty, dependencies: [MediaQuery, _EffectiveTickerMode], state: _MyHomePageState#7da5f(ticker inactive)):
Invalid argument(s)
**The Tracker showing the following reasons:**
The relevant error-causing widget was:
MyHomePage file:///F:/Orangebd/app/GoogleDriveClone-Flutter/lib/Screen/Home.dart:37:15
When the exception was thrown, this was the stack:
#0 _StringBase.+ (dart:core-patch/string_patch.dart:272:57)
#1 _MyHomePageState.build (package:googledriveclone_flutter/Screen/Home.dart:133:45)
#2 StatefulElement.build (package:flutter/src/widgets/framework.dart:4716:27)
#3 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4599:15)
#4 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4772:11)
...
══════════════════════════════════════════
During that error, the screen appears something like that
Here is my Home page code
import 'package:fab_circular_menu/fab_circular_menu.dart';
//import 'package:file_picker/file_picker.dart';
import 'package:floating_action_bubble/floating_action_bubble.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'package:googledriveclone_flutter/Screen/Files.dart';
import 'package:googledriveclone_flutter/Screen/HomeScreen.dart';
import 'package:googledriveclone_flutter/Screen/LoginPage.dart';
import 'package:googledriveclone_flutter/Screen/Profile.dart';
import 'package:googledriveclone_flutter/Widget/constants.dart';
import 'package:prompt_dialog/prompt_dialog.dart';
import 'package:sk_alert_dialog/sk_alert_dialog.dart';
import 'package:storage_capacity/storage_capacity.dart';
import 'IssudFile.dart';
void main() {
runApp(HomePage());
}
class HomePage extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
try {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Digilocker',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Digilocker'),
);
}
catch(e){
print('Loading expception of page'+e.toString());
}
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin {
Widget _widgetBody = HomeScreen();
int _currrentIndex = 0;
Animation<double> _animation;
AnimationController _animationController;
TextEditingController _foldername = TextEditingController();
String _fileName;
var scaffoldKey = GlobalKey<ScaffoldState>();
bool isFolder;
double _diskSpace = 0;
var _freespace ;
var _freespacemb;
var _occupiedSpace ;
var _totalSpace;
#override
void initState() {
// TODO: implement initState
// _controller.addListener(() => _extension = _controller.text);
_getStorgeInfo();
_animationController = AnimationController(
vsync: this,
duration: Duration(milliseconds: 300),
);
final curvedAnimation = CurvedAnimation(curve: Curves.easeInOut, parent: _animationController);
_animation = Tween<double>(begin: 0, end: 1).animate(curvedAnimation);
// initDiskSpace();
super.initState();
}
#override
void dispose() {
_animationController.dispose();
super.dispose();
}
void _onItemTapped(int index) async{
setState(() {
if(index == 0){
_currrentIndex = index;
_widgetBody = HomeScreen();
}
else if(index == 1){
_currrentIndex = index;
_widgetBody = MyIssuedDocScreen();
}
else if(index == 2){
_currrentIndex = index;
_widgetBody = Center(child: Text('Shared documents'),);
}
else if(index == 3){
_currrentIndex = index;
_widgetBody = MyDriveScreen();
}
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
key: scaffoldKey,
endDrawerEnableOpenDragGesture: false, // This way it will not open
// endDrawer: Drawer(),
drawer: new Drawer(
elevation: 10,
child: new ListView(
padding: EdgeInsets.all(0),
children: <Widget>[
DrawerHeader(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Image.asset('assets/digi_locker.png', width: MediaQuery.of(context).size.width*0.30,),
SizedBox(height: 10,),
Text('Available space: '+_freespace+'\t (MB)'),
]
),
decoration: BoxDecoration(
color: kPrimaryLightColor,
),
),
ListTile(
leading: Icon(Icons.person),
title: Text('My profile'),
onTap: () {
// Get.back();
Get.to(profilePage());
},
),
Divider(),
ListTile(
leading: Icon(Icons.create_new_folder),
title: Text('Create folder'),
onTap: () {
// Get.back();
_showMyDialog();
},
),
ListTile(
leading: Icon(Icons.cloud_upload_rounded),
title: Text('File upload'),
onTap: () {
// Get.back();
},
),
ListTile(
leading: Icon(Icons.six_ft_apart_outlined),
title: Text('Issued documents'),
onTap: () {
// Get.back();
},
),
Divider(),
ListTile(
leading: Icon(Icons.translate_rounded),
title: Text('Change lagnuage'),
onTap: () {
// Get.back();
//Get.offAll(LoginPage());
//Do some stuff here
//Closing programmatically - very less practical use
scaffoldKey.currentState.openEndDrawer();
},
),
ListTile(
leading: Icon(Icons.logout),
title: Text('Logout'),
onTap: () {
// Get.back();
Get.offAll(LoginPage());
//Do some stuff here
//Closing programmatically - very less practical use
scaffoldKey.currentState.openEndDrawer();
},
)
],
),
),
appBar: AppBar(
elevation: 0,
backgroundColor: Colors.white,
brightness: Theme.of(context).brightness,
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children:
[
Expanded(
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(35)),
color: Colors.grey.shade50,
),
child: TextFormField(
decoration: InputDecoration(
hintText: "Search in locker",
border: InputBorder.none,
icon: Container(
margin: EdgeInsets.only(left: 10),
child: Icon(Icons.search, color: kPrimaryColor,)
),
),
),
),
),
]
),
iconTheme: IconThemeData(color: kPrimaryColor),
actions: <Widget>[
IconButton(
onPressed: (){
print("Sync started");
showSnackMessage(context,"Sync Started please wait...", scaffoldKey,'');
},
icon: Icon(
Icons.sync,
color:kPrimaryColor,
),
),
IconButton(
icon: Container(
height: 50,
width: 50,
margin: EdgeInsets.all(5),
child: CircleAvatar(
radius: 14.0,
backgroundColor: Colors.white,
child: CircleAvatar(
radius: 14.0,
backgroundColor: Colors.grey[200],
backgroundImage: NetworkImage("https://qph.fs.quoracdn.net/main-qimg-11ef692748351829b4629683eff21100.webp"),
),
),
),
onPressed: () {
// do something
},
)
],
),
body: SafeArea(
child: Container(
padding: EdgeInsets.all(15.0),
child: _widgetBody
),
),
floatingActionButtonLocation: FloatingActionButtonLocation.endFloat,
//Init Floating Action Bubble
floatingActionButton: FloatingActionBubble(
// Menu items
items: <Bubble>[
// Floating action menu item
Bubble(
title:"Upload",
iconColor :kPrimaryColor,
bubbleColor : Colors.white.withOpacity(0.9),
titleStyle:TextStyle(fontSize: 16 , color: kPrimaryColor),
icon:Icons.cloud_upload,
onPress: () {
// OpenFilePicker();
_animationController.reverse();
_openFileType(context);
},
),
// Floating action menu item
Bubble(
title:"Folder",
icon:Icons.create_new_folder,
iconColor :kPrimaryColor,
bubbleColor : Colors.white.withOpacity(0.9),
titleStyle:TextStyle(fontSize: 16 , color: kPrimaryColor),
onPress: () {
_animationController.reverse();
print('creating folder');
_showMyDialog();
},
),
//Floating action menu item
],
// animation controller
animation: _animation,
// On pressed change animation state
onPress: _animationController.isCompleted
? _animationController.reverse
: _animationController.forward,
// Floating Action button Icon color
iconColor: kPrimaryColor,
// Flaoting Action button Icon
icon: AnimatedIcons.menu_close,
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: _currrentIndex,
type: BottomNavigationBarType.fixed,
showSelectedLabels: true,
showUnselectedLabels: true,
selectedItemColor: kPrimaryColor,
onTap: _onItemTapped,
items: [
BottomNavigationBarItem(
icon: _currrentIndex==0?Icon(Icons.home,size: 25,):Icon(Icons.home_outlined,size: 25),
title: Text("Home")
),
BottomNavigationBarItem(
icon: _currrentIndex==1?Icon(Icons.file_download_done,size: 25,):Icon(Icons.file_download_done_outlined,size: 25),
title: Text("Issued")
),
BottomNavigationBarItem(
icon: _currrentIndex==2?Icon(Icons.supervised_user_circle,size: 25,):Icon(Icons.supervised_user_circle,size: 25),
title: Text("Shared")
),
BottomNavigationBarItem(
icon: _currrentIndex==3?Icon(Icons.folder,size: 25,):Icon(Icons.folder_open,size: 25),
title: Text("My locker")
),
],
), );
}
Future<void> _showMyDialog() async {
return showDialog<void>(
context: context,
barrierDismissible: false, // user must tap button!
builder: (BuildContext context) {
return AlertDialog(
backgroundColor: Colors.white,
elevation: 13,
title: Text('Create folder'),
content: TextField(
onChanged: (value) { },
controller: _foldername,
decoration: InputDecoration(hintText: "your folder/directory name",
suffixIcon: IconButton(
onPressed: () => _foldername.clear(),
icon: Icon(Icons.clear),
),
),
),
actions: <Widget>[
TextButton(
child: Text('Cancel', style: TextStyle(color: Colors.red),),
onPressed: () {
//Navigator.pop(_);
Navigator.of(context).pop();
// _animationController.reverse();
},
),
TextButton(
child: Text('Create', style: TextStyle(color: kPrimaryColor),),
onPressed: () {
createFolder(context, scaffoldKey, _foldername.text.toString()) ;
Get.back();
//Navigator.of(context).pop();
// _animationController.reverse();
},
),
],
);
},
);
}
void _openFileType(BuildContext context) {
SKAlertDialog.show(
context: context,
type: SKAlertType.radiobutton,
radioButtonAry: {'Certificate': 1, 'Signature': 2, 'NID': 3, 'Passport': 4, 'Driving licence': 5},
title: 'Choose File category',
onCancelBtnTap: (value) {
print('Cancel Button Tapped');
Navigator.of(context).pop(false);
},
onRadioButtonSelection: (value) {
print('onRadioButtonSelection $value');
},
);
}
/* Future<void> initDiskSpace() async {
double diskSpace = 0;
diskSpace = await DiskSpace.getFreeDiskSpace;
if (!mounted) return;
setState(() {
_diskSpace = diskSpace;
});
}
*/
Future<void> _getStorgeInfo() async{
_freespace = await StorageCapacity.getFreeSpace;
//_freespacemb = await StorageCapacity.toMegaBytes(double.parse(_freespace.toString()));
_occupiedSpace = await StorageCapacity.getOccupiedSpace;
_totalSpace = await StorageCapacity.getTotalSpace;
}
}
NOTE: if I Hot Reload this page, it's working okay again
Please help.
the problem is, you are getting your data in the initState method, but your widget's build is being completed before initializing the data to _freespace, and that's why the error is appearing.
as a solution, I suggest removing _getStorgeInfo() call from initState, and implementing the following structure:
#override
Widget build(BuildContext context) {
return Scaffold(
key: scaffoldKey,
endDrawerEnableOpenDragGesture: false, // This way it will not open
// endDrawer: Drawer(),
drawer: new Drawer(
...
),
appBar: AppBar(
...
),
body: SafeArea(
child: Container(
padding: EdgeInsets.all(15.0),
child: FutureBuilder(
future: _getStorgeInfo(),
builder: (context, snapshot) {
if(snapshot.connectionState!=ConnectionState.Done) return CircularProgressIndicator();
return _widgetBody;
},
),
),
));
}