How to set state using button click in flutter? - flutter

I have a boolean isUserLoggedIn = false; in my main.dart file and when isUserLoggedIn = false i am loading
Widget build(BuildContext context) {
return Scaffold(
body: isUserLoggedIn == false ? IntroAuthScreen() : HomePage(),
);
This is working fine. IntroAuthScreen is loading. But there is a button in IntroAuthScreen i want the value of isUserLoggedIn to be true when user click the button and he will be redirected to HomePage() as above code show.
IntroAuthCode:-
child: ElevatedButton.icon(
icon: Icon(
Icons.navigate_next,
color: Colors.white,
),
onPressed: () {
setState(() {
username = usernameController.text;
isUserLoggedIn = true;
});
print(username);
Navigator.pop(context);
},
label: Text("Finish"),
),
but its not working. help me

What if you try to create a wrapper class rather than switching the content of the scaffold?
Perhaps something like this:
class AuthWrapper extends StatelessWidget {
#override
Widget build(BuildContext context) {
final _user = Provider.of<User>(context);
return (_user == null) ? IntroAuthScreen() : HomeScreen();
}
}
The answer does make use of Provider, but it's definitely a worthwhile package to consider learning.

Check Below code.
Widget build(BuildContext context) {
return Scaffold(
body: isUserLoggedIn == false ? IntroAuthScreen() : HomePage(),
);
IntroAuthScreen() async {
bool isLoggedIN = await Navigator.push(MaterialPageRoute Bla Bla);
setState((){
isUserLoggedIn = isLoggedIN ?? false;
});
}
}
In Auth Code
child: ElevatedButton.icon(
icon: Icon(
Icons.navigate_next,
color: Colors.white,
),
onPressed: () {
setState(() {
username = usernameController.text;
isUserLoggedIn = true;
});
print(username);
Navigator.pop(context, isUserLoggedIn);
},
label: Text("Finish"),
),

Related

CircularProgressIndicator not stopping while moving back

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

SpeedDial: change color on click

I'm trying to do so that if I click on a SpeedDialChild (button) then the color of it changes, but even if the value of fun.switchTakePhoto changes from true to false (and vice versa) the color remains red for some reason.
class MainPage extends StatefulWidget {
Home createState() => Home();
}
#immutable
class Home extends State<MainPage> {
//Home({super.key});
var fun = FunctionManager();
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: ElevatedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => ChangePWD()),
);
},
child: const Text('Change password'),
),
),
floatingActionButton: SpeedDial(
icon: Icons.settings,
backgroundColor: Colors.amber,
children: [
SpeedDialChild(
child: const Icon(Icons.photo_camera),
label: 'Activate/Deactivate: Take Photo',
backgroundColor: fun.switchSendPhoto == true
? const Color.fromARGB(255, 109, 255, 64)
: const Color.fromARGB(255, 255, 64, 64),
onTap: () {
setState(() {
fun.switchTakePhoto = !fun.switchTakePhoto;
});
},
),
]),
);
}
}
class FunctionManager {
bool switchTakePhoto = true;
bool switchSendPhoto = false;
bool switchRec = true;
bool switchPlay = true;
bool switchNotifications = true;
}
The issue might be with data class. I've solve this way.
class FunctionManager {
final bool switchSendPhoto;
FunctionManager({
this.switchSendPhoto = false,
});
FunctionManager copyWith({
bool? switchTakePhoto,
}) {
return FunctionManager(
switchSendPhoto: switchTakePhoto ?? switchSendPhoto,
);
}
}
A state-level variaable like
FunctionManager fun = FunctionManager()
And update data
onTap: () {
fun = fun.copyWith(switchTakePhoto: !fun.switchSendPhoto);
setState(() {});
},
Same goes for others

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()

boolean expression must not be empty error in Flutter

I'm trying to check if the user likes the current post and set an icon. I'm trying to do a simple check but it throws an error.
The method I created
List<String> fav = List<String>();
checkFav(String id) {
bool isFav = fav.contains(id);
if(isFav)
return true;
else
return null;
}
And where I use the method
IconButton(
icon: Icon(favorite.checkFav(widget.blogModel.id)
? Icons.favorite
: Icons.favorite_border,
color: Colors.redAccent),
onPressed: () {
setState(
() {
favorite.checkFav(widget.blogModel.id)
? favorite.deleteItemToFav(widget.blogModel.id)
: favorite.addItemToFav(widget.blogModel.id);
},
);
//favorite.checkItemInFav(widget.blogModel.id, context);
},
),
Your checkFav should specify it returns bool. Also, you are returning null in case of false which is properly not what you have intended.
So you can rewrite your method to the following which will properly work:
bool checkFav(String id) => fav.contains(id);
Good day. Try this code:
class MyHomePage extends StatelessWidget {
final _favorites = <String>['1', '2', '3'];
#override
Widget build(BuildContext context) {
final buttonIsActive = checkFavorites('1', _favorites);
return Scaffold(
body: Center(
body: Center(child: buildFavoriteButton(isActive: buttonIsActive)),
),
);
}
}
bool checkFavorites(String id, List<String> favorites) {
return favorites.contains(id);
}
Widget buildFavoriteButton({bool isActive = false}) {
return IconButton(
icon: Icon(
Icons.ac_unit,
color: isActive ? Colors.red : Colors.grey,
),
onPressed: () {},
);
}

How to get state changed value after widget build?

I have simple application where I work with user location. On first app open I will ask from user to allow location and then save to var. But when I try check inside widget location allow status it is return old value instance of changed value.
Code
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:yandex_mapkit/yandex_mapkit.dart';
import 'package:permission_handler/permission_handler.dart';
class PlacesListScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return _Map();
}
}
class _Map extends StatefulWidget {
#override
_MapState createState() => _MapState();
}
class _MapState extends State<_Map> {
YandexMapController controller;
PermissionStatus _permissionStatus = PermissionStatus.undetermined;
#override
void initState() {
super.initState();
_requestPermission();
}
Future<void> _requestPermission() async {
Map<Permission, PermissionStatus> permissions =
await [Permission.location].request();
setState(() {
_permissionStatus = permissions[Permission.location];
});
}
void _showMessage(BuildContext context, Text text) {
final ScaffoldState scaffold = Scaffold.of(context);
scaffold.showSnackBar(
SnackBar(
content: text,
action: SnackBarAction(
label: 'OK', onPressed: scaffold.hideCurrentSnackBar),
),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('App Name'),
actions: <Widget>[
IconButton(
icon: Icon(Icons.add),
onPressed: null,
),
],
),
body: Text('App Content'),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
floatingActionButton: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
FloatingActionButton(
onPressed: () async {
if (_permissionStatus == PermissionStatus.granted) {
await Future.wait([
controller.moveToUser(),
controller.showUserLayer(
iconName: 'lib/assets/arrow.png',
arrowName: 'lib/assets/user_location1.png',
accuracyCircleFillColor: Colors.green.withOpacity(0.5),
)
]);
} else {
_showMessage(context, const Text('Permission Denied'));
}
},
child: Icon(Icons.place, color: Colors.white),
backgroundColor: Colors.green,
heroTag: 'showUserLocation',
),
],
),
);
}
}
Using FloatingActionButton I tried check Permission status in my code. But my var _permissionStatus doesn't updated when user allowed location. How to fix this problem and get changed value from state?
You can use this package: https://pub.dev/packages/location
and then you can read the permission status:
Location location = new Location();
PermissionStatus _permissionGranted;
_permissionGranted = await location.hasPermission();
if (_permissionGranted == PermissionStatus.denied) {
_permissionGranted = await location.requestPermission();
if (_permissionGranted != PermissionStatus.granted) {
return;
}
}
another way:
location.hasPermision().then(PermissionStatus status){
if (_permissionGranted == PermissionStatus.denied){
location.requestPermission().then((PermissionStatus requestStatus){
// save the value
}
);
}
});
You need to know when user grand the permission then you know it, you must use the wrap your widget with FocusScope like this:
first define this:
final _focusNode = FocusScopeNode();
then wrap it with this:
return FocusScope(
node: _focusNode,
child: WillPopScope(
onWillPop: () async {
_requestPermission();
},.....