Toggle icon in IconButton - flutter

I am trying to toggle the IconButton icon when pressed on it. This is what I have so far:
class _AppsScreenState extends State<AppsScreen> {
late Future<AllApps> activateApps;
#override
void initState() {
super.initState();
activateApps = getActivatedApps();
}
#override
Widget build(BuildContext context) {
IconData iconData = Icons.grid_view;
void _toggleViewIcon() {
setState(() {
if (iconData == Icons.grid_view) {
iconData = Icons.list;
} else {
iconData = Icons.grid_view;
}
});
}
return Scaffold(
appBar: AppBar(
title: const Text('Apps'),
primary: false,
toolbarHeight: 50,
leading: IconButton(
tooltip: 'Toggle view',
icon: Icon(iconData),
onPressed: _toggleViewIcon,
),
actions: <Widget>[
Padding(
padding: const EdgeInsets.only(right: 20.0),
child: IconButton(
tooltip: 'Refresh',
icon: const Icon(Icons.refresh),
onPressed: () {
setState(() {
activateApps = getActivatedApps();
});
},
)),
Padding(
padding: const EdgeInsets.only(right: 20.0),
child: IconButton(
tooltip: 'Add or remove apps',
icon: const Icon(Icons.add),
onPressed: () {
setState(() {
activateApps = getActivatedApps();
});
},
)),
],
),
primary: false,
body: Column(children: []));
}
}
The button never toggles. I am not sure what I am doing wrong here. Any help is appreciated.

setState will rebuild the widget, i.e the build function will be called again, thus the iconData variable will be set again to Icons.grid_view
move the iconData declaration and the function _toggleViewIcon outside of the build function

iconData variable will be set again to Icons.grid_view each time when you call set state if it put inside build method, so declare it outside build method
class _AppsScreenState extends State<AppsScreen> {
late Future<AllApps> activateApps;
IconData iconData = Icons.grid_view;
#override
void initState() {
super.initState();
activateApps = getActivatedApps();
}
#override
Widget build(BuildContext context) {
void _toggleViewIcon() {
setState(() {
if (iconData == Icons.grid_view) {
iconData = Icons.list;
} else {
iconData = Icons.grid_view;
}
});
}
return Scaffold(
appBar: AppBar(
title: const Text('Apps'),
primary: false,
toolbarHeight: 50,
leading: IconButton(
tooltip: 'Toggle view',
icon: Icon(iconData),
onPressed: _toggleViewIcon,
),
actions: <Widget>[
Padding(
padding: const EdgeInsets.only(right: 20.0),
child: IconButton(
tooltip: 'Refresh',
icon: const Icon(Icons.refresh),
onPressed: () {
setState(() {
activateApps = getActivatedApps();
});
},
)),
Padding(
padding: const EdgeInsets.only(right: 20.0),
child: IconButton(
tooltip: 'Add or remove apps',
icon: const Icon(Icons.add),
onPressed: () {
setState(() {
activateApps = getActivatedApps();
});
},
)),
],
),
primary: false,
body: Column(children: []));
}
}

You can use SteamBuilder instead, if you want to change a bit of space, but it will rebuild all widgets

Related

How to edit a name on screen2 and make the new name appear on screen1?

I started studying Flutter these days and I made the app of this tutorial smoothly.
I managed to create a button that switch from list and card visualization, an icon that removes a word and instead of showing infinite words now shows only 20 words. But now I wanted to create another screen via named routes and on this screen you can edit the name you clicked on screen1, for example:
But I'm having a lot of trouble trying to do this. I managed to create the screen2, the textform and the routes but the part of changing the name is still giving me little headaches xD
Could someone help me please? This is the code:
import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Startup Names',
initialRoute: '/',
routes: {
'/': (context) => const RandomWords(),
EditScreen.routeName: (context) => EditScreen(),
},
);
}
}
class RandomWords extends StatefulWidget {
const RandomWords({super.key});
#override
State<RandomWords> createState() => _RandomWordsState();
}
class _RandomWordsState extends State<RandomWords> {
final _suggestions = <WordPair>[];
final _saved = <WordPair>{};
final _biggerFont = const TextStyle(fontSize: 20);
String selected = '';
bool isList = true;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Startup Names'),
actions: [
IconButton(
icon: const Icon(Icons.bookmark_border_sharp),
onPressed: _pushSaved,
tooltip: 'Favorites',
),
IconButton(
icon:
isList ? const Icon(Icons.grid_view) : const Icon(Icons.list),
onPressed: () {
setState(() {
isList = !isList;
});
},
tooltip: isList ? 'Card mode' : 'List mode',
),
],
),
body: isList ? lista() : cards());
}
Widget lista() {
return ListView.builder(
padding: const EdgeInsets.all(16.0),
itemCount: 40,
itemBuilder: (context, i) {
if (i.isOdd) return const Divider();
final index = i ~/ 2;
if (index >= _suggestions.length) {
_suggestions.addAll(generateWordPairs().take(10));
}
return favorites(_suggestions[index], index);
},
);
}
Widget cards() {
return GridView.builder(
padding: const EdgeInsets.all(16.0),
itemCount: 20,
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 5,
mainAxisSpacing: 5,
mainAxisExtent: 100),
itemBuilder: (context, i) {
if (i >= _suggestions.length) {
_suggestions.addAll(generateWordPairs().take(10));
}
return Card(child: favorites(_suggestions[i], i));
});
}
Widget favorites(WordPair pair, int index) {
final alreadySaved = _saved.contains(pair);
return ListTile(
title: Text(
pair.asPascalCase,
style: _biggerFont,
),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
IconButton(
icon: Icon(alreadySaved ? Icons.favorite : Icons.favorite_border),
color: alreadySaved ? Colors.red : null,
tooltip: alreadySaved ? 'Remove favorite' : 'Favorite',
onPressed: () {
setState(() {
if (alreadySaved) {
_saved.remove(pair);
} else {
_saved.add(pair);
}
});
},
),
IconButton(
icon: const Icon(Icons.delete),
color: Colors.black87,
tooltip: 'Remove from list',
onPressed: () {
setState(() {
_suggestions.remove(pair);
_saved.remove(pair);
});
},
),
],
),
onTap: () {
selected = pair.asPascalCase;
Navigator.pushNamed(context, '/second',
arguments: Argumentos(index, selected));
});
}
void _pushSaved() {
Navigator.of(context).push(
MaterialPageRoute<void>(
builder: (context) {
final tiles = _saved.map(
(pair) {
return ListTile(
title: Text(
pair.asPascalCase,
style: _biggerFont,
),
);
},
);
final divided = tiles.isNotEmpty
? ListTile.divideTiles(
context: context,
tiles: tiles,
).toList()
: <Widget>[];
return Scaffold(
appBar: AppBar(
title: const Text('Favorites'),
),
body: ListView(children: divided),
);
},
),
);
}
}
class EditScreen extends StatefulWidget {
static const routeName = '/second';
const EditScreen({super.key});
#override
State<EditScreen> createState() => _EditScreenState();
}
class _EditScreenState extends State<EditScreen> {
final first = TextEditingController();
final second = TextEditingController();
#override
Widget build(BuildContext context) {
final argumentos = ModalRoute.of(context)?.settings.arguments as Argumentos;
String selected = argumentos.name;
return Scaffold(
appBar: AppBar(
title: Text('Edit word'),
),
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Text("What's the new name?",
style: TextStyle(fontSize: 30)),
const SizedBox(height: 30),
Padding(
padding:
const EdgeInsets.symmetric(horizontal: 100, vertical: 16),
child: TextFormField(
controller: first,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'First part of the name',
),
),
),
Padding(
padding:
const EdgeInsets.symmetric(horizontal: 100, vertical: 16),
child: TextFormField(
controller: second,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Second part of the name',
),
),
),
const SizedBox(height: 20),
ElevatedButton(
child: const Text('Change it'),
onPressed: () {
selected = (WordPair(first.text, second.text)).toString();
Navigator.pushNamed(context, '/');
},
),
],
),
));
}
}
class Argumentos {
final int id;
final String name;
Argumentos(this.id, this.name);
}
You can use .then() and update value.
Exp :
Navigator.pushNamed(context, '/second',
arguments: Argumentos(index, selected)).then((value) {
setState(() { // update ui
// update value here;
});});
then() : https://api.flutter.dev/flutter/dart-async/Future/then.html

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!

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;
},
),
),
));
}

Display different fab depending on active View of TabBarView

If PageA is selected, fabA should be displayed. If PageB is selected, fabB respectively.
Whats the best way to achieve this?
var fabA = FloatingActionButton();
var fabB = FloatingActionButton();
...
Scaffold(
body: TabBarView(children: [
PageA(),
PageB(),
]),
floatingActionButton: fabA,
)
You can copy paste run full code below
You can declare a List<FloatingActionButton> and return based on tabController.index
code snippet
_tabController = TabController(vsync: this, length: choices.length)
..addListener(() {
if (_tabController.indexIsChanging) {
print(
"tab is animating. from active (getting the index) to inactive(getting the index) ");
} else {
setState(() {});
...
floatingActionButton: floatButton[_tabController.index],
...
List<FloatingActionButton> floatButton = [
FloatingActionButton(
onPressed: () {
// Add your onPressed code here!
},
child: Icon(Icons.navigation),
backgroundColor: Colors.green,
),
FloatingActionButton(
onPressed: () {
// Add your onPressed code here!
},
child: Icon(Icons.share),
backgroundColor: Colors.green,
),
working demo
full code
import 'package:flutter/material.dart';
class AppBarBottomSample extends StatefulWidget {
#override
_AppBarBottomSampleState createState() => _AppBarBottomSampleState();
}
class _AppBarBottomSampleState extends State<AppBarBottomSample>
with SingleTickerProviderStateMixin {
TabController _tabController;
#override
void initState() {
super.initState();
_tabController = TabController(vsync: this, length: choices.length)
..addListener(() {
if (_tabController.indexIsChanging) {
print(
"tab is animating. from active (getting the index) to inactive(getting the index) ");
} else {
//tab is finished animating you get the current index
//here you can get your index or run some method once.
print(_tabController.index);
setState(() {});
}
});
}
#override
void dispose() {
_tabController.dispose();
super.dispose();
}
void _nextPage(int delta) {
final int newIndex = _tabController.index + delta;
if (newIndex < 0 || newIndex >= _tabController.length) return;
_tabController.animateTo(newIndex);
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('AppBar Bottom Widget'),
leading: IconButton(
tooltip: 'Previous choice',
icon: const Icon(Icons.arrow_back),
onPressed: () {
_nextPage(-1);
},
),
actions: <Widget>[
IconButton(
icon: const Icon(Icons.arrow_forward),
tooltip: 'Next choice',
onPressed: () {
_nextPage(1);
},
),
],
bottom: PreferredSize(
preferredSize: const Size.fromHeight(48.0),
child: Theme(
data: Theme.of(context).copyWith(accentColor: Colors.white),
child: Container(
height: 48.0,
alignment: Alignment.center,
child: TabPageSelector(controller: _tabController),
),
),
),
),
body: TabBarView(
controller: _tabController,
children: choices.map((Choice choice) {
return Padding(
padding: const EdgeInsets.all(16.0),
child: ChoiceCard(choice: choice),
);
}).toList(),
),
floatingActionButton: floatButton[_tabController.index],
),
);
}
}
List<FloatingActionButton> floatButton = [
FloatingActionButton(
onPressed: () {
// Add your onPressed code here!
},
child: Icon(Icons.navigation),
backgroundColor: Colors.green,
),
FloatingActionButton(
onPressed: () {
// Add your onPressed code here!
},
child: Icon(Icons.share),
backgroundColor: Colors.green,
),
FloatingActionButton(
onPressed: () {
// Add your onPressed code here!
},
child: Icon(Icons.create),
backgroundColor: Colors.green,
),
FloatingActionButton(
onPressed: () {
// Add your onPressed code here!
},
child: Icon(Icons.repeat),
backgroundColor: Colors.green,
),
FloatingActionButton(
onPressed: () {
// Add your onPressed code here!
},
child: Icon(Icons.forward),
backgroundColor: Colors.green,
),
FloatingActionButton(
onPressed: () {
// Add your onPressed code here!
},
child: Icon(Icons.link),
backgroundColor: Colors.green,
)
];
class Choice {
const Choice({this.title, this.icon});
final String title;
final IconData icon;
}
const List<Choice> choices = const <Choice>[
const Choice(title: 'CAR', icon: Icons.directions_car),
const Choice(title: 'BICYCLE', icon: Icons.directions_bike),
const Choice(title: 'BOAT', icon: Icons.directions_boat),
const Choice(title: 'BUS', icon: Icons.directions_bus),
const Choice(title: 'TRAIN', icon: Icons.directions_railway),
const Choice(title: 'WALK', icon: Icons.directions_walk),
];
class ChoiceCard extends StatelessWidget {
const ChoiceCard({Key key, this.choice}) : super(key: key);
final Choice choice;
#override
Widget build(BuildContext context) {
final TextStyle textStyle = Theme.of(context).textTheme.display1;
return Card(
color: Colors.white,
child: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Icon(choice.icon, size: 128.0, color: textStyle.color),
Text(choice.title, style: textStyle),
],
),
),
);
}
}
void main() {
runApp(AppBarBottomSample());
}