CircularProgressIndicator not stopping while moving back - flutter

Created a demo for understanding future..
I have taken two screen....Using Future.delayed I am forwarding to next screen in 5 seconds with CircularProgressIndicator...but when I move to back..it still showing CircularProgressbar...
What should I correct my code?
here is my code
class _MyHomePageState extends State<MyHomePage> {
#override
void initState() {
// TODO: implement initState
super.initState();
}
bool isloading = false;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Async demo'),
),
body: isloading == true
? Center(child: CircularProgressIndicator())
: Center(
child: TextButton(
child: Text('Pressed'),
onPressed: () {
setState(() {
isloading = true;
});
Future.delayed(Duration(seconds: 5), () {
Navigator.of(context)
.push(MaterialPageRoute(builder: (context) {
return NextScreen();
}));
isloading = false;
});
},
),
),
);
}
}

What should I correct my code?
Wrap the second assignment of isloading to false inside setState (just as you did when setting to true). Something like the following:
onPressed: () {
setState(() {
isloading = true;
});
Future.delayed(Duration(seconds: 5), () {
Navigator.of(context).push(MaterialPageRoute(builder: (context) {
return NextScreen();
}));
setState(() {
isloading = false;
});
});
},

you need to use setState when you are assign variable = false
For that do as below
replace this
isloading = false;
with
setState(() {
isloading = false;
});

Related

Flutter, getting value from showTimePicker not working

I am trying to displayed time selected from showTimePicker dialogue but after getting the value it becomes null again.
after debugging, it seems like the value returned from future function expried or something.
after the widgets onPress function it is back to null.
ElevatedButton(
child: const Text('Time'),
onPressed: () async {
vTimeSelected = await getTimeSelected(context);
setState(() {
// vStrToRndr = vTimeSelected.toString();
//print(vStrToRndr);
});
},
),
ElevatedButton(
child: const Text('Solid'),
onPressed: () {
setState(() {
vDetail.solid = !vDetail.solid;
});
},
),
],
),
),
if (vDetail.wet == true) Text('Nappy wet'),
if (vDetail.solid == true) Text('Nappy Solid'),
Text('Time: $vTimeSelected'),
[7:35 PM]
Future<TimeOfDay?> getTimeSelected(BuildContext context) async {
TimeOfDay vTime = TimeOfDay(hour: 0, minute: 0);
TimeOfDay? newTime =
await showTimePicker(context: context, initialTime: vTime);
return newTime;
//print($newTime);
}
//thanks for any help
Text('Time: $vTimeSelected') //<---- this is displaying null
You can follow this code structure. Make sure to declare variable outside the build method.
class TS extends StatefulWidget {
const TS({super.key});
#override
State<TS> createState() => _TSState();
}
class _TSState extends State<TS> {
TimeOfDay? vTimeSelected;
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(onPressed: () async {
vTimeSelected = await getTimeSelected(context);
setState(() {});
}),
body: Text("${vTimeSelected}"),
);
}
}

how to Enable button if "All textfield" is not empty flutter

my app has two textformfield. I want to enable button if all textfield are not empty.
In the internet, there are a way to enable button if "one" textfield are not empty.
I try to make isFilledTitle true if title of textfield is not empty. and isFilledContent true if content of textfield is not empty. and then if they are all true, isButtonActive is true. but it doesn't work.
late TextEditingController _titleEditingController;
late TextEditingController _contentEditingController;
bool isButtonActive = true;
bool isFilledContent = false;
bool isFilledTitle = false;
#override
void initState() {
super.initState();
_titleEditingController = TextEditingController();
_contentEditingController = TextEditingController();
_titleEditingController.addListener(() {
final isFilledTitle = _titleEditingController.text.isNotEmpty;
setState(() {
this.isFilledTitle = isFilledTitle;
});
});
_contentEditingController.addListener(() {
final isFilledContent = _contentEditingController.text.isNotEmpty;
setState(() {
this.isFilledContent = isFilledContent;
});
});
if(isFilledContent && isFilledTitle){
setState(() {
isButtonActive = true;
});
} else {
setState(() {
isButtonActive = false;
});
}
}
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
FocusScope.of(context).unfocus();
},
child: Container(
child: SafeArea(
child: Scaffold(
appBar: AppBarWriteContainer(
onButtonPressed: isButtonActive
? (widget.postNo != null)
? () => revisePost()
: () => newPost()
: null,
),
Yeah your answer is correct but the user needs validation on two text field so i will modify the answer like
class _TempDialogState extends State<TempDialog> {
final TextEditingController _inputController = TextEditingController();
final TextEditingController _inputController2 = TextEditingController();
bool enable = false;
#override
void initState() {
super.initState();
}
#override
void dispose() {
_inputController.dispose();
_inputController2.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: Center(
child: Column(children: [
TextField(
controller: _inputController,
onChanged: (data) {
if (_inputController.text.isEmpty ||
_inputController2.text.isEmpty) {
enable = false;
} else {
enable = true;
}
setState(() {});
},
),
TextField(
controller: _inputController2,
onChanged: (data) {
if (_inputController.text.isEmpty ||
_inputController2.text.isEmpty) {
enable = false;
} else {
enable = true;
}
setState(() {});
},
),
ElevatedButton(
onPressed: enable ? () {} : null,
child: Text('${enable}'),
)
])),
),
);
}
}
You don't need any additional libraries to do that. Flutter has it out-of-the-box and you can make sure you're not going to rebuild the whole tree on each keystroke.
TextEditingController extends ValueNotifier<TextEditingValue> which means you can utilize ValueListenableBuilder from material package to listen to text changes.
class MyWidget extends StatelessWidget {
final TextEditingController _inputController = TextEditingController();
#override
void dispose() {
_inputController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Column(children: [
TextField(controller: _inputController),
ValueListenableBuilder<TextEditingValue>(
valueListenable: _inputController,
builder: (context, value, child) {
return ElevatedButton(
onPressed: value.text.isNotEmpty ? () {} : null,
child: Text('I am disabled when text is empty'),
);
},
),
]);
}
}
You only set the isButtonActive in the initState. Try updating it in the controller listeners. Maybe something like:
#override
void initState() {
super.initState();
_titleEditingController = TextEditingController();
_contentEditingController = TextEditingController();
_titleEditingController.addListener(() {
final isFilledTitle = _titleEditingController.text.isNotEmpty;
setState(() {
this.isFilledTitle = isFilledTitle;
updateIsButtonActive();
});
});
_contentEditingController.addListener(() {
final isFilledContent = _contentEditingController.text.isNotEmpty;
setState(() {
this.isFilledContent = isFilledContent;
updateIsButtonActive();
});
});
}
void updateIsButtonActive() {
if(isFilledContent && isFilledTitle){
isButtonActive = true;
} else {
isButtonActive = false;
}
}

how to add loader when on the toggle button

I want to display a circular loader when user is going to on the toggle button, then after few secs toggle button will active.
here is my code
InkWell(
onTap: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => ProductProfile(),
));
},
child: Container(
decoration: BoxDecoration(
color: _selectedProducts.contains(book.id) ? Colors.grey[200] :Colors.white,
borderRadius: BorderRadius.all(
Radius.circular(10),
),
),
child: ListTile(
dense: true,
trailing: Switch(
value: _selectedProducts.contains(book.id),
onChanged: (bool? selected) {
if (selected != null) {
setState(() {
_onProductSelected(selected, book.id);
});
}
},
activeTrackColor: HexColor("#b8c2cc"),
activeColor: HexColor("#7367f0"),
),
title: Text(
book.title,),
Divider()
),
),
),
SizedBox10(),
],
);
please help how to do this
To achieve that, you need bool _isLoading and a timer. Steps I would do:
Declare _isLoading: bool _isLoading = false;
Change _isLoading value using a timer:
void timer() {
int _time = 10;
Timer timer = new Timer.periodic(
Duration(seconds: 1),
(Timer timer) async {
if (_time == 0) {
_isLoading = true;
timer.cancel();
} else {
setState(() {
_time--;
});
}
},
);
}
Use _isLoading on your build method (for example):
#override
Widget build(BuildContext context) {
return _isLoading ? CircularProgressIndicator() : Container();
}
Or to hide your button:
#override
Widget build(BuildContext context) {
return _isLoading ? Container() : YourToggleButton;
}
Also remember to dispose your timer!
#override
void dispose() {
timer.cancel();
}
So, If you are on Flutter web, there is a widget called MouseRegion which has onHover, onEnter & onExit.
You can assign a new bool for instance bool showLoader=false which you will toggle to true with setState (inside the onHover, where you could also start the Timer and when finished reset the showLoader to false).
Now you can show your button with a ternary operator : showLoader ? CircularProgressIndicator() : YourButton()

Loading progress indicator is not displaing while making async call

I try to use https://pub.dev/packages/loading_overlay to display a simple loading overlay while making an async call in form.
class AccountFormState extends State<AccountForm> {
bool _loading = false;
override
Widget build(BuildContext context) {
return LoadingOverlay(
child: Form(
...
),
isLoading: _loading,
);
where in the form there is a
ElevatedButton(
onPressed: () async {
if (_formKey.currentState.validate()) {
bool loginResult = await webService.testLoginSite(); // an async call
print('loginResult = $loginResult');
if (loginResult == true) {
Scaffold.of(context)
.showSnackBar(SnackBar(content: Text('successfull')));
}
}
},
child: Text('Check login'),
),
The problem is that the LoadingOverlay does not show overlay loading indicatow while making an async call in the ElevatedButton.
Why does it not work?
You need to setState _isLoading before and after webService.testLoginSite()
ElevatedButton(
onPressed: () async {
if (_formKey.currentState.validate()) {
setState(() {
_isLoading = true;
});
bool loginResult = await webService.testLoginSite(); // an async call
print('loginResult = $loginResult');
setState(() {
_isLoading = false;
});
if (loginResult == true) {
Scaffold.of(context)
.showSnackBar(SnackBar(content: Text('successfull')));
}
}
},
child: Text('Check login'),
),

How to show loading screen after click on url in webview using Flutter?

I am trying to show loading screen when i click on webpage in webview using flutter. loading screen is showing after splash screen. But it's not showing after click on link of in webview.
class _HomeState extends State<Home> {
bool isLoading;
#override
void initState() {
isLoading = true;
}
#override
Widget build(BuildContext context) {
return Scaffold(
body:Stack(
children: <Widget>[
new WebView(
initialUrl:"https://abcdef.com/",
javascriptMode:JavascriptMode.unrestricted,
onPageFinished: (_) {
setState(() {
isLoading = false;
});
},
),
isLoading ? Center( child: CircularProgressIndicator()) : Container(),
],
),
);
}
}
Add onPageStarted callback to your Webview, then set isLoading to true
Like this
Webview(
initialUrl:"https://abcdef.com/",
javascriptMode:JavascriptMode.unrestricted,
onPageStarted: (_){
setState(() => isLoading = true);
},
onPageFinished: (_) {
setState(() {
isLoading = false;
});
},
}