How to add basic functionalities in calculator app? like addition, subtraction - flutter

Can someone please help me with adding functionalities to my calculator app? Well, I have done everything in it the only thing remaining is to add calculations operation. I am a bit confused about how to make calculations operation work when the user inputs something please help me out! This is going to be my first app... code is given below
import 'package:calculator/constants/constants.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Calculator',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
debugShowCheckedModeBanner: false,
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
var question = "0";
var answer1 = "0";
var result = "";
/* String _privateOutput = "0"; */
/* double num1 = 0.0;
double num2 = 0.0;
String task = ""; */
Widget calculatorButton(String numberText) {
return Expanded(
child: MaterialButton(
onPressed: () {
setState(() {
if (question == "0") {
question = numberText;
} else {
question += numberText;
}
});
},
padding: EdgeInsets.all(24),
child: Text(
numberText,
style: kCalculatorStyle,
),
),
);
}
Widget calculatorButtonSymbols(String text) {
return Expanded(
child: MaterialButton(
onPressed: () {
setState(() {
if (text == "÷" || text == "×" || text == "+" || text == "-") {
} else if (text == "=") {}
});
},
padding: EdgeInsets.all(24),
child: Text(
text,
style: kCalculatorStyleSymbols,
),
),
);
}
Widget calculatorButtonTopSymbols(String text) {
return Expanded(
child: MaterialButton(
onPressed: () {
setState(() {
if (text == "AC") {
question = "0";
} else if (text == "±" || text == "%") {
question += text;
}
});
},
padding: EdgeInsets.all(24),
child: Text(
text,
style: kCalculatorStyleSymbols1,
),
),
);
}
Widget calculatorResetButton(IconData icon) {
return Expanded(
child: MaterialButton(
onPressed: () {
setState(() {
if (icon == Icons.arrow_back) {
question = question.substring(0, question.length - 1);
}
if (question == "") {
question = "0";
}
});
},
padding: EdgeInsets.all(24),
child: Icon(
icon,
size: 30,
),
),
);
}
#override
Widget build(BuildContext context) {
SystemChrome.setSystemUIOverlayStyle(
SystemUiOverlayStyle(
statusBarColor: Colors.transparent,
systemNavigationBarColor: Colors.transparent,
statusBarIconBrightness: Brightness.dark,
systemNavigationBarIconBrightness: Brightness.dark,
),
);
return Scaffold(
backgroundColor: Colors.white,
body: Container(
child: Column(
children: [
SafeArea(
child: Container(
alignment: Alignment.centerRight,
padding: EdgeInsets.all(20),
child: Text(
question,
style: kCalculatorStyle,
),
),
),
Expanded(child: Divider()),
Column(
children: [
Row(
children: [
calculatorButtonTopSymbols('AC'),
calculatorButtonTopSymbols('±'),
calculatorButtonTopSymbols('%'),
calculatorButtonSymbols('÷'),
],
),
Row(
children: [
calculatorButton('7'),
calculatorButton('8'),
calculatorButton('9'),
calculatorButtonSymbols('×'),
],
),
Row(
children: [
calculatorButton('4'),
calculatorButton('5'),
calculatorButton('6'),
calculatorButtonSymbols('-'),
],
),
Row(
children: [
calculatorButton('1'),
calculatorButton('2'),
calculatorButton('3'),
calculatorButtonSymbols('+'),
],
),
Row(
children: [
calculatorResetButton(Icons.arrow_back),
calculatorButton('0'),
calculatorButton('.'),
calculatorButtonSymbols('='),
],
),
],
),
],
),
),
);
}
}

Check Out this Link . You can get Idea From Here .

Related

How to change Elevated button's title and color onpressed

I'm developing an app to make meal reservations, and I have an ElevatedButton that opens an alert when pressed. This alert is where the user is able to confirm the reservation. So, the alert has 2 text buttons, and I need that when the "sim" button is pressed, the ElevatedButton changes from "Reservar" with green color to "Cancelar Reserva" with red color.
I tried this way but it doesn't work:
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import '../components/meal_item.dart';
import '../models/day_of_week.dart';
import '../models/want_to_comment.dart';
import '../models/meal.dart';
import '../utils/app_routes.dart';
import '../data/dummy_data.dart';
enum StatusReserva { y, n }
Color statusToColor(StatusReserva value) {
Color color = Colors.green;
switch (value) {
case StatusReserva.n:
break;
case StatusReserva.y:
color = Colors.red;
break;
}
return color;
}
String statusToString(StatusReserva value) {
String title = 'Reservar';
switch (value) {
case StatusReserva.n:
break;
case StatusReserva.y:
title = 'Cancelar Reserva';
break;
}
return title;
}
class DaysOfWeekMealsScreen extends StatefulWidget {
final List<Meal> meals;
final StatusReserva status;
final Function(StatusReserva) onStatusChanged;
const DaysOfWeekMealsScreen({
Key? key,
required this.meals,
required this.status,
required this.onStatusChanged,
}) : super(key: key);
#override
State<DaysOfWeekMealsScreen> createState() => _DaysOfWeekMealsScreenState();
}
class _DaysOfWeekMealsScreenState extends State<DaysOfWeekMealsScreen> {
StatusReserva status = StatusReserva();
#override
void initState() {
super.initState();
status = widget.status;
}
#override
Widget build(BuildContext context) {
final dayOfWeek = ModalRoute.of(context)!.settings.arguments as DayOfWeek;
final dayOfWeekMeals = widget.meals.where((meal) {
return meal.days_of_week.contains(dayOfWeek.id);
}).toList();
void _incrementCount(BuildContext context) {
dayOfWeek.count++;
}
Future<void> _showMyDialog(BuildContext context) async {
return showDialog<void>(
context: context,
barrierDismissible: false, // user must tap button!
builder: (BuildContext context) {
return AlertDialog(
title: const Text(
' ',
),
content: SingleChildScrollView(
child: ListBody(
children: const <Widget>[
Text(
'Confirmar reserva para o dia XX/XX/XX?',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 15,
fontFamily: 'Raleway',
fontWeight: FontWeight.bold),
),
],
),
),
actions: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
TextButton(
child: const Text('Sim'),
onPressed: () => {
_incrementCount,
Navigator.pop(context),
status = StatusReserva.y
},
),
TextButton(
child: const Text('Não'),
onPressed: () => Navigator.pop(context),
),
],
),
],
);
},
);
}
return Scaffold(
appBar: AppBar(
title: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Image.asset(
'assets/images/logo.png',
fit: BoxFit.contain,
height: 32,
),
Container(
padding: const EdgeInsets.all(8.0),
child: Text(dayOfWeek.title)),
],
),
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15),
),
margin: const EdgeInsets.all(10),
child: ElevatedButton(
onPressed: () => {_showMyDialog(context)},
style: ButtonStyle(
shape: MaterialStateProperty.all(RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15),
)),
padding: MaterialStateProperty.all(const EdgeInsets.all(15)),
backgroundColor:
MaterialStateProperty.all(statusToColor(widget.status)),
),
child: Text(statusToString(widget.status)),
),
),
Expanded(
child: ListView.builder(
itemCount: dayOfWeekMeals.length,
itemBuilder: (ctx, index) {
return MealItem(dayOfWeekMeals[index]);
},
),
),
],
),
);
}
}
import 'package:apetit_project/models/want_to_comment.dart';
import 'package:apetit_project/screens/login_screen.dart';
import 'package:flutter/material.dart';
import 'screens/tabs_screen.dart';
import 'screens/days_of_week_meals_screen.dart';
import 'screens/meal_detail_screen.dart';
import 'screens/settings_screen.dart';
import 'screens/want_to_comment_screen.dart';
import 'screens/comment_screen.dart';
import 'utils/app_routes.dart';
import 'models/meal.dart';
import 'models/settings.dart';
import 'data/dummy_data.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
Settings settings = Settings();
StatusReserva status = StatusReserva();
List<Meal> _gourmetMeals = [];
List<Meal> _lightMeals = [];
void _filterMeals(Settings settings) {
setState(() {
this.settings = settings;
});
}
void _reserveMeals(StatusReserva status) {
setState(() {
this.status = status;
});
}
void _toggleGourmet(Meal meal) {
setState(() {
_gourmetMeals.contains(meal)
? _gourmetMeals.remove(meal)
: _gourmetMeals.add(meal);
});
}
bool _isGourmet(Meal meal) {
return _gourmetMeals.contains(meal);
}
void _toggleLight(Meal meal) {
setState(() {
_lightMeals.contains(meal)
? _lightMeals.remove(meal)
: _lightMeals.add(meal);
});
}
bool _isLight(Meal meal) {
return _lightMeals.contains(meal);
}
#override
Widget build(BuildContext context) {
final ThemeData tema = ThemeData(
fontFamily: 'Raleway',
textTheme: ThemeData.light().textTheme.copyWith(
headline6: const TextStyle(
fontSize: 20,
fontFamily: 'Raleway',
fontWeight: FontWeight.bold,
),
),
);
return MaterialApp(
title: 'Appetit',
theme: tema.copyWith(
colorScheme: tema.colorScheme.copyWith(
primary: const Color.fromRGBO(222, 1, 59, 1),
secondary: const Color.fromRGBO(240, 222, 77, 1),
),
),
routes: {
AppRoutes.LOGIN: (ctx) => LoginScreen(),
AppRoutes.HOME: (ctx) => TabsScreen(_gourmetMeals, _lightMeals),
AppRoutes.WANT_TO_COMMENT: (ctx) => const WantToCommentScreen(),
AppRoutes.COMMENT: (ctx) => const CommentScreen(),
AppRoutes.DAYS_OF_WEEK_MEALS: (ctx) => DaysOfWeekMealsScreen(
meals: DUMMY_MEALS,
status,
_reserveMeals,
),
AppRoutes.MEAL_DETAIL: (ctx) => MealDetailScreen(
_toggleGourmet, _isGourmet, _toggleLight, _isLight),
AppRoutes.SETTINGS: (ctx) => SettingsScreen(settings, _filterMeals),
},
);
}
createMaterialColor(Color color) {}
}
To change the state of a widget you can use setState
enum StatusReserva { y, n }
Color statusToColor(StatusReserva value) {
Color color = Colors.green;
switch (value) {
case StatusReserva.n:
break;
case StatusReserva.y:
color = Colors.red;
break;
}
return color;
}
class StatusTest extends StatefulWidget {
const StatusTest({Key? key}) : super(key: key);
#override
State<StatusTest> createState() => _StatusTestState();
}
class _StatusTestState extends State<StatusTest> {
var status = StatusReserva.n;
Future<void> _showMyDialog(BuildContext context) async {
return showDialog<void>(
context: context,
barrierDismissible: false, // user must tap button!
builder: (BuildContext context) {
return AlertDialog(
title: const Text(
' ',
),
content: SingleChildScrollView(
child: ListBody(
children: const <Widget>[
Text(
'Confirmar reserva para o dia XX/XX/XX?',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 15,
fontFamily: 'Raleway',
fontWeight: FontWeight.bold),
),
],
),
),
actions: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
TextButton(
child: const Text('Sim'),
onPressed: () => setState(() {
Navigator.pop(context);
status = StatusReserva.n;
}),
),
TextButton(
child: const Text('Não'),
onPressed: () => setState(() {
Navigator.pop(context);
status = StatusReserva.y;
}),
),
],
),
],
);
},
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 0,
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
width: 100,
height: 100,
child: Container(
color: statusToColor(status),
child: const Center(
child: Text(
'Status color',
style: TextStyle(color: Colors.white),
)),
),
),
ElevatedButton(
onPressed: () {
_showMyDialog(context);
},
child: const Text('Show dialog'),
),
],
),
),
);
}
}
For further clarification
The StatusReserva status = StatusReserva.n; should be in the State class _DaysOfWeekMealsScreenState. And to change it use setState. This value should never change if not inside a setState.
The Sim button onPressed should be like the following (Also with fixes of an unintended Set creation):
TextButton(
child: const Text('Sim'),
onPressed: () {
_incrementCount();
Navigator.pop(context);
setState(() => status = StatusReserva.y);
},
),
Use a boolean value instead of enum like this
bool isCancelReservar = false;
and in the state class before build method add this code :
bool isCancelReservar = false;
#override
void initState(){
isCancelReservar = widget.isCancelReservar;
super.initState();
}
Now you are able to update the value of isCancelReservar on clicking "sim button" using setState method. Your text button should look like this :
TextButton(
child: const Text('Sim'),
onPressed: () {
setState(() {
isCancelReservar = true;
});
_incrementCount,
Navigator.pop(context);
},
),
and your elevated button like this :
Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15),
),
margin: const EdgeInsets.all(10),
child: ElevatedButton(
onPressed: () => {_showMyDialog(context)},
style: ButtonStyle(
shape: MaterialStateProperty.all(RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15),
)),
padding: MaterialStateProperty.all(const EdgeInsets.all(15)),
backgroundColor:
MaterialStateProperty.all(isCancelReservar ? Colors.red :
Colors.green),
),
child: Text(isCancelReservar ? "Cancelar Reserva" : "Reservar"),
),
),
where you can see the backgroundColor will be red with text "Cancelar Reserva" if the value of isCancelReservar is true else it would be of color green with test Reservar.

How to move the Quiz interface to the next question?

Here is the code for a Quiz App I have been making. This is the main.dart file.
import 'package:flutter/material.dart';
import 'list.dart';
void main() {
runApp(
const Quizzler(),
);
}
class Quizzler extends StatefulWidget {
const Quizzler({Key? key}) : super(key: key);
#override
State<Quizzler> createState() => _QuizzlerState();
}
class _QuizzlerState extends State<Quizzler> {
List<Widget> scoreKeeper = [];
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.black,
body: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(
flex: 6,
child: Padding(
padding: const EdgeInsets.all(32.0),
child: Center(
child: Text(
Quiz().getQuestion(),
style: const TextStyle(
color: Colors.white,
fontSize: 20,
),
textAlign: TextAlign.center,
),
),
),
),
boolButton(Colors.green, 'True'),
boolButton(Colors.red, 'False'),
Row(
children: scoreKeeper,
),
],
),
),
);
}
Expanded boolButton(Color c, String s) {
return Expanded(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: ElevatedButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(c),
),
onPressed: () {
setState(
() {
switcher(s);
Quiz().nextQuestion();
},
);
},
child: Text(
s,
),
),
),
);
}
switcher(String s) {
if (Quiz().getAnswer().toLowerCase() == s.toLowerCase()) {
scoreKeeper.add(
const Icon(
Icons.check,
color: Colors.green,
),
);
} else {
scoreKeeper.add(
const Icon(
Icons.close,
color: Colors.red,
),
);
}
}
}
This is the list.dart file that I imported onto the main.dart file:
import 'question.dart';
class Quiz {
int _counter = 0;
final List<Question> _q = [
Question(
'Cows can only be lead up a flight of stairs and not down.',
'False',
),
Question(
'Approximately one quarter of human bones are in the feet.',
'True',
),
Question(
'A slug\'s blood is green.',
'True',
),
];
void nextQuestion() {
_counter++;
}
String getQuestion() {
return _q[_counter].question;
}
String getAnswer() {
return _q[_counter].answer;
}
}
And this is the question.dart file that I imported onto the list.dart file:
class Question {
String question;
String answer;
Question(this.question, this.answer);
}
In the Quiz app, once I hit True or False it just shows a tick for the right answer (False) and a cross for the wrong answer (True), without moving to the next question. How do I fix this?
Here, you call any variables or methods from Quiz class by calling directly by Quiz(), basically problems occur here.
By calling Quiz() every time you created a new object, there is no tracking of this object. Because you don't save the object.
So, at first, save the object like that...
Quiz quiz = Quiz();
then wherever you call by Quiz(), replace by quiz.
be like..... quiz.getQuestion(),quiz.nextQuestion(),quiz.getAnswer()
I add all three dart file added below ... with the solution of showing a ques ending alert snackbar.
This is the main.dart file.
import 'package:flutter/material.dart';
import 'list.dart';
void main() {
runApp(
const Quizzler(),
);
}
class Quizzler extends StatefulWidget {
const Quizzler({Key? key}) : super(key: key);
#override
State<Quizzler> createState() => _QuizzlerState();
}
class _QuizzlerState extends State<Quizzler> {
/// This is for show snack bar
final _messangerKey = GlobalKey<ScaffoldMessengerState>();
Quiz quiz = Quiz();
List<Widget> scoreKeeper = [];
#override
Widget build(BuildContext context) {
return MaterialApp(
scaffoldMessengerKey: _messangerKey,
home: Scaffold(
backgroundColor: Colors.black,
body: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(
flex: 6,
child: Padding(
padding: const EdgeInsets.all(32.0),
child: Center(
child: Text(
quiz.getQuestion(),
style: const TextStyle(
color: Colors.white,
fontSize: 20,
),
textAlign: TextAlign.center,
),
),
),
),
boolButton(Colors.green, 'True'),
boolButton(Colors.red, 'False'),
Row(
children: scoreKeeper,
),
],
),
),
);
}
Expanded boolButton(Color c, String s) {
return Expanded(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: ElevatedButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(c),
),
onPressed: () {
(quiz.q.length - 1) > quiz.counter ? setState(
() {
switcher(s);
quiz.nextQuestion();
},
) : _messangerKey.currentState!.showSnackBar(
const SnackBar(duration: Duration(seconds : 2),content: Text('No more questions')));
},
child: Text(
s,
),
),
),
);
}
switcher(String s) {
if (quiz.getAnswer().toLowerCase() == s.toLowerCase()) {
scoreKeeper.add(
const Icon(
Icons.check,
color: Colors.green,
),
);
} else {
scoreKeeper.add(
const Icon(
Icons.close,
color: Colors.red,
),
);
}
}
}
This is the list.dart file
import 'question.dart';
class Quiz {
int counter = 0;
final List<Question> q = [
Question(
'Cows can only be lead up a flight of stairs and not down.',
'False',
),
Question(
'Approximately one quarter of human bones are in the feet.',
'True',
),
Question(
'A slug\'s blood is green.',
'True',
),
];
void nextQuestion() {
counter++;
}
String getQuestion() {
return q[counter].question;
}
String getAnswer() {
return q[counter].answer;
}
}
And this is the question.dart file
class Question {
String question;
String answer;
Question(this.question, this.answer);
}

Flutter: How to replace icon image from the list of pictures to chose from?

For instance: I have a main Icon so when you click on it, it opens a pop-up window with smaller icons/images to select from. So if you select one of the pictures from that pop-up it replaces the main Icon to that specific image.
I have spent hours trying to figure out how to replace icon images but nothing seems to work.
I have created an example (I have used flutter_speed_dial to make expandable buttons but it's not necessary). You can adjust it to your needs:
class _TestState extends State<Test> {
var fabIcon = Icons.expand_less;
var button1Icon = Icons.home;
var button2Icon = Icons.shop;
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
floatingActionButton: SpeedDial(
icon: fabIcon,
backgroundColor: Color(0xFF801E48),
visible: true,
curve: Curves.bounceIn,
children: [
// FAB 1
SpeedDialChild(
child: Icon(button1Icon),
backgroundColor: Color(0xFF801E48),
onTap: () {
var temp = fabIcon;
setState(() {
fabIcon = button1Icon;
button1Icon = temp;
});
},
labelStyle: TextStyle(
fontWeight: FontWeight.w500,
color: Colors.white,
fontSize: 16.0),
labelBackgroundColor: Color(0xFF801E48)),
// FAB 2
SpeedDialChild(
child: Icon(button2Icon),
backgroundColor: Color(0xFF801E48),
onTap: () {
var temp = fabIcon;
setState(() {
fabIcon = button2Icon;
button2Icon = temp;
});
},
labelStyle: TextStyle(
fontWeight: FontWeight.w500,
color: Colors.white,
fontSize: 16.0),
labelBackgroundColor: Color(0xFF801E48))
],
),
),
);
}
}
Using showDialog(...) is the solution.
Hope this will help you and others.
you can look at this example:
import 'package:flutter/material.dart';
class IconDialogScreen extends StatefulWidget {
const IconDialogScreen({Key? key}) : super(key: key);
#override
State<IconDialogScreen> createState() => _IconDialogScreenState();
}
class _IconDialogScreenState extends State<IconDialogScreen> {
IconData icon = Icons.abc;
List<IconData> icons = [
Icons.abc,
Icons.person_add,
Icons.person,
Icons.person_remove,
];
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Center(
child: TextButton(
onPressed: onIconClicked,
child: Wrap(
crossAxisAlignment: WrapCrossAlignment.center,
spacing: 20,
children: [Icon(icon, size: 50), const Text("change icon")],
),
),
)
],
),
);
}
void onIconClicked() async {
IconData? _icon = await showDialog<IconData?>(
context: context,
builder: (context) {
return AlertDialog(
title: const Text('Select one icon'),
content: Wrap(
spacing: 10,
runSpacing: 10,
children: icons.map<Widget>((e) {
return ElevatedButton(
onPressed: () {
Navigator.of(context).pop(e);
},
child: Icon(e, size: 50));
}).toList(),
),
);
},
);
if (_icon != null) {
setState(() {
icon = _icon;
});
}
}
}

DROPDOWNBUTTON WITH CLASS - Either zero or 2 or more [DropdownMenuItem]s were detected with the same value

Good afternoon, I have a problem that I have already tried to solve on my own for days, but I can not, I hope you can help me.
I have 2 DropdownButton, of which the first one if it changes and the next one loads. When I try to change the second DropdownButton, let's say I choose ACCESSORIES I get the message, lines below I attach the code.
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:app_calimod_pedidos/models/coleccion.dart';
import 'package:app_calimod_pedidos/providers/coleccion_provider.dart';
import 'package:app_calimod_pedidos/providers/compania_provider.dart';
import 'package:app_calimod_pedidos/services/coleccion_services.dart';
import 'package:app_calimod_pedidos/shared_preference/usuario_shared_preference.dart';
import 'package:app_calimod_pedidos/models/compania.dart';
import 'package:app_calimod_pedidos/models/usuario.dart';
import 'package:app_calimod_pedidos/providers/usuario_provider.dart';
import 'package:app_calimod_pedidos/services/compania_services.dart';
dynamic tempColeccionSelect;
class ProductosPage extends StatefulWidget {
const ProductosPage({Key key}) : super(key: key);
#override
_ProductosPageState createState() => _ProductosPageState();
}
class _ProductosPageState extends State<ProductosPage> {
List<Compania> _companialist;
Compania _compania;
Coleccion _coleccion;
CompaniaServices _companiaServices = new CompaniaServices();
ColeccionServices _coleccionServices = new ColeccionServices();
UsuarioPreferences _usuarioPreferences = new UsuarioPreferences();
String token;
List<Compania> listcompania;
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
Compania selectCompania;
Usuario usuario = Provider.of<UsuarioProvider>(context).getUsuario;
token = usuario.token;
return SafeArea(
child: Scaffold(
appBar: AppBar(
title: Text('Pedidos'),
),
body: Container(
padding: EdgeInsets.all(15.0),
width: MediaQuery.of(context).size.width,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Center(
child: Text(
'PEDIDO',
style: TextStyle(
fontSize: 17.0,
),
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Column(
children: [
ListarCombos(
token: token,
)
],
))
],
)
],
),
),
),
);
}
}
class ListarCombos extends StatefulWidget {
final String token;
ListarCombos({#required this.token});
#override
_ListarCombosState createState() => _ListarCombosState();
}
class _ListarCombosState extends State<ListarCombos> {
CompaniaServices companiaServices = new CompaniaServices();
ColeccionServices coleccionServices = new ColeccionServices();
List<Compania> listcompania;
List<Coleccion> listcoleccion;
Compania selectCompania;
Coleccion _selectColeccion;
String selectCombo;
#override
Widget build(BuildContext context) {
final coleccionProvider =
Provider.of<ColeccionProvider>(context, listen: false);
return Container(
//width: MediaQuery.of(context).size.width * 0.7,
child: Column(
children: [
FutureBuilder(
// future: companiaServices.obtenerCompania(widget.token),
future: companiaServices.obtenerCompania(widget.token),
builder: (context, AsyncSnapshot snaphost) {
if (snaphost.hasData) {
listcompania = snaphost.data;
return Container(
child: DropdownButton<Compania>(
hint: Text("Seleccionar"),
value: selectCompania,
onChanged: (Compania value) {
setState(() {
selectCompania = value;
Provider.of<CompaniaProvider>(context,
listen: false)
.setCompania(value);
});
},
items: listcompania.map((Compania compania) {
return new DropdownMenuItem<Compania>(
value: compania,
child: new Text(
compania.name,
style: new TextStyle(color: Colors.black),
),
);
}).toList()));
} else {
return Container(child: CircularProgressIndicator());
}
}),
//selectCompania != null ??
SizedBox(
height: 10,
),
selectCompania != null
? FutureBuilder(
future: coleccionServices.obtenerColeccion(
widget.token, selectCompania.id),
builder: (context, AsyncSnapshot snaphost) {
if (snaphost.connectionState == ConnectionState.waiting) {
return Container(
child: CircularProgressIndicator(),
);
}
if (snaphost.hasData) {
listcoleccion = null;
listcoleccion = snaphost.data;
return DropdownButton<Coleccion>(
value: _selectColeccion,
hint: Text('Seleccione'),
onChanged: (Coleccion value) {
setState(() {
_selectColeccion = value;
});
},
items: listcoleccion?.map((Coleccion coleccion) {
return new DropdownMenuItem<Coleccion>(
value: coleccion,
child: new Text(
coleccion.name,
style: new TextStyle(color: Colors.black),
),
);
})?.toList() ??
[]);
} else {
return Container(
child: Text('Seleccione una Compania'),
);
}
})
: Container(
child: Text('ABC'),
)
],
),
);
}
}
https://gist.github.com/hacrispin/162345a2a3ee4953c96c41dbe69f47bd
Imagen ERROR APP
Imagen Error

How to rebuild IndexedStack when its children particular state changes

IndexedStack solved the problem of persisting the content when the bottom navigation index changes. But I how couldn't find a way to rebuild the IndexedStack when its children state changes. The children's state change is reflected only when the app is restarted.
IndexedStack is not updated when _children changed.
Below is the code:
Widget myBody() {
Widget myBodyWidgetData = SizedBox.shrink();
if (_isSelectedConnectionReady &&
_selectedConnectionId is int &&
_selectedConnectionId >= 0 &&
_selectedConnection.runtimeType == Connection) {
myBodyWidgetData = IndexedStack(
index: _selectedBottomNavigationIndex,
children: _children,
);
} else if (_isSelectedConnectionReady && _selectedConnectionId < 0) {
final GlobalKey<RefreshIndicatorState> _refreshIndicatorKey =
new GlobalKey<RefreshIndicatorState>();
myBodyWidgetData = RefreshIndicator(
key: _refreshIndicatorKey,
onRefresh: setSelectedConnection,
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.fromLTRB(10, 20, 10, 20),
child: Text(
"Kindly add a connection to manage woocommerce",
textAlign: TextAlign.center,
),
),
Container(
height: 45,
width: 200,
child: RaisedButton(
color: Theme.of(context).primaryColor,
textColor: Colors.white,
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => AddConnectionPage(
refreshConnectionsList: setSelectedConnection,
),
),
);
},
child: Text(
"Add Connection",
style: Theme.of(context).textTheme.button,
),
),
)
],
),
),
);
} else {
myBodyWidgetData = Center(
child: SpinKitPulse(
color: Theme.of(context).primaryColor,
size: 70,
),
);
}
return myBodyWidgetData;
}
Full code:
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:woocommerceadmin/src/common/widgets/MyDrawer.dart';
import 'package:woocommerceadmin/src/connections/widgets/AddConnectionPage.dart';
import 'package:woocommerceadmin/src/customers/widgets/CustomersListPage.dart';
import 'package:woocommerceadmin/src/db/ConnectionDBProvider.dart';
import 'package:woocommerceadmin/src/db/models/Connection.dart';
import 'package:woocommerceadmin/src/orders/widgets/OrdersListPage.dart';
import 'package:woocommerceadmin/src/products/widgets/ProductsListPage.dart';
import 'package:woocommerceadmin/src/reports/widgets/ReportsPage.dart';
import 'package:woocommerceadmin/src/config.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Woocommerce Admin',
theme: ThemeData(
primarySwatch: Colors.purple,
textTheme: TextTheme(
headline: TextStyle(
fontSize: 24.0,
fontWeight: FontWeight.bold,
// backgroundColor: Colors.purple,
// color: Colors.white
),
subhead: TextStyle(
fontSize: 18.0,
fontWeight: FontWeight.bold,
),
body1: TextStyle(
fontSize: 14.0,
),
button: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 16,
)),
),
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
HomePage();
final _HomePageState _homePageState = _HomePageState();
#override
_HomePageState createState() => _homePageState;
Future<void> setSelectedConnection() async {
await _homePageState.setSelectedConnection();
}
}
class _HomePageState extends State<HomePage> {
int _selectedConnectionId = -1;
bool _isSelectedConnectionReady = false;
Connection _selectedConnection;
int _selectedBottomNavigationIndex = 0;
List<Widget> _children = [];
#override
void initState() {
super.initState();
setSelectedConnection();
}
#override
void setState(fn) {
if (mounted) {
super.setState(fn);
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: myAppBar(),
drawer: MyDrawer(),
body: myBody(),
bottomNavigationBar: myBottomNavigation(),
);
}
Future<void> setSelectedConnection() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
int selectedConnectionId;
try {
selectedConnectionId = prefs.getInt("selectedConnectionId");
} catch (e) {
selectedConnectionId = -1;
_isSelectedConnectionReady = true;
}
List<Connection> connectionList =
await ConnectionDBProvider.db.getAllConnections();
if (selectedConnectionId is int &&
selectedConnectionId >= 0 &&
connectionList.isNotEmpty) {
if (connectionList[selectedConnectionId] is Connection) {
setState(() {
_selectedConnectionId = selectedConnectionId;
_selectedConnection = connectionList[_selectedConnectionId];
_isSelectedConnectionReady = true;
_children = [
ReportsPage(
baseurl: _selectedConnection.baseurl,
username: _selectedConnection.username,
password: _selectedConnection.password,
),
OrdersListPage(
baseurl: _selectedConnection.baseurl,
username: _selectedConnection.username,
password: _selectedConnection.password,
),
ProductsListPage(
baseurl: _selectedConnection.baseurl,
username: _selectedConnection.username,
password: _selectedConnection.password,
),
CustomersListPage(
baseurl: _selectedConnection.baseurl,
username: _selectedConnection.username,
password: _selectedConnection.password,
)
];
});
}
}
}
Widget myAppBar() {
Widget myAppBarWidgetData;
if (!_isSelectedConnectionReady &&
_selectedConnectionId is int &&
_selectedConnection is! Connection) {
myAppBarWidgetData = AppBar(
title: Text("Setup"),
);
}
return myAppBarWidgetData;
}
Widget myBody() {
Widget myBodyWidgetData = SizedBox.shrink();
if (_isSelectedConnectionReady &&
_selectedConnectionId is int &&
_selectedConnectionId >= 0 &&
_selectedConnection.runtimeType == Connection) {
myBodyWidgetData = IndexedStack(
index: _selectedBottomNavigationIndex,
children: _children,
);
} else if (_isSelectedConnectionReady && _selectedConnectionId < 0) {
final GlobalKey<RefreshIndicatorState> _refreshIndicatorKey =
new GlobalKey<RefreshIndicatorState>();
myBodyWidgetData = RefreshIndicator(
key: _refreshIndicatorKey,
onRefresh: setSelectedConnection,
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.fromLTRB(10, 20, 10, 20),
child: Text(
"Kindly add a connection to manage woocommerce",
textAlign: TextAlign.center,
),
),
Container(
height: 45,
width: 200,
child: RaisedButton(
color: Theme.of(context).primaryColor,
textColor: Colors.white,
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => AddConnectionPage(
refreshConnectionsList: setSelectedConnection,
),
),
);
},
child: Text(
"Add Connection",
style: Theme.of(context).textTheme.button,
),
),
)
],
),
),
);
} else {
myBodyWidgetData = Center(
child: SpinKitPulse(
color: Theme.of(context).primaryColor,
size: 70,
),
);
}
return myBodyWidgetData;
}
Widget myBottomNavigation() {
Widget myBottomNavigationWidgetData = SizedBox.shrink();
if (_isSelectedConnectionReady &&
_selectedBottomNavigationIndex >= 0 &&
_selectedConnection.runtimeType == Connection) {
myBottomNavigationWidgetData = BottomNavigationBar(
// backgroundColor: Colors.purple, //Not Working Don't Know why
showSelectedLabels: true,
showUnselectedLabels: true,
unselectedItemColor: Config.colors["lightTheme"]
["bottomNavInactiveColor"],
selectedItemColor: Config.colors["lightTheme"]["mainThemeColor"],
currentIndex: _selectedBottomNavigationIndex,
onTap: (int index) {
setState(() {
_selectedBottomNavigationIndex = index;
});
},
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.insert_chart),
title: Text('Reports'),
),
BottomNavigationBarItem(
icon: Icon(Icons.assignment),
title: Text('Orders'),
),
BottomNavigationBarItem(
icon: Icon(Icons.collections),
title: Text('Products'),
),
BottomNavigationBarItem(
icon: Icon(Icons.people),
title: Text('Customers'),
),
]);
}
return myBottomNavigationWidgetData;
}
}
I had the same issue, fixed with passing and assigning the GlobalKey() to the child.
Example:
setState(() {
_children.removeAt(0);
_children.insert(0, CustomWidget(customData: customData, key: GlobalKey()));
});