How to sync the UI with data changes in my code - android

the code is running correctly but the problem is I don't see the UI changes according to the data. as you may notice from my code, in _buildWidget function my cards are made and the shareTag function in the stack is called but at first, because the variable is not true then container is not visible but after the user click on one of the cards I would expect that the isSelected turns to true and then I could see the container in that stack that but it doesn't happen ... I have debugged the code and I noticed that the isSelected variable turn to right correctly every time the users tap on the card but I don't see any changes on UI
Activity activity;
List<double> _cost;
ActivityPeopleCard({this.activity});
#override
_ActivityPeopleCardState createState() => _ActivityPeopleCardState();
}
class _ActivityPeopleCardState extends State<ActivityPeopleCard> {
int _peopleIndex = -1;
List<int> _peopleIndexes = new List();
List<int> _longPressed = new List();
var _vlContainer;
#override
void initState() {
super.initState();
_vlContainer = myListContainer();
}
#override
Widget build(BuildContext context) {
return _vlContainer;
}
myListContainer() {
return Container(
height: height / 2.6,
child: new GridView.builder(
itemCount: widget.activity.peopleInvolved.length,
gridDelegate:
new SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3),
itemBuilder: (BuildContext context, int index) {
return new GestureDetector(
onTap: () => setState(() => {
_priceSet(index),
_buildWidget(index)
}),
child: _buildWidget(index));
},
),
);
}
_buildWidget(int index) {
bool isSelected = _peopleIndexes.contains(index) ? true : false;
return new Card(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(30)),
elevation: 5.0,
child: Stack(children: <Widget>[
new Container(
height: height / 4,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
width: height / 15,
height: height / 15,
decoration: new BoxDecoration(
borderRadius: BorderRadius.circular(height / 20),
border: Border.all(color: Colors.white, width: 2),
),
child: ClipRRect(
borderRadius: BorderRadius.circular(height / 15),
child: Image.asset(
widget.activity.peopleInvolved[index].imagePath,
fit: BoxFit.fill)), //CircleAvatar(
),
Center(child: Text(widget.activity.peopleInvolved[index].name))
],
),
),
shareTag(index)
]));
}
shareTag(index) {
return GestureDetector(
onLongPress: () => {
enterPrice(index),
},
child: Visibility(
visible: isSelected ? true : false,
child: new Container(
height: height / 2,
decoration: new BoxDecoration(
borderRadius: BorderRadius.circular(height / 20),
color: Colors.red.shade500.withOpacity(0.7),
),
child: Center(
child: SizedBox(
width: width / 4,
height: height / 15,
child: Center(
child: AutoSizeText(
"\$${ActivityPeopleCard._cost[index]}",
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.white,
fontFamily: 'Oxygen',
fontSize: height / 25),
maxLines: 1,
minFontSize: 5,
textAlign: TextAlign.center,
),
),
))),
));
}
enterPrice(int index) {
//print("Long Pressed");
showDialog(
context: context,
builder: (context) {
return AlertDialog(
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(25)),
backgroundColor: Colors.white,
content: Form(
//key: _formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
new TextFormField(
initialValue: ActivityPeopleCard._cost[index].toString(),
keyboardType: TextInputType.number,
cursorColor: secondColor,
style: TextStyle(
letterSpacing: 1,
),
autofocus: true,
decoration: new InputDecoration(
focusedBorder: new OutlineInputBorder(
borderRadius: new BorderRadius.circular(15.0),
borderSide: new BorderSide(color: secondColor)),
labelStyle: TextStyle(color: firstColor
//decorationColor: Colors.yellow
),
prefixIcon: Icon(
Icons.attach_money,
color: firstColor,
),
labelText: "Cost",
border: new OutlineInputBorder(
borderRadius: new BorderRadius.circular(15.0),
borderSide: new BorderSide(color: Colors.black87),
),
),
),
],
),
),
);
});
}
}
although I have called the _buildWidget again on onTap function and the isSelected is true the ui is not updated

Related

Want to add login button only when user input credentials

I want to make the login button visible only when user enter the credentials in Text Form Field (Email and Password), otherwise login button should be invisible.
My LoginPage is designed as below:-
class _LoginPageState extends State<LoginPage> {
final _formKey = GlobalKey<FormState>();
late String _email, _password, error = '';
bool _obscureText = true;
bool _isKeyboardVisible = true;
bool _canShowButton = true;
final AuthenticationService _authenticationService = AuthenticationService();
_hideWidget(){
setState(() {
_canShowButton = !_canShowButton;
});
}
_toggle() {
setState(() {
_obscureText = !_obscureText;
});
}
_submit() async {
if(_formKey.currentState!.validate()){
_formKey.currentState?.save();
dynamic result = await _authenticationService.loginWithEmail(email: _email, password: _password);
if(result == null) {
setState(() => error = 'Es wurde kein Benutzerkonto gefunden. Bitte erstellen Sie zuerst das Konto');
} else {
Navigator.pushNamed(context, HomePage.id);
}
print(_email);
print(_password);
}
}
#override
void initState() {
super.initState();
}
#override
void dispose() {
super.dispose();
}
#override
Widget build(BuildContext context) {
_isKeyboardVisible = MediaQuery.of(context).viewInsets.bottom != 0;
if(!_isKeyboardVisible) {
return GestureDetector(
onTap: (){
FocusScopeNode currentFocus = FocusScope.of(context);
if(!currentFocus.hasPrimaryFocus){
currentFocus.unfocus();
}
},
child: Scaffold(
resizeToAvoidBottomInset: false,
backgroundColor: Colors.white,
body: SingleChildScrollView(
child: Column(
children: [
Container(
margin: EdgeInsets.only(top: 20),
alignment: Alignment.center,
child: Text("Bitte Melde Dich an",
style: TextStyle(color: color, fontWeight: FontWeight.bold, fontSize: 28),),
),
Form(
key: _formKey,
autovalidateMode: AutovalidateMode.onUserInteraction,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Padding(
padding: const EdgeInsets.symmetric(horizontal: 30.0, vertical: 10.0),
child: Padding(
padding: EdgeInsets.only(left: 5.0, right: 5.0, top: 5.0),
child: SizedBox(
child: TextFormField(
autofocus: false,
decoration: InputDecoration(
labelText: 'Email',
border: OutlineInputBorder(borderRadius: BorderRadius.all(
const Radius.circular(10.0),
)
),
filled: true,
fillColor: Colors.white,
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: color, width: 2.0),
borderRadius: BorderRadius.circular(10.0)
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: color, width: 2.0),
borderRadius: BorderRadius.circular(10.0)
)
),
validator: (input) => !EmailValidator.validate(input!, true)
? 'Please enter valid email'
: null,
onSaved: (input) => _email = input!,
),
),
),
),
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 30.0, vertical: 10.0
),
child: Padding(
padding: const EdgeInsets.only(left: 5, right: 5, top: 5, bottom: 5),
child: Stack(
alignment: const Alignment(0, 0),
children: <Widget>[
TextFormField(
autofocus: false,
decoration: InputDecoration(
labelText: 'Password',
border: OutlineInputBorder(
borderRadius: BorderRadius.all(
const Radius.circular(10.0)
)
),
filled: true,
fillColor: Colors.white,
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: color, width: 2.0),
borderRadius: BorderRadius.circular(10.0)
),
suffixIcon: IconButton(
onPressed: (){
_toggle();
},
icon: Icon(_obscureText ? Icons.visibility : Icons.visibility_off)
)
),
validator: (input) => input!.length < 6
? 'Must be at least 6 characters': null,
onSaved: (input) => _password = input!,
obscureText: _obscureText,
)
],
),
),
),
Padding(
padding: const EdgeInsets.only(top: 10),
child: Container(
width: MediaQuery.of(context).size.width - 70,
height: MediaQuery.of(context).size.height * 0.09,
child: !_canShowButton ? SizedBox.shrink() : TextButton(
style: TextButton.styleFrom(
primary: Colors.white,
backgroundColor: color,
elevation: 5,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10.0))
),
onPressed: () {
_hideWidget();
},
child: Text('Anmelden')),
),
),
],
),
)
],
),
),
),
);
} else {
return GestureDetector(
onTap: (){
FocusScopeNode currentFocus = FocusScope.of(context);
if(!currentFocus.hasPrimaryFocus){
currentFocus.unfocus();
}
},
child: Scaffold(
resizeToAvoidBottomInset: false,
body: SingleChildScrollView(
child: Column(
children: [
Container(
margin: EdgeInsets.only(top: 60),
alignment: Alignment.center,
child: Text(
'Login Credentials',
style: TextStyle(color: color, fontWeight: FontWeight.bold, fontSize: 28),
overflow: TextOverflow.clip,
)
),
Container(
margin: EdgeInsets.only(top: 20),
alignment: Alignment.center,
child: Text("Bitte Melde Dich an",
style: TextStyle(color: color, fontWeight: FontWeight.bold, fontSize: 28),),
),
Form(
key: _formKey,
autovalidateMode: AutovalidateMode.onUserInteraction,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Padding(
padding: const EdgeInsets.symmetric(horizontal: 30.0, vertical: 10.0),
child: Padding(
padding: EdgeInsets.only(left: 5.0, right: 5.0, top: 5.0),
child: SizedBox(
/*height: _animation.value,*/
child: TextFormField(
decoration: InputDecoration(
labelText: 'Email',
border: OutlineInputBorder(borderRadius: BorderRadius.all(
const Radius.circular(10.0),
)
),
filled: true,
fillColor: Colors.white,
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: color, width: 2.0),
borderRadius: BorderRadius.circular(10.0)
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: color, width: 2.0),
borderRadius: BorderRadius.circular(10.0)
)
),
// focusNode: _focusNode,
validator: (input) => !EmailValidator.validate(input!, true) ? 'Please provide valid email':null,
onSaved: (input) => _email = input!,
),
),
),
),
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 30.0, vertical: 10.0
),
child: Padding(
padding: const EdgeInsets.only(left: 5, right: 5, top: 5, bottom: 5),
child: Stack(
alignment: const Alignment(0, 0),
children: <Widget>[
TextFormField(
decoration: InputDecoration(
labelText: 'Password',
border: OutlineInputBorder(
borderRadius: BorderRadius.all(
const Radius.circular(10.0)
)
),
filled: true,
fillColor: Colors.white,
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: color, width: 2.0),
borderRadius: BorderRadius.circular(10.0)
),
suffixIcon: IconButton(
onPressed: (){
_toggle();
},
icon: Icon(_obscureText ? Icons.visibility : Icons.visibility_off)
)
),
validator: (input) => input!.length < 6
? 'Must be at least 6 characters': null,
onSaved: (input) => _password = input!,
obscureText: _obscureText,
)
],
),
),
),
],
),
)
],
),
),
),
);
In short I have added the bool variable and function as below. After that in onPressed of login Button I called _hideWidget().
bool _canShowButton = true;
_hideWidget(){
setState(() {
_canShowButton = !_canShowButton;
});
Padding(
padding: const EdgeInsets.only(top: 10),
child: Container(
width: MediaQuery.of(context).size.width - 70,
height: MediaQuery.of(context).size.height * 0.09,
child: !_canShowButton ? SizedBox.shrink() : TextButton(
style: TextButton.styleFrom(
primary: Colors.white,
backgroundColor: color,
elevation: 5,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10.0))
),
onPressed: () {
_hideWidget();
},
child: Text('Anmelden')),
),
),
What I have achieved is: The Login Button is there on the page and when I click on TextFormField it gets disappear.
Want to achieve: Login Button should be invisible on the screen and when user enters the credentials after that it should appear.
Is there any way to achieve this??
This is how you can tell if there's data in the textfield or not, if there is it'll change isFilled to true.
bool isFilled = false;
TextFormField(
onChanged: (val) {
setState(() {
(val.isEmpty) ? isFilled = false : isFilled = true;
});
},
)
Now to show the button when there's data in the textfield you can use ternary operator.
(isFilled)?TextButton(onPressed: (){}, child: Container()) : Container()
Just switch TextButton with your button. Ternary operators work like so
(condition) ? (do if true) : (do if false)
in this case, you're showing the button if isFilled = true, and an empty container if not
Well the simplest way of implementing this is to add a TextEdittingController to each Textfield and then render the button only when the TextEdittingController.tex is not empty,when it's empty you can render an empty container otherwise render the button,use a simple tenary operator to do this

How to share data between two widgets by using Provider?

I have two widgets which I shared codes below, In first card widget for user selecting ingredients, second card will be used for displaying selected ingrediens, initial both screen will be empty, when user add an igredients both widget will be rebuilt by according to selected ingredients, I could handle it displaying in first widget, but I can not handle to display selectedIngredient list data when it changes, I know I have to use provider packages but I could not implement for my code, I have stuck please help me.. .
class AddIngredientsCard extends StatefulWidget {
AddIngredientsCard({this.subCategoryId,this.subCategoryCardId});
final int subCategoryCardId;
final int subCategoryId;
#override
_AddIngredientsCardState createState() => _AddIngredientsCardState();
}
class _AddIngredientsCardState extends State<AddIngredientsCard>{
String textValue;
double _animatedContainerHeight=350;
double _top=15;
double _right=30;
double _left=30;
double _bottom=15;
List<String> items= [];
List<String>selectedIngredients=[];
#override
void initState() {
ingredients=ingredients..sort((String a, String b)=>a.compareTo(b));
items.addAll(ingredients);
super.initState();
}
void filterSearchResults(String query) {
List<String> searchList = [];
searchList.addAll(ingredients);
if(query.isNotEmpty) {
List<String> listData = [];
searchList.forEach((item) {
if(item.contains(query)) {
listData.add(item);
}
});
setState(() {
items.clear();
items.addAll(listData);
});
return;
} else {
setState(() {
items.clear();
items.addAll(ingredients);
});
}
}
void _toggleCardSize(){
_top==15?_top=7.5: _top=15;
_right==30?_right=7.5: _right=30;
_left==30?_left=7.5: _left=30;
_bottom==15?_bottom=7.5: _bottom=15;
}
void _toggleCardHeight(){
_animatedContainerHeight==350?_animatedContainerHeight=600:_animatedContainerHeight=350;
}
#override
Widget build(BuildContext context) {
return AnimatedPadding(
duration: Duration(milliseconds: 500),
curve: Curves.linearToEaseOut,
padding:EdgeInsets.only(top: _top,right: _right,left: _left,bottom: _bottom),
child: AnimatedContainer(
height:_animatedContainerHeight,
duration: Duration(milliseconds: 500),
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
decoration: BoxDecoration(
border:Border.all(style: BorderStyle.solid, width: 1),
color: Colors.white,
borderRadius: BorderRadius.circular(90),
),
height: 60,
child: TextField(
style: TextStyle(
color: Colors.black,
fontFamily:"OpenSans",
fontSize: 20,
),
textAlign: TextAlign.center,
textAlignVertical: TextAlignVertical.center,
onChanged: (value){
if(value.length>0){
value=value[0].toUpperCase()+value.substring(1);
filterSearchResults(value);
}
else{
filterSearchResults(value);
}
},
decoration: InputDecoration(
prefixIcon: Icon(Icons.search),
border:OutlineInputBorder(
borderRadius: BorderRadius.circular(90),
borderSide: BorderSide(
color: kColorTheme10,
),
),
hintText: "Malzeme ismi arayın",
hintStyle: TextStyle(
color: Colors.black.withOpacity(0.5),
fontFamily: "OpenSans",
),
),
),
),
SizedBox(height: 2,),
Expanded(
flex: _animatedContainerHeight==350?1:4,
child: ListView.builder(
scrollDirection: Axis.horizontal,
shrinkWrap: true,
itemCount: selectedIngredients.length,
itemBuilder: (context,index){
return Padding(
padding: EdgeInsets.all(1),
child: GestureDetector(
onTap: (){
setState(() {
selectedIngredients.removeAt(index);
if (selectedIngredients.length == 0) {
_toggleCardHeight();
_toggleCardSize();
}
}
);
},
child: Container(
decoration: BoxDecoration(
color: kColorTheme11,
borderRadius: BorderRadius.circular(90),
border: Border.all(style: BorderStyle.solid,width: 1),
),
child: Padding(
padding: EdgeInsets.all(8.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
BorderedText(strokeColor: Colors.black,strokeWidth: 5,child: Text(selectedIngredients[index],style:
TextStyle(fontWeight: FontWeight.bold,fontSize:20,color: Colors.white),)),
SizedBox(width: 5,),
Icon(
Icons.cancel,color: Colors.white,size: 20,
),
],
),
),
),
),
);
}
),
),
SizedBox(height: 2,),
Expanded(
flex: 40,
child: ListView.builder(
shrinkWrap: true,
itemCount: items.length,
itemBuilder: (context, index) {
return Padding(
padding: EdgeInsets.all(2.0),
child: GestureDetector(
onTap: (){
setState(() {
if(selectedIngredients.length==0){
selectedIngredients.add("${items[index]}");
_toggleCardHeight();
_toggleCardSize();
}
else{
selectedIngredients.add("${items[index]}");
}
});
},
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(90),
border: Border.all(style:BorderStyle.solid,width: 1),
color: Colors.white54,
),
child: Padding(
padding: EdgeInsets.all(5),
child: Text('${items[index]}',style: TextStyle(fontWeight: FontWeight.bold),)),
),
),
);
},
),
),
SizedBox(height: 8,),
Expanded(
flex: _animatedContainerHeight==350?1:4,
child: Row(
children: [
Expanded(
child: Container(
decoration: BoxDecoration(
color: _animatedContainerHeight==350?categoryModels[widget.subCategoryId].
subCategoryModels[widget.subCategoryCardId].categoryColor.withOpacity(0.1):kColorTheme11,
borderRadius: BorderRadius.circular(20),
border: _animatedContainerHeight==350?null:
Border.all(style: BorderStyle.solid,width: 2),
),
child: Padding(
padding: EdgeInsets.all(5),
child: GestureDetector(
onTap: (){
AddIngredientsAmount(subCategoryId:widget.subCategoryId,subCategoryCardId: widget.subCategoryId,selectedIngredients: selectedIngredients,);
/////////////////////////////////////// => isPageSaved için Provider eklenecek...
},
child: Center(child: BorderedText(strokeWidth:3,strokeColor: Colors.black,child:
Text("KAYDET",style: TextStyle(fontSize: 25, fontWeight: FontWeight.w900 ,color: Colors.white))),
),
),
),
)
),
],
),
),
],
),
),
decoration: BoxDecoration(
border: Border.all(style: BorderStyle.solid, width: 1),
borderRadius: BorderRadius.circular(30),
color:categoryModels[widget.subCategoryId].subCategoryModels[widget.subCategoryCardId].categoryColor.withOpacity(0.5),
)
),
);
}
}
class AddIngredientsAmount extends StatefulWidget {
AddIngredientsAmount({this.subCategoryId,this.subCategoryCardId, this.selectedIngredients});
final List selectedIngredients;
final int subCategoryCardId;
final int subCategoryId;
#override
_AddIngredientsAmountState createState() => _AddIngredientsAmountState();
}
class _AddIngredientsAmountState extends State<AddIngredientsAmount> {
String textValue;
double _animatedContainerHeight=300;
double _top=15;
double _right=30;
double _left=30;
double _bottom=15;
#override
Widget build(BuildContext context) {
void _toggleCardSize(){
_top==15?_top=7.5: _top=15;
_right==30?_right=7.5: _right=30;
_left==30?_left=7.5: _left=30;
_bottom==15?_bottom=7.5: _bottom=15;
}
void _toggleCardHeight(){
_animatedContainerHeight==300?_animatedContainerHeight=500:_animatedContainerHeight=300;
}
return AnimatedPadding(
duration: Duration(milliseconds: 500),
curve: Curves.linearToEaseOut,
padding:EdgeInsets.only(top: _top,right: _right,left: _left,bottom: _bottom),
child: GestureDetector(
onTap: (){
setState(() {
_toggleCardHeight();
_toggleCardSize();
});
},
child: AnimatedContainer(
height:_animatedContainerHeight,
duration: Duration(milliseconds: 500),
child: Padding(
padding: EdgeInsets.all(15.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(
decoration: BoxDecoration(
border:Border.all(style: BorderStyle.solid, width: 1),
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(90))),
child: Center(
child: Text("Malzemelerinizin Miktarını Belirlerin",style: TextStyle(
color: Colors.black,
fontFamily:'OpenSans',
fontSize:25,
fontWeight: FontWeight.w300,
),
),
),
),
SizedBox(height: 7.5,),
Expanded(
child: Container(
decoration: BoxDecoration(
color:Colors.white,
border: Border.all(style: BorderStyle.solid, width: 1),
borderRadius: BorderRadius.circular(10),
),
child: ListView.builder(
itemCount: widget.selectedIngredients.length==null?0:
widget.selectedIngredients.length,
itemBuilder: (context, index){
return Padding(
padding: EdgeInsets.all(2),
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(90),
border: Border.all(style:BorderStyle.solid,width: 1),
color: Colors.white54,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(
padding: EdgeInsets.all(5),
child: Text('${widget.selectedIngredients[index]}',style: TextStyle(fontWeight: FontWeight.bold,fontSize: 30),)),
],
),
),
);
},
),
),
),
],
),
),
decoration: BoxDecoration(
border: Border.all(style: BorderStyle.solid, width: 1),
borderRadius: BorderRadius.circular(30),
color:categoryModels[widget.subCategoryId].subCategoryModels[widget.subCategoryCardId].categoryColor.withOpacity(0.5),
)
)
),
);
}
}
//------------------------------------------------------------------------
class AddRecipeVoice extends StatefulWidget {
AddRecipeVoice({this.subCategoryId,this.subCategoryCardId});
final int subCategoryCardId;
final int subCategoryId;
#override
_AddRecipeVoiceState createState() => _AddRecipeVoiceState();
}
class _AddRecipeVoiceState extends State<AddRecipeVoice> {
String textValue;
#override
Widget build(BuildContext context) {
return AnimatedPadding(
duration: Duration(seconds: 1),
curve: Curves.linearToEaseOut,
padding:EdgeInsets.only(top: 15,left: 30,right: 30,bottom: 7.5),
child: GestureDetector(
onTap: (){
setState(() {
});
},
child: Container(
height:130,
child: Padding(
padding: EdgeInsets.all(15.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(
decoration: BoxDecoration(
border:Border.all(style: BorderStyle.solid, width: 1),
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(90))),
child: Center(
child: Text("Tarifinizi anlatın",style: TextStyle(
color: Colors.black,
fontFamily:'OpenSans',
fontSize:25,
fontWeight: FontWeight.w300,
),
),
),
),
SizedBox(height: 7.5,),
Expanded(
child: GestureDetector(
child: Container(
decoration: BoxDecoration(
color:kColorTheme7,
border: Border.all(style: BorderStyle.solid, width: 1),
borderRadius: BorderRadius.circular(20),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Icon(Icons.mic,size: 40,color: Colors.white,),
SizedBox(width: 50,),
Text(
"KAYIT ZAMANI !!",
style: TextStyle(
fontSize: 30,
fontFamily: "OpenSans",
color: Colors.white,
fontWeight: FontWeight.bold
),
),
],
),
),
),
),
],
),
),
decoration: BoxDecoration(
border: Border.all(style: BorderStyle.solid, width: 1),
borderRadius: BorderRadius.circular(30),
color:categoryModels[widget.subCategoryId].subCategoryModels[widget.subCategoryCardId].categoryColor.withOpacity(0.5),
)
)
),
);
}
}
Make a provider class that mixin with ChangeNotifier.
Wrap your widget prior calling the provider class with MultiProvider widget. Likewise:
MultiProvider (
providers: [
ChangeNotifierProvider.value(value: IngredientsProvider()),
],
child: YourWidget(), //You can wrap your MaterialApp here
)
Create your needed methods that changes the selected data and call notifyListeners() inside your method. It will rebuild your desired widget where you listen to them.
Example:
class IngredientsProvider with ChangeNotifier {
List<String> _selectedIngredients = [];
List<String> get selectedIngredients() {
return _selectedIngredients;
}
void addIngredient(String ingredient) {
_selectedIngredients.add(ingredient);
notifyListeners();
}
}
In your widget listen to them:
Widget1 {
//Call this in you onPress/onTap
void addIngredient(String ing, BuildContext ctx) {
Provider.of<IngredientsProvider>(ctx, listen:
false).addIngredient(ing);
}
........
#override
Widget build(BuildContext context) {
//Use this list to select
List<String> _ingredients = Provider.of<IngredientsProvider>(context, listen:
true).ingredients;
}
........
}
Use in the 2nd Widget in this way.
Widget2 {
........
#override
Widget build(BuildContext context) {
//Use this list to show
List<String> _ingredients = Provider.of<IngredientsProvider>(context, listen:
true).ingredients;
}
........
}

Nested Gesture Does not change on Tap

I am currently working on the ui stuff for the appliction, so the thing is i have one gesture as a parent that swipes up and down and based on it the position of the widgets gets changed but the problem is the child gesture does not get any precedence when tapped on it it gives the precedence. So my tree structure is Pageview.builder which has single widget with topmost parent as Gesturedetector and the children accrodingly, Can any one tell me what i am doing wrong or any improvements to get the gesture for each.
Below is the sample code that i have been working on:
import 'dart:math';
import 'package:LocationAnimation/Model/device_model.dart';
import 'package:LocationAnimation/SplashPage/splash_page.dart';
import 'package:LocationAnimation/widgets/device_function_widget.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:google_fonts/google_fonts.dart';
import 'Model/device_model.dart' as devices;
import 'Model/locations_model.dart' as locations;
import 'extensions/capitalize.dart';
void main() {
runApp(new MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'HAL',
home: MyHomePage(),
);
}
}
class SampleList {
final String locationName;
SampleList({this.locationName});
}
class MyHomePage extends StatefulWidget {
#override
State createState() => new MyHomePageState();
}
class MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
final _controller = new PageController();
final _kArrowColor = Colors.black.withOpacity(0.8);
bool _isSwipe = false;
bool _isLoading = false;
var list = [
SampleList(locationName: 'Living Room'),
SampleList(locationName: 'Bed Room'),
SampleList(locationName: 'Back Porch Lights'),
SampleList(locationName: 'Basement Porch Lights'),
SampleList(locationName: 'Sample Room'),
];
#override
Widget build(BuildContext context) {
return new Scaffold(
body: new IconTheme(
data: new IconThemeData(color: _kArrowColor),
child: new Stack(
children: <Widget>[
new PageView.builder(
physics: _isSwipe
? NeverScrollableScrollPhysics()
: AlwaysScrollableScrollPhysics(),
controller: _controller,
itemCount: list.length,
itemBuilder: (BuildContext context, int index) {
return LocationDetails(
isLoading: _isLoading,
item: list[index],
onSwipeDown: () {
setState(() {
_isSwipe = false;
});
},
onSwipeUp: () {
setState(() {
_isSwipe = true;
});
},
);
},
),
],
),
),
);
}
}
class LocationDetails extends StatefulWidget {
final bool isLoading;
SampleList item;
final Function() onSwipeUp;
final Function() onSwipeDown;
LocationDetails(
{Key key, this.item, this.onSwipeUp, this.onSwipeDown, this.isLoading})
: super(key: key);
#override
_LocationDetailsState createState() => _LocationDetailsState();
}
class _LocationDetailsState extends State<LocationDetails> {
DragStartDetails startVerticalDragDetails;
DragUpdateDetails updateVerticalDragDetails;
bool moveWidget = false;
bool dismissSwipeText = true;
bool _isRotate = false;
int currentSelectedIndex = 0;
bool ignoreChildGestures = true;
bool _isSwpie = false;
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Container(
child: GestureDetector(
onTap: () {
print('Tap');
},
onVerticalDragStart: (dragDetails) {
startVerticalDragDetails = dragDetails;
},
onVerticalDragUpdate: (dragDetails) {
updateVerticalDragDetails = dragDetails;
},
onVerticalDragEnd: (endDetails) {
double dx = updateVerticalDragDetails.globalPosition.dx -
startVerticalDragDetails.globalPosition.dx;
double dy = updateVerticalDragDetails.globalPosition.dy -
startVerticalDragDetails.globalPosition.dy;
double velocity = endDetails.primaryVelocity;
//Convert values to be positive
if (dx < 0) dx = -dx;
if (dy < 0) dy = -dy;
if (velocity < 0) {
widget.onSwipeUp();
print('drag up');
setState(() {
moveWidget = true;
_isSwpie = true;
});
} else {
widget.onSwipeDown();
print(' drag down');
setState(() {
moveWidget = false;
_isSwpie = false;
});
}
},
child: Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
decoration: new BoxDecoration(
image: new DecorationImage(
colorFilter: ColorFilter.mode(
Colors.black.withOpacity(0.8), BlendMode.srcOver),
image: /* moveWidget
? */
AssetImage(
'Assets/backgroundImage.jpg',
),
/* : NetworkImage(widget.samplePage.networkImage), */
fit: BoxFit.fill,
),
),
child:
/* widget.isLoading
? Center(
child: CircularProgressIndicator(),
)
: */
Stack(
children: <Widget>[
AnimatedOpacity(
opacity: moveWidget ? 0 : 1,
duration: Duration(microseconds: 100),
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Column(
children: <Widget>[
Icon(
Icons.power_settings_new,
color: Colors.white,
size: 30,
),
Icon(
Icons.more_horiz,
color: Colors.white,
size: 25,
)
],
),
Row(
children: <Widget>[
Column(
children: <Widget>[
Text(
'Inside Temp',
style: TextStyle(
color: Colors.white, fontSize: 18),
),
SizedBox(
height: 5,
),
Row(
children: <Widget>[
Icon(
Icons.ac_unit,
color: Colors.white,
size: 20,
),
SizedBox(
width: 10,
),
Text(
'19 C',
style: TextStyle(color: Colors.white),
),
],
)
],
),
SizedBox(
width: 10,
),
Column(
children: <Widget>[
Text(
'Outside Temp',
style: TextStyle(
color: Colors.white, fontSize: 18),
),
SizedBox(
height: 5,
),
Row(
children: <Widget>[
Icon(
Icons.ac_unit,
color: Colors.white,
size: 20,
),
SizedBox(
width: 10,
),
Text(
'19 C',
style: TextStyle(color: Colors.white),
),
],
)
],
),
],
)
],
),
),
),
AnimatedPositioned(
onEnd: () {
setState(() {
dismissSwipeText = !dismissSwipeText;
//print(dismissSwipeText);
});
},
curve: Curves.ease,
duration: Duration(milliseconds: 700),
bottom: moveWidget
? 10
: MediaQuery.of(context).size.height * 0.18,
left: 10.0,
right: 0.0,
top: moveWidget
? 50
: MediaQuery.of(context).size.height * 0.75,
child: AnimatedOpacity(
opacity: dismissSwipeText ? 1 : 0,
duration: Duration(milliseconds: 500),
child: Text(
'Swipe up to customize',
style: TextStyle(color: Colors.white, fontSize: 20),
),
),
),
AnimatedPositioned(
curve: Curves.ease,
duration: Duration(milliseconds: 700),
onEnd: () {
setState(() {
_isSwpie = true;
});
},
left: 10,
top: moveWidget
? 80
: MediaQuery.of(context).size.height * 0.80,
child: Container(
width: MediaQuery.of(context).size.width * 0.97,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
GestureDetector(
onTap: () {
setState(() {
currentSelectedIndex = 0;
});
},
child: Container(
width: MediaQuery.of(context).size.width * 0.20,
height:
MediaQuery.of(context).size.height * 0.10,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: currentSelectedIndex == 0
? Colors.blue
: Colors.grey[900],
),
child: Center(
child: Text(
'Lights',
style: GoogleFonts.lato(
color: Colors.white,
fontWeight: FontWeight.w700),
)),
),
),
Row(
children: <Widget>[
SizedBox(
width: 10,
),
GestureDetector(
onTap: () {
setState(() {
currentSelectedIndex = 1;
});
},
child: Container(
width: MediaQuery.of(context).size.width *
0.20,
height: MediaQuery.of(context).size.height *
0.10,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: currentSelectedIndex == 1
? Colors.blue
: Colors.grey[900],
),
child: Center(
child: Text(
'Applicanes',
style: GoogleFonts.lato(
color: Colors.white,
fontWeight: FontWeight.w700),
)),
),
),
],
),
Row(
children: <Widget>[
SizedBox(
width: 10,
),
GestureDetector(
onTap: () {
setState(() {
currentSelectedIndex = 2;
});
},
child: Container(
width: MediaQuery.of(context).size.width *
0.20,
height: MediaQuery.of(context).size.height *
0.10,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: currentSelectedIndex == 2
? Colors.blue
: Colors.grey[900],
),
child: Center(
child: Text(
'Sensors',
style: GoogleFonts.lato(
color: Colors.white,
fontWeight: FontWeight.w700),
)),
),
),
],
),
Row(
children: <Widget>[
SizedBox(
width: 10,
),
Container(
width:
MediaQuery.of(context).size.width * 0.20,
height:
MediaQuery.of(context).size.height * 0.10,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.grey[900],
),
child: Center(
child: Text(
'Doors \n& Locks',
style: GoogleFonts.lato(
color: Colors.white,
fontWeight: FontWeight.w700),
)),
),
],
),
SizedBox(
width: 10,
),
],
),
),
),
AnimatedPositioned(
curve: Curves.ease,
duration: Duration(milliseconds: 400),
bottom: moveWidget
? 10
: MediaQuery.of(context).size.height * 0.20,
left: 10.0,
right: 0.0,
top: moveWidget
? 15
: MediaQuery.of(context).size.height * 0.70,
child: Text(
'${widget.item.locationName}',
style: TextStyle(fontSize: 30, color: Colors.white),
),
),
],
)),
),
),
),
);
}
}
You can add Color to the last AnimatedPositioned which use text widget.item.locationName in your code, like:
AnimatedPositioned(
curve: Curves.ease,
duration: Duration(milliseconds: 400),
bottom: moveWidget
? 10
: MediaQuery.of(context).size.height * 0.20,
left: 10.0,
right: 0.0,
top: moveWidget
? 15
: MediaQuery.of(context).size.height * 0.70,
child: Container(
color: Colors.white,
Text(
'${widget.item.locationName}',
style: TextStyle(fontSize: 30, color: Colors.white),
),
),
),
You will see a white screen (the widget which blocking you) when you scroll up. You can fix it by 2 ways
Change the bottom 10 to a larger number
Move this part of AnimatedPositioned to Top of the Stack widget
The Nested Gesture should work probably as you expected.
First of All you are using multiple Scaffold in a single page which is not recommended.
And remove the unwanted widgets from your tree which will help you to debug a way more better level. And Next you can try with passing a Callback function from parent to child which can eventually solve your problem

How to show a Count down Timer within and Alertbox in flutter

i have a Flutter app which should show a counting down timer in an alert box for Phone code confirming (i need this timer to resend the code to my user when 60 second is up) , i start timer when i click on Confirm Button , but the problem is that the timer is not showing that he's going down he stills with a fixed value.
here is my alert box
Alert Box with timer NOT SHOWING COUNT DOWN
here is my timer Function :
int _counter = 60;
Timer _timer;
void _startTimer(){
_counter = 60;
if(_timer != null){
_timer.cancel();
}
_timer = Timer.periodic(Duration(seconds: 1), (timer){
setState(() {
(_counter > 0) ? _counter-- : _timer.cancel();
});
});
}
here is my alert Box code :
void alertD(BuildContext ctx) {
var alert = AlertDialog(
// title: Center(child:Text('Enter Code')),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(20.0))),
backgroundColor: Colors.grey[100],
elevation: 0.0,
content: Container(
height: 215,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(
top: 10, left: 10, right: 10, bottom: 15),
child: Text(
'Enter Code',
style: TextStyle(
color: Colors.green[800],
fontWeight: FontWeight.bold,
fontSize: 16
),
)),
Container(
height: 70,
width: 180,
child: TextFormField(
style: TextStyle(fontSize: 20,fontWeight: FontWeight.bold),
textAlign: TextAlign.center,
decoration: InputDecoration(
enabledBorder: OutlineInputBorder(
borderSide:
BorderSide(color: Colors.green, width: 0.0)),
),
keyboardType: TextInputType.number,
maxLength: 10,
),
),
SizedBox(
height: 1,
),
Text('00:$_counter'),
SizedBox(height: 15,)
,
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
ClipRRect(
borderRadius: BorderRadius.circular(25),
child: Material(
child: InkWell(
onTap: () {
Navigator.of(ctx).pushNamed(SignUpScreenSecond.routeName);
},
child: Container(
width: 100,
height: 50,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25),
gradient: LinearGradient(
colors: [
Colors.green,
Colors.grey,
],
begin: Alignment.topLeft,
end: Alignment.bottomRight),
),
child: Center(
child: Text(
'Validate',
style: TextStyle(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.bold),
)),
),
),
),
),
ClipRRect(
borderRadius: BorderRadius.circular(25),
child: Material(
child: InkWell(
onTap: () {},
child: Container(
width: 100,
height: 50,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25),
gradient: LinearGradient(
colors: [
Colors.grey,
Colors.green,
],
begin: Alignment.topLeft,
end: Alignment.bottomRight),
),
child: Center(
child: Text(
'Resend',
style: TextStyle(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.bold),
)),
),
),
),
)
],
), //new column child
],
),
));
showDialog(
context: ctx,
builder: (BuildContext c) {
return alert;
});
}
that's how i'm calling my alert dialog and my timer when i click Confirm Button :
onTap: () {
_startTimer;
alertD(context);
},
You can copy paste run full code below
You can use StreamBuilder and StreamController
AlertDialog content continually receive stream int from Timer
code snippet
StreamController<int> _events;
#override
initState() {
super.initState();
_events = new StreamController<int>();
_events.add(60);
}
...
_timer = Timer.periodic(Duration(seconds: 1), (timer) {
(_counter > 0) ? _counter-- : _timer.cancel();
print(_counter);
_events.add(_counter);
});
...
content: StreamBuilder<int>(
stream: _events.stream,
builder: (BuildContext context, AsyncSnapshot<int> snapshot) {
...
Text('00:${snapshot.data.toString()}'),
working demo
full code
import 'package:flutter/material.dart';
import 'dart:async';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
StreamController<int> _events;
#override
initState() {
super.initState();
_events = new StreamController<int>();
_events.add(60);
}
Timer _timer;
void _startTimer() {
_counter = 60;
if (_timer != null) {
_timer.cancel();
}
_timer = Timer.periodic(Duration(seconds: 1), (timer) {
//setState(() {
(_counter > 0) ? _counter-- : _timer.cancel();
//});
print(_counter);
_events.add(_counter);
});
}
void alertD(BuildContext ctx) {
var alert = AlertDialog(
// title: Center(child:Text('Enter Code')),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(20.0))),
backgroundColor: Colors.grey[100],
elevation: 0.0,
content: StreamBuilder<int>(
stream: _events.stream,
builder: (BuildContext context, AsyncSnapshot<int> snapshot) {
print(snapshot.data.toString());
return Container(
height: 215,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(
top: 10, left: 10, right: 10, bottom: 15),
child: Text(
'Enter Code',
style: TextStyle(
color: Colors.green[800],
fontWeight: FontWeight.bold,
fontSize: 16),
)),
Container(
height: 70,
width: 180,
child: TextFormField(
style: TextStyle(
fontSize: 20, fontWeight: FontWeight.bold),
textAlign: TextAlign.center,
decoration: InputDecoration(
enabledBorder: OutlineInputBorder(
borderSide:
BorderSide(color: Colors.green, width: 0.0)),
),
keyboardType: TextInputType.number,
maxLength: 10,
),
),
SizedBox(
height: 1,
),
Text('00:${snapshot.data.toString()}'),
SizedBox(
height: 15,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
ClipRRect(
borderRadius: BorderRadius.circular(25),
child: Material(
child: InkWell(
onTap: () {
//Navigator.of(ctx).pushNamed(SignUpScreenSecond.routeName);
},
child: Container(
width: 100,
height: 50,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25),
gradient: LinearGradient(
colors: [
Colors.green,
Colors.grey,
],
begin: Alignment.topLeft,
end: Alignment.bottomRight),
),
child: Center(
child: Text(
'Validate',
style: TextStyle(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.bold),
)),
),
),
),
),
ClipRRect(
borderRadius: BorderRadius.circular(25),
child: Material(
child: InkWell(
onTap: () {},
child: Container(
width: 100,
height: 50,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25),
gradient: LinearGradient(
colors: [
Colors.grey,
Colors.green,
],
begin: Alignment.topLeft,
end: Alignment.bottomRight),
),
child: Center(
child: Text(
'Resend',
style: TextStyle(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.bold),
)),
),
),
),
)
],
), //new column child
],
),
);
}));
showDialog(
context: ctx,
builder: (BuildContext c) {
return alert;
});
}
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
onPressed: () {
_startTimer();
alertD(context);
},
child: Text('Click')),
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}

how to keep list values even after AlertDialog disappear

I made a list in my stateful widget class that is going to be filled with some values when the user selects cards, I have a showDialog function on a button in my app that every time it is clicked a form will be shown to the user.
the problem is after the user come back from the form by clicking on the Ok button the stateful class will be recreated and clean up all my list's values (the ActivityPeopleCard class called again)... how to keep the value of the list even after coming back from showDialog form?
class ActivityPeopleCard extends StatefulWidget{
Activity activity;
List<double> _cost ;
ActivityPeopleCard({this.activity});
#override
_ActivityPeopleCardState createState() => _ActivityPeopleCardState();
}
class _ActivityPeopleCardState extends State<ActivityPeopleCard> {
int _peopleIndex = -1;
List<int> _peopleIndexes = new List();
List<int> _longPressed = new List();
#override
Widget build(BuildContext context) {
return Container(
height: height/2.6,
child:new GridView.builder(
itemCount: widget.activity.peopleInvolved.length,
gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3),
itemBuilder: (BuildContext context, int index) {
return new GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: ()=> setState(() => {
}
),
child: _buildWidget(index, context)
);
},
),
);
}
_buildWidget(int index, BuildContext context){
bool isSelected = _peopleIndexes.contains(index)?true:false;
return new Card(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(30)),
elevation: 5.0,
child: Stack(
children:<Widget>[
new Container(
height: height/4,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
width:height/15,
height: height/15,
decoration: new BoxDecoration(
borderRadius: BorderRadius.circular(height/20),
border: Border.all(color: Colors.white, width:2),
),
child: ClipRRect(
borderRadius: BorderRadius.circular(height/15),
child: Image.asset(widget.activity.peopleInvolved[index].imagePath, fit: BoxFit.fill)),//CircleAvatar(
),
Center(child: Text(widget.activity.peopleInvolved[index].name))
],
),
),
shareTag(index, isSelected, context)
])
);
}
shareTag(index, isSelected, BuildContext context){
return GestureDetector(
onLongPress: ()=>{
enterPrice(index, context),
},
child: Visibility(
visible: isSelected ? true:false,
child: new Container(
height: height/2,
decoration: new BoxDecoration(
borderRadius: BorderRadius.circular(height/20),
color: Colors.red.shade500.withOpacity(0.7),
),
child: Center(child: SizedBox(
width: width/4,
height: height/15,
child:Center(child: AutoSizeText("\$${ActivityPeopleCard._cost[index]}", style:TextStyle(fontWeight: FontWeight.bold,color: Colors.white,fontFamily: 'Oxygen',fontSize: height/25),
maxLines: 1,minFontSize: 5,textAlign: TextAlign.center,),
),
))),
)
);
}
enterPrice(int index, BuildContext context){
//print("Long Pressed");
showDialog(
context: context,
builder: (context) {
return AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(25)
),
backgroundColor: Colors.white,
content: Form(
//key: _formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
new TextFormField(
initialValue: ActivityPeopleCard._cost[index].toString(),
keyboardType: TextInputType.number,
cursorColor: secondColor,
style: TextStyle(letterSpacing: 1,),
autofocus: true,
decoration: new InputDecoration(
focusedBorder: new OutlineInputBorder(
borderRadius: new BorderRadius.circular(15.0),
borderSide: new BorderSide(
color: secondColor
)),
labelStyle: TextStyle(
color: firstColor
//decorationColor: Colors.yellow
),
prefixIcon: Icon(Icons.attach_money, color: firstColor,),
labelText: "Cost",
border: new OutlineInputBorder(
borderRadius: new BorderRadius.circular(15.0),
borderSide: new BorderSide(
color: Colors.black87
),
),
),
),
],
),
),
);
});
}
}
after the user come back from the form the _cost list will be initialized again with null and shows null values instead of previous values
Create a variable in your initial state that returns your Container. Then in your build method return your variable. This will stop the list refreshing/resetting every time the build method is called
class ActivityPeopleCard extends StatefulWidget {
Activity activity;
List<double> _cost;
ActivityPeopleCard({this.activity});
#override
_ActivityPeopleCardState createState() => _ActivityPeopleCardState();
}
class _ActivityPeopleCardState extends State<ActivityPeopleCard> {
int _peopleIndex = -1;
List<int> _peopleIndexes = new List();
List<int> _longPressed = new List();
var _vlContainer;
#override
void initState() {
super.initState();
_vlContainer = myListContainer();
}
#override
Widget build(BuildContext context) {
return _vlContainer;
}
myListContainer() {
return Container(
height: height / 2.6,
child: new GridView.builder(
itemCount: widget.activity.peopleInvolved.length,
gridDelegate:
new SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3),
itemBuilder: (BuildContext context, int index) {
return new GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () => setState(() => {}),
child: _buildWidget(index, context));
},
),
);
}
_buildWidget(int index, BuildContext context) {
bool isSelected = _peopleIndexes.contains(index) ? true : false;
return new Card(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(30)),
elevation: 5.0,
child: Stack(children: <Widget>[
new Container(
height: height / 4,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
width: height / 15,
height: height / 15,
decoration: new BoxDecoration(
borderRadius: BorderRadius.circular(height / 20),
border: Border.all(color: Colors.white, width: 2),
),
child: ClipRRect(
borderRadius: BorderRadius.circular(height / 15),
child: Image.asset(
widget.activity.peopleInvolved[index].imagePath,
fit: BoxFit.fill)), //CircleAvatar(
),
Center(child: Text(widget.activity.peopleInvolved[index].name))
],
),
),
shareTag(index, isSelected, context)
]));
}
shareTag(index, isSelected, BuildContext context) {
return GestureDetector(
onLongPress: () => {
enterPrice(index, context),
},
child: Visibility(
visible: isSelected ? true : false,
child: new Container(
height: height / 2,
decoration: new BoxDecoration(
borderRadius: BorderRadius.circular(height / 20),
color: Colors.red.shade500.withOpacity(0.7),
),
child: Center(
child: SizedBox(
width: width / 4,
height: height / 15,
child: Center(
child: AutoSizeText(
"\$${ActivityPeopleCard._cost[index]}",
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.white,
fontFamily: 'Oxygen',
fontSize: height / 25),
maxLines: 1,
minFontSize: 5,
textAlign: TextAlign.center,
),
),
))),
));
}
enterPrice(int index, BuildContext context) {
//print("Long Pressed");
showDialog(
context: context,
builder: (context) {
return AlertDialog(
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(25)),
backgroundColor: Colors.white,
content: Form(
//key: _formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
new TextFormField(
initialValue: ActivityPeopleCard._cost[index].toString(),
keyboardType: TextInputType.number,
cursorColor: secondColor,
style: TextStyle(
letterSpacing: 1,
),
autofocus: true,
decoration: new InputDecoration(
focusedBorder: new OutlineInputBorder(
borderRadius: new BorderRadius.circular(15.0),
borderSide: new BorderSide(color: secondColor)),
labelStyle: TextStyle(color: firstColor
//decorationColor: Colors.yellow
),
prefixIcon: Icon(
Icons.attach_money,
color: firstColor,
),
labelText: "Cost",
border: new OutlineInputBorder(
borderRadius: new BorderRadius.circular(15.0),
borderSide: new BorderSide(color: Colors.black87),
),
),
),
],
),
),
);
});
}
}

Categories

Resources