I am trying to make Tags which are draggable text so that I can drag them to one of 2 DragTarget I have (ideally being able to move them between 3 DragTarget). Unfortunately I can't make them interact with the DragTargets as they dont even call onWillAccept(). My draggables are DragabbleTag and extends Draggable and my dragTargets are in a Stateful Widget and should accept them.
import 'package:myApp/components/draggableTag.dart';
import 'package:flutter/material.dart';
class DraggableTagTarget extends StatefulWidget {
final String title;
final int maxTagAmount;
final Color backgroundColor;
final List<DraggableTag> tagsPool;
const DraggableTagTarget(
{Key key,
this.title,
this.backgroundColor,
this.tagsPool,
this.maxTagAmount})
: super(key: key);
#override
_DraggableTagTargetState createState() => _DraggableTagTargetState();
}
class _DraggableTagTargetState extends State<DraggableTagTarget> {
String test = "Test";
#override
Widget build(BuildContext context) {
return DragTarget<DraggableTag>(onAccept: (DraggableTag value) {
setState(() {
widget.tagsPool.add(value);
test = value.label;
});
}, onWillAccept: (DraggableTag data) {
bool result =
widget.tagsPool.length <= widget.maxTagAmount ? true : false;
debugPrint("ONWillAccept: " + data.label + " = " + result.toString());
return result;
}, builder: (context, candidateData, rejectedData) {
return Container(
decoration: new BoxDecoration(
color: widget.backgroundColor,
border: Border.all(
color: Colors.black,
),
),
child: Column(
children: <Widget>[
Text(test),
Text(widget.title),
SizedBox(
height: 60,
child: Wrap(
children: widget.tagsPool,
),
),
],
),
);
});
}
}
Custom DragTarget 'DraggableTagTarget'
import 'package:flutter/material.dart';
class DraggableTag extends Draggable<String> {
final String label;
DraggableTag({Key key, this.label})
: super(
key: key,
data: label,
child: idleTag(label),
feedback: feedbackTag(label),
childWhenDragging: ghostTag(label),
);
static Widget idleTag(String label) {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 2.0),
child: Text(
label,
style: TextStyle(
fontSize: 16,
),
),
decoration: BoxDecoration(
color: Colors.blue,
border: Border.all(
color: Colors.black,
),
borderRadius: BorderRadius.all(Radius.circular(20)),
),
);
}
Custom Draggable 'DraggableTag'
I excluded feedbackTag() and ghostTag which shouldnt be relevant
At first my draggableTag was extending a widget but seeing some similar problem I made it into extending directly a Draggable but it didnt help
EDIT:
I am assigning ma values to draggable in a custom DialogWidget (stateful widget) in a list
class _RatingDialogState extends State<RatingDialog> {
List<DraggableTag> tagsPool = [
DraggableTag(label: "Acting"),
DraggableTag(label: "Scenario"),
DraggableTag(label: "Pace"),
DraggableTag(label: "Length"),
DraggableTag(label: "Message"),
];
List<DraggableTag> negativeTagsPool = [];
List<DraggableTag> positiveTagsPool = [];
#override
Widget build(BuildContext context) {
return Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
elevation: 0,
backgroundColor: Colors.transparent,
child: contentBox(context),
);
}
contentBox(context) {
return Stack(
...
Wrap(
children: tagsPool,
),
SizedBox(height: 22),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Flexible(
child: FractionallySizedBox(
widthFactor: 0.85,
child: DraggableTagTarget(
title: "Negative",
backgroundColor: Colors.red,
tagsPool: negativeTagsPool,
maxTagAmount: 3),
),
),
Flexible(
child: FractionallySizedBox(
widthFactor: 0.85,
child: DraggableTagTarget(
title: "Positive",
backgroundColor: Colors.green,
tagsPool: positiveTagsPool,
maxTagAmount: 3),
),
),
]),
...
SOLUTION: as ikerfah explained, I didnt put the right type into <> because I was confused to what my DraggableTag class was. I made another class to contains the data Tag so that both my DragTarget and DraggableTag use this class
Draggable and DragTarget must have the same generic type, but you have Draggable<String> and DragTarget<DraggableTag>
Related
I created a stepper (4 steps) with two buttons for next and previous. Each step has a form, and each form is in a widget in its own class.
The first problem is that every time I click the previous button, the data in the text fields disappear.
How can I preserve the state of each widget in each step?
The second problem, I want the last step to be a summary of what the user has entered in the previous steps. What is the best way to get the data from each step and display them in the last step?
I would really appreciate it if you could give me a solution. Thank you
I tried using AutomaticKeepAliveClientMixin but it didn't work .
import 'package:flutter/material.dart';
class CustomeStepper extends StatelessWidget {
final double width;
final List<IconData> icons;
final List<String> titles;
final int curStep;
final Color circleActiveColor;
final Color circleInactiveColor;
final Color iconActiveColor;
final Color iconInactiveColor;
final Color textActiveColor;
final Color textInactiveColor;
final double lineWidth = 4.0;
final List<Widget> content;
CustomeStepper(
{required this.icons,
required this.curStep,
required this.titles,
required this.width,
required this.circleActiveColor,
required this.circleInactiveColor,
required this.iconActiveColor,
required this.iconInactiveColor,
required this.textActiveColor,
required this.textInactiveColor,
required this.content})
: assert(curStep > 0 && curStep <= icons.length),
assert(width > 0);
#override
Widget build(BuildContext context) {
return Directionality(
textDirection: TextDirection.rtl,
child: Container(
width: width,
padding: const EdgeInsets.only(
top: 32.0,
left: 24.0,
right: 24.0,
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Row(
children: _iconViews(),
),
const SizedBox(
height: 10,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: _titleViews(),
),
Expanded(
child: Container(
margin: const EdgeInsets.only(top: 16),
child: content[curStep - 1]),
)
],
)),
);
}
List<Widget> _iconViews() {
var list = <Widget>[];
icons.asMap().forEach((i, icon) {
var circleColor = (i == 0 || curStep >= i + 1)
? circleActiveColor
: circleInactiveColor;
var lineColor = (i == 0 || curStep >= i + 1)
? circleActiveColor
: circleInactiveColor;
var iconColor =
(i == 0 || curStep >= i + 1) ? iconActiveColor : iconInactiveColor;
list.add(
Container(
width: 50.0,
height: 50.0,
padding: const EdgeInsets.all(0),
child: Icon(
icon,
color: iconColor,
size: 25.0,
),
decoration: BoxDecoration(
color: circleColor,
borderRadius: const BorderRadius.all(
Radius.circular(25.0),
),
),
),
);
//line between icons
if (i != icons.length - 1) {
list.add(Expanded(
child: Container(
height: lineWidth,
color: lineColor,
)));
}
});
return list;
}
List<Widget> _titleViews() {
var list = <Widget>[];
titles.asMap().forEach((i, text) {
var _textColor =
(i == 0 || curStep > i + 1) ? textActiveColor : textInactiveColor;
list.add(
Container(
width: 50.0,
alignment: Alignment.topCenter,
padding: const EdgeInsets.all(0),
child: Text(
text,
textAlign: TextAlign.center,
style: TextStyle(color: _textColor, fontWeight: FontWeight.bold),
),
),
);
});
return list;
}
}
import 'package:flutter/material.dart';
import 'package:project_five/widgets/business/adding_product_widgets/first_step.dart';
import 'package:project_five/widgets/business/adding_product_widgets/four_step.dart';
import 'package:project_five/widgets/business/adding_product_widgets/second_step.dart';
import 'package:project_five/widgets/business/adding_product_widgets/third_step.dart';
import 'package:project_five/widgets/business/custome_stepper.dart';
class AddProduct extends StatefulWidget {
const AddProduct({Key? key}) : super(key: key);
#override
State<AddProduct> createState() => _AddProductState();
}
class _AddProductState extends State<AddProduct> {
static const _stepIcons = [
Icons.add_circle,
Icons.document_scanner,
Icons.camera_alt_rounded,
Icons.check,
];
static const _titles = ['المنتج', 'تفاصيل', 'الصور', 'نشر'];
var _contnet = [
FirstStep(),
SecondStep(),
ThirdStep(),
Forth()];
var _curStep = 1;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('إضافة منتج'),
centerTitle: true,
),
persistentFooterButtons: [
Row(
children: [
Expanded(
child: ElevatedButton(
child: const Text('التالي'),
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.all(16),
),
onPressed: () => setState(() {
if (_curStep < _stepIcons.length) _curStep++;
}),
),
),
const SizedBox(
width: 8,
),
Expanded(
child: ElevatedButton(
child: const Text('رجوع'),
style: ElevatedButton.styleFrom(
primary: Colors.white,
onPrimary: Colors.black,
padding: const EdgeInsets.all(16)),
onPressed: () => setState(() {
if (_curStep > 1) _curStep--;
}),
),
),
],
)
],
body: CustomeStepper(
icons: _stepIcons,
width: MediaQuery.of(context).size.width,
curStep: _curStep,
titles: _titles,
circleActiveColor: Colors.green,
circleInactiveColor: const Color(0xffD5D5D5),
iconActiveColor: Colors.white,
iconInactiveColor: Colors.white,
textActiveColor: Colors.green,
textInactiveColor: const Color(0xffD5D5D5),
content: _contnet,
),
);
}
}
I had the same problem, It would help to see your forms widgets. I will try my best to describe what you need to do.
Your textfields in your forms should be tied to your model class. Example: onChange: Product.title = TextField.value. and you should use initial value with your model properties, example: initialValue: Product.title. I think this way you can retain the state of the inputs in your forms.
As for the second part of your question, the Main widget that is controlling the stepper should have a state variable, such as isCompleted, on the last step you set this variable to 'true' and the main body of the stepper should be in a stack, in your stack you check if "isCompleted" ? Stepper : SummaryWidget.
How are handling Arabic titles for text fields and matching them with your class model properties?
I hope my answer can help!
I am trying to implement this design where one chip is clickable at a time
Design Image
I tried multiple approaches like listview and grid view builders, but nothing gave me precisely what I was looking for. I eventually settled for the Wrap() widget with a list used to map Animated Container widgets, it gave me the look I wanted, but when I clicked on one chip, everything changes color instead of one like this.
How I can implement those grids of chips dynamically with the property of only one chip changing color at a time and from there be able to navigate to the next page. For more context, this is the code I used,
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/painting.dart';
import 'package:scree/constants.dart';
class SiteAbooutScreen extends StatefulWidget {
const SiteAbooutScreen({Key? key}) : super(key: key);
#override
_SiteAbooutScreenState createState() => _SiteAbooutScreenState();
}
class _SiteAbooutScreenState extends State<SiteAbooutScreen> {
bool _isTapped = false;
#override Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: EdgeInsets.only(left: 24, right: 24, top: 74.75),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Wrap(
spacing: 16,
runSpacing: 16,
children: _stuff
.map(
(strings) => GestureDetector(
onTap: () {
setState(() {
_isTapped = !_isTapped;
});
},
child: AnimatedContainer(
padding:
EdgeInsets.symmetric(horizontal: 24, vertical: 10),
duration: Duration(milliseconds: 200),
decoration: BoxDecoration(
color: _isTapped ? primary1 : Colors.transparent,
border: Border.all(color: Colors.black54),
borderRadius: BorderRadius.circular(100)),
child: Text(
strings,
style: Small.copyWith(
fontSize: 14,
color:
_isTapped ? Colors.white : Color(0xff929292)),
),
),
),
)
.toList(),
)
],
),
),
);
}
List<String> _stuff = [
'Portfolio',
'Art',
'Marketing',
'Education',
'Blog',
'Travel',
'Fashion',
'Beauty',
'Design',
'Online Store',
'Fitness',
'Food'
];
}
This is happening because you are using single bool to handle every item. That's why everything change at the same time. In order to handle one at a time, you need to check separately.
For this, you can create list of bool or String for selected items.
class SiteAbooutScreen extends StatefulWidget {
const SiteAbooutScreen({Key? key}) : super(key: key);
#override
_SiteAbooutScreenState createState() => _SiteAbooutScreenState();
}
class _SiteAbooutScreenState extends State<SiteAbooutScreen> {
List<String> tappedItems = [];
#override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: EdgeInsets.only(left: 24, right: 24, top: 74.75),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Wrap(
spacing: 16,
runSpacing: 16,
children: _stuff
.map(
(strings) => GestureDetector(
onTap: () {
setState(() {
if (tappedItems.contains(strings)) {
tappedItems.remove(strings);
} else {
tappedItems.add(strings);
}
});
},
child: AnimatedContainer(
padding:
EdgeInsets.symmetric(horizontal: 24, vertical: 10),
duration: Duration(milliseconds: 200),
decoration: BoxDecoration(
color: tappedItems.contains(strings)
? Theme.of(context).primaryColor
: Colors.transparent,
border: Border.all(color: Colors.black54),
borderRadius: BorderRadius.circular(100)),
child: Text(
strings,
style: TextStyle(
fontSize: 14,
color: tappedItems.contains(strings)
? Colors.white
: Color(0xff929292)),
),
),
),
)
.toList(),
)
],
),
),
);
}
List<String> _stuff = [
'Portfolio',
'Art',
'Marketing',
'Education',
'Blog',
'Travel',
'Fashion',
'Beauty',
'Design',
'Online Store',
'Fitness',
'Food'
];
}
I'm trying to create a custom checkbox widget and I'm having trouble getting the bool value of that checkbox from another class:
So am having a form in stateful widget Signup, within this form I'm calling my CustomCheckBox widget (also a stateful widget).
The issue: When I click on the checkbox its value change to true in the CustomCheckBox widget however after submitting the form in Signup widget the value always false (seams to be no back communication between the the two widgets)
My CustomCheckBox code:
import 'package:flutter/material.dart';
import 'package:tunimmo/Constants/palette.dart';
class CustomCheckBox extends StatefulWidget {
bool checked;
final String label;
CustomCheckBox({this.checked, this.label});
#override
_CustomCheckBoxState createState() => _CustomCheckBoxState();
}
class _CustomCheckBoxState extends State<CustomCheckBox> {
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(top: 15.0, left: 30, right: 30),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
Container(
height: 30,
decoration: BoxDecoration(
color: myPrimaryColor,
),
child: Text(" "),
),
Text(' ${widget.label}', style: Theme.of(context).textTheme.bodyText1),
],
),
Center(
child: InkWell(
onTap: () {
setState(() {
widget.checked = !widget.checked;
});
},
child: Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
color: widget.checked ? myPrimaryColor : myWhiteColor,
border: Border.all(
color: myPrimaryColor,
width: 3,
),
),
child: Padding(
padding: const EdgeInsets.all(3.0),
child: widget.checked
? Icon(
Icons.check,
size: 25.0,
color: myWhiteColor,
)
: Icon(
Icons.check_box_outline_blank,
size: 25.0,
color: myWhiteColor,
),
),
),
)),
],
),
);
}
}
In the Signup widget I'm just calling the constructor and passing a bool field (expected to send/get the value in the CustomCheckBox widget) and a string label.
PS: I have more than one checkbox in my form.
Please advice!
The problem is that you are not changing the checked value in the screen(signup) but changing in the custom checkbox, to solve this issue define checked variable in SignUp if not already did, then define Function call back in the checkbox widget as follows:
final Function(bool)checkChanged;
CustomCheckBox({this.checked, this.label,this.checkedChanged});
then call it in ontap and give the value change
onTap: () {
widget.checkedChanged(!widget.checked);
setState(() {
widget.checked = !widget.checked;
});
}
do the following when calling the CustomCheckbox:
CustomCheckBox(
checked:false,
label:'a label',
checkedChanged:(val){
checked=val;
}
)
and use that checked variable when submitting the form and that should solve your problem.
I am trying to pass a custom made container (with background color, title, and onPressed properties) into another custom widget that creates a row of three of these containers. The goal is to be able to input titles for each of these buttons in the second widget like so, TriButton(title1, title2, title3). Any tips or tricks would be appreciated!
Custom container
class RectButton extends StatelessWidget {
RectButton({this.buttonChild, this.bgColor, this.onPress});
final Widget buttonChild;
final Color bgColor;
final Function onPress;
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: onPress,
child: Container(
constraints: BoxConstraints.expand(width: 100, height: 50),
child: Center(child: buttonChild),
decoration: BoxDecoration(
color: bgColor,
shape: BoxShape.rectangle,
border: Border.all(width: 1, color: Colors.white)),
padding: EdgeInsets.fromLTRB(12, 12, 12, 12),
),
);
}
}
`Tri-button code`
enum Weight {
ideal,
actual,
adjusted,
}
class TriButton extends StatefulWidget {
TriButton({this.title1, this.title2, this.title3, this.buttonChild});
final Text title1;
final Text title2;
final Text title3;
final RectButton buttonChild;
#override
_TriButtonState createState() => _TriButtonState();
}
class _TriButtonState extends State<TriButton> {
Weight selectedWeight;
#override
Widget build(BuildContext context) {
return Center(
child: Container(
constraints: BoxConstraints(maxWidth: 300),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(
child: RectButton(
buttonChild: GOAL TO ENTER TITLE HERE,
onPress: () {
setState(() {
selectedWeight = Weight.adjusted;
});
},
bgColor: selectedWeight == Weight.adjusted
? Colors.orange[600]
: Colors.grey[600],
),
),
When using a StatefulWidget you need to use "widget.property" in your implementation.
In your case
Expanded(
child: RectButton(
buttonChild: Text(widget.title1),
onPress: () {
setState(() {
selectedWeight = Weight.adjusted;
});
},
bgColor: selectedWeight == Weight.adjusted
? Colors.orange[600]
: Colors.grey[600],
),
),
Expanded(
child: RectButton(
buttonChild: Text(widget.title2),
onPress: () {
setState(() {
selectedWeight = Weight.adjusted;
});
},
bgColor: selectedWeight == Weight.adjusted
? Colors.orange[600]
: Colors.grey[600],
),
),
.....
I'm trying to get a very simple set of radiobuttons up, which is why it's so frustrating that they aren't working. I've tried setting this up in a similar class, and it's worked. I know for a fact that setstate is being called, but for some reason it's not updating the individual radio button. Which makes me think that this is some weird issue related to state.
Anyways, all help would be appreciated. My main class is the second part of the code below.
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../bloc/thembloc.dart';
import './components/textfield.dart';
class SignUp extends StatefulWidget {
#override
_SignUpState createState() => _SignUpState();
}
class _SignUpState extends State<SignUp> {
/*
ui for signup
includes multiple textfields.
includes all of the information that we'll need
to collect for an user to register an account.
todo: wrap everything in a form, encrypt it and send it to a private server.
*/
#override
Widget build(BuildContext context) {
double _height = MediaQuery.of(context).size.height;
double _width = MediaQuery.of(context).size.width;
final double _margin = 16.0;
final double _promptWidth = _width - 32.0;
final double _promptHeight = _height - 32.0;
final double _textFieldWidth = _promptWidth - 32.0;
int subscriberValue;
void switchSubscriber(int value) {
setState(() {
subscriberValue = value;
});
}
return BlocBuilder(
bloc: BlocProvider.of<ThemeBloc>(context),
builder: (context, ThemeState state) {
return Scaffold(
resizeToAvoidBottomInset: false,
resizeToAvoidBottomPadding: false,
appBar: AppBar(
centerTitle: true,
title: Text(
"smartmoney",
style: BlocProvider.of<ThemeBloc>(context).currentState.themedata.primaryTextTheme.display2,
),
// appbar
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(8.0),
bottomRight: Radius.circular(8.0))),
leading: IconButton(
icon: Icon(
Icons.arrow_back,
color: BlocProvider.of<ThemeBloc>(context).currentState.themedata.buttonColor,
),
onPressed: () {
print("going back");
},
),
backgroundColor: BlocProvider.of<ThemeBloc>(context).currentState.themedata.canvasColor,
),
body: Container(
height: _height,
width: _width,
color: BlocProvider.of<ThemeBloc>(context).currentState.themedata.backgroundColor,
child: Column(
children: <Widget>[
Padding(
padding: EdgeInsets.only(top: _margin),
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(8.0)),
color: BlocProvider.of<ThemeBloc>(context).currentState.themedata.canvasColor,
boxShadow: [
BoxShadow(
spreadRadius: 0.0,
color: Colors.black38,
blurRadius: 6.0,
offset: Offset(0.0, 3.0)),
]),
width: _promptWidth,
height: _promptHeight - 48 - _margin,
child: Column(
children: <Widget>[
Text("Let's get started",
style: BlocProvider.of<ThemeBloc>(context).currentState.themedata.primaryTextTheme.display2,
),
Text("Enter your information to create an account",
style: BlocProvider.of<ThemeBloc>(context).currentState.themedata.primaryTextTheme.subtitle,
),
Padding(
padding: EdgeInsets.only(top: 8.0),
child: StyledTextField(
textFieldWidth: _textFieldWidth,
helperText: "First name",
),
),
Padding(
padding: EdgeInsets.only(top: 8.0),
child: StyledTextField(
textFieldWidth: _textFieldWidth,
helperText: "Last name",
),
),
Padding(
padding: EdgeInsets.only(top: 8.0),
child: StyledTextField(
textFieldWidth: _textFieldWidth,
helperText: "Email",
),
),
Padding(
padding: EdgeInsets.only(top: 8.0),
child: StyledTextField(
textFieldWidth: _textFieldWidth,
helperText: "Password",
),
),
Padding(
padding: EdgeInsets.only(top: 8.0),
child: StyledTextField(
textFieldWidth: _textFieldWidth,
helperText: "Phone number",
),
),
Text("Subscriber type",
style: BlocProvider.of<ThemeBloc>(context).currentState.themedata.primaryTextTheme.display1,
),
Radio(
groupValue: subscriberValue,
value: 0,
onChanged: (int value) => switchSubscriber(value),
),
Radio(
groupValue: subscriberValue,
value: 1,
onChanged: (int value) => switchSubscriber(value),
)
],
),
),
)
],
),
),
);
});
}
}
import 'package:flutter/material.dart';
import './bloc/thembloc.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'ui/signin.dart';
import 'ui/signup.dart';
import 'ui/onboarding.dart';
import './ui/testing/whatthefuck.dart';
void main() {
runApp(
MaterialApp(
home: SmartMoney(),
)
// SmartMoney()
);
}
class SmartMoney extends StatefulWidget {
#override
_SmartMoneyState createState() => _SmartMoneyState();
}
class _SmartMoneyState extends State<SmartMoney> {
final _themeBloc = ThemeBloc();
#override
Widget build(BuildContext context) {
return BlocProvider(
bloc: _themeBloc,
child: SignUp(),
);
}
}
The problem is because you defined your variable subscriberValue inside your build method. You're using setState calls that recall build method and in every recall of build you're losing the value of subscriberValue. I advise you to always use variables that will control the state of your widget as class members.
class _SignUpState extends State<SignUp> {
// HAS TO BE CLASS MEMBER AND IT'S GOOD AN INITIAL VALUE TOO..
int subscriberValue =1; // asuming that 1 is default radio button option
#override
Widget build(BuildContext context) {
//... some codes ...
//int subscriberValue; REMOVE THIS LINE. YOU'RE LOSING THE VALUE IN EVERY setState call
//You can define this method outside from build too.
void switchSubscriber(int value) {
setState(() {
subscriberValue = value;
});
}
}