I have a Bottom Sheet which has sets of buttons. I use the buttons to change the value of pinString and a text to show the pinString. The value of the text does not update when button is clicked. How to fix this
showNumberPad(BuildContext context) {
showModalBottomSheet(
context: context,
builder: (context) {
return StatefulBuilder(builder: (context, setState) {
return Container(
height: 550.0,
child: Column(
children: <Widget>[
Text(
"$pinString",
),
KeyboardNumber(
n: 1,
onPressed: () {
pinIndexSetup("1");
setState1() {
pinString = "New Pin";
}
},
),
],
),
);
});
},
);
}
KeyboardNumber is a custom Stateful widget where I want to pass the onPressed as a parameter.
Code for keyboardNumber:
class KeyboardNumber extends StatefulWidget {
final int n;
final onPressed;
const KeyboardNumber({Key key, this.n, this.onPressed}) : super(key: key);
#override
_KeyboardNumberState createState() => _KeyboardNumberState();
}
class _KeyboardNumberState extends State<KeyboardNumber> {
#override
Widget build(BuildContext context) {
return Container(
width: 60.0,
height: 60.0,
decoration: BoxDecoration(
color: teal2,
borderRadius: BorderRadius.all(
Radius.circular(10),
),
),
alignment: Alignment.center,
child: FlatButton(
padding: EdgeInsets.all(8.0),
onPressed: widget.onPressed,
height: 90.0,
child: Text(
"${widget.n}",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 16,
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
),
);
}
}
you define pinString in another state and change it in bottomeSheet state, you must define it in this line :
showModalBottomSheet(
context: context,
builder: (context) {
String pinString = 'hi';
return StatefulBuilder(builder: (BuildContext context, StateSetter setState){
return Container(
height: 550.0,
child: Column(
children: <Widget>[
Text(
"$pinString",
),
FlatButton(
child: Text("Update"),
onPressed: () {
setState(() => pinString = 'new');
},
),
],
),
);
});
},
);
}
Please note that the new setState will override your main widget setState but sure you can just rename it so you would be able to set state of your parent widget and the modal's
Here is the updated code.
showNumberPad(BuildContext context) {
showModalBottomSheet(
context: context,
builder: (context) {
return StatefulBuilder(builder: (context, SetState1) {
return Container(
height: 550.0,
child: Column(
children: <Widget>[
Text(
"$pinString",
),
FlatButton(
child: Text("Update"),
onPressed: () {
SetState1(() {
pinString = "New Pin";
});
},
),
],
),
);
});
},
);
}
Related
I have created basic todo app Everything is going well but while deleting or converting to completed(clicked on checkbox) it removes instantly.. I want animated so that It took time and user can see its checked or deleted
I have done all code but now don't know how to replace and where part should be corrected to convert into AnimatedList...
I want to have ur suggestion,
for how to convert to animatedList and is there any simple way instead animatedList bcz I have to do many changes in converting list view to animated list
class TodoListWidget extends StatelessWidget {
const TodoListWidget({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
final provider = Provider.of<TodoProvider>(context);
final todos = provider.todos;
return todos.length == 0
? Center(
child: Text('No Todos'),
)
: ListView.separated(
//physics: BouncingScrollPhysics(),
padding: EdgeInsets.all(10),
separatorBuilder: (context, index) {
return Container(
height: 9,
);
},
itemCount: todos.length,
itemBuilder: (context, index) {
final todo = todos[index];
return TodoWidget(todo: todo);
},
);
}
}
here is my class todowidget
class TodoWidget extends StatelessWidget {
final Todo todo;
TodoWidget({required this.todo});
#override
Widget build(BuildContext context) {
return ClipRRect(
borderRadius: BorderRadius.circular(10.0),
child: Container(
color: todo.color,
padding: EdgeInsets.all(20),
child: Row(
children: [
todo.isdone==false?Checkbox(
activeColor: Colors.white,
checkColor: Colors.red,
value: todo.isdone,
onChanged: (value) {
final result= Provider.of<TodoProvider>(context,listen: false).toogletodo(todo);
}):IconButton(onPressed: (){
final result= Provider.of<TodoProvider>(context,listen: false).toogletodo(todo);
}, icon: Icon(Icons.refresh)),
SizedBox(
width: 20,
),
GestureDetector(
onTap: todo.isdone?null:(){
showDialog(
barrierDismissible: false,
context: context,
builder: (ctx)=> AddTodoDialogWidget(
title: todo.title,
description: todo.description,
isedit:true,
id: todo.id,
));
},
child: Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(todo.title,style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 16, color: Colors.black)),
SizedBox(height: 6,),
if (todo.description.isNotEmpty)
Container(
child: Text(
todo.description,
style: TextStyle(fontSize: 12, color: Colors.black),
),
),
],
),
),
),
Spacer(),
IconButton(
onPressed: () {
Provider.of<TodoProvider>(context,listen: false).deletetodo(todo);
},
icon: Icon(Icons.delete,color: Colors.red,)),
],
),
),
);
}
}
I am showing a showModalBottomSheet using a function. I want that as soon as it closes, value of a variable should change. I wanted to change value of two variables, but I am not able to change for even one. Please help me with this. I tried to make my own onChanged and also tried to return the value using function, but nothing happens.
This is the function, please scroll to the last of it and check out the onTap function and return.
String showChapterSelectionSheet(
BuildContext context,
List<ChapterModel> chapter_list,
String chapter_name,
final Function(String) onChapterChanged) {
String retValue = chapter_name;
showModalBottomSheet(
context: context,
backgroundColor: Colors.transparent,
elevation: 0,
isScrollControlled: true,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20), topRight: Radius.circular(20)),
),
builder: (context) {
return StatefulBuilder(
builder: (BuildContext context,
StateSetter setState /*You can rename this!*/) {
return makeDismissible(
context,
child: DraggableScrollableSheet(
initialChildSize: 0.81,
minChildSize: 0.5,
maxChildSize: 0.81,
builder: (_, controller) => Container(
padding: EdgeInsets.all(getProportionateScreenWidth(25)),
height: getProportionateScreenWidth(600),
decoration: BoxDecoration(
color: backgroundColor2,
borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
),
child: Column(
children: [
Padding(
padding: EdgeInsets.only(
top: getProportionateScreenHeight(32),
bottom: getProportionateScreenHeight(16)),
child: Text(
AppLocalizations.of(context)!.chapters,
style: Theme.of(context)
.textTheme
.headline2!
.apply(color: Colors.white),
),
),
Expanded(
child: ListView.builder(
shrinkWrap: true,
controller: controller,
itemCount: chapter_list.length,
itemBuilder: (_, index) {
return GestureDetector(
child: Padding(
padding: EdgeInsets.only(
top: getProportionateScreenHeight(8)),
child: Card(
child: Container(
height: getProportionateScreenHeight(56),
width: getProportionateScreenWidth(341),
decoration: BoxDecoration(
border: Border.all(color: cardColor),
color: chapter_list[index].chapter_name! ==
chapter_name
? backgroundColor
: cardColor,
),
child: Padding(
padding: EdgeInsets.all(0),
child: Center(
child: Row(
children: [
Container(
width:
getProportionateScreenWidth(
32),
child: chapter_list[index]
.chapter_name! ==
chapter_name
? Icon(
Icons.check,
color: brandYellow,
)
: SizedBox()),
Text(
"Chapter ${chapter_list[index].position!}: ",
style: Theme.of(context)
.textTheme
.bodyText2!
.apply(color: brandYellow),
),
Expanded(
child: Text(
chapter_list[index]
.chapter_name!,
style: Theme.of(context)
.textTheme
.bodyText2!
.apply(
color: chapter_list[
index]
.chapter_name! ==
chapter_name
? tertiaryTextColor
: primaryTextColor)),
),
],
),
),
),
),
),
),
onTap: () {
onChapterChanged(chapter_list[index].chapter_name!);
setState(() {
retValue = chapter_list[index].chapter_name!;
});
Navigator.pop(context);
},
);
},
),
),
],
),
),
),
);
},
);
},
);
return retValue;
}
And I am accessing it here -
return InkWell(
onTap: () async {
if(dataList.isNotEmpty) {
chapterName.value = showChapterSelectionSheet(
context,dataList,chapterName.value,(val) {
setState(() {
chapterName.value = val;
print("Val is - $val");
});
}
);
}
},
child: .....
);
In the above InkWell, the print statement is working fine but value is not changing.
And I want to update and use the value here -
child: ValueListenableBuilder(
valueListenable: chapterName,
builder: (context, String val, Widget? child) {
return Text(
val,
style: TextStyle(
color: Colors.white,
fontSize: 15,
),
);
},
),
It is possible you are just missing await before await showModalBottomSheet(..).
You can follow this simplified snippet.
class BVChange extends StatefulWidget {
const BVChange({Key? key}) : super(key: key);
#override
State<BVChange> createState() => _BVChangeState();
}
class _BVChangeState extends State<BVChange> {
String var1 = "Old", var2 = "old1";
Future<String> _showDialog(String v) async {
double _sliderValue = 0.0;
await showModalBottomSheet(
context: context,
builder: (_) {
return StatefulBuilder(
builder: (context, sbSate) => Column(
children: [
Text(_sliderValue.toString()),
Slider(
value: _sliderValue,
onChanged: (sval) {
sbSate(() {
_sliderValue = sval;
});
}),
],
),
);
});
return _sliderValue.toString();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
GestureDetector(
onTap: () async {
final data = await _showDialog(var1);
setState(() {
var1 = data;
});
},
child: Text("var1 : $var1")),
GestureDetector(
onTap: () async {
final data = await _showDialog(var2);
setState(() {
var2 = data;
});
},
child: Text("var 2 : $var2"),
),
],
),
);
}
}
https://github.com/flutter-devs/flutter_folding_cell_demo/blob/master/lib/demo_screen.dart
I'm trying to follow the code in the link above.
But in the SimpleFoldingCell part, an error named 'The class 'SimpleFoldingCell' doesn't have a default constructor.' occurs.
Could
Is there a way to resolve this error in Dart?
class Notific extends StatefulWidget{
#override
_State createState() => _State();
}
class _State extends State<Notific>{
late List<TechnologyModel> _technologyList;
#override
void initState() {
super.initState();
_technologyList = [
TechnologyModel(title: "Application Development",),
TechnologyModel(title: "Research & Development",),
TechnologyModel(title: "Big Data & Analytics",),
TechnologyModel(title: "Support Services",),
TechnologyModel(title: "QA & Software Testing",),
];
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
automaticallyImplyLeading: false,
backgroundColor: Colors.pink[200],
title: Text("Folding Cell Demo",
style: TextStyle(color: Colors.white),),
),
body: Container(
child: ListView.builder(
itemCount: _technologyList.length,
itemBuilder: (context, index) {
return SimpleFoldingCell(
frontWidget: _buildFrontWidget(index),
innerTopWidget: _buildInnerWidget(index),
innerBottomWidget: _buildInnerBottomWidget(),
cellSize: Size(MediaQuery.of(context).size.width, 125),
padding: EdgeInsets.all(15),
animationDuration: Duration(milliseconds: 200),
borderRadius: 10,
onOpen: () => print('$index cell opened'),
onClose: () => print('$index cell closed'),
);
},
),
),
);
}
Widget _buildFrontWidget(int index) {
return Builder(
builder: (BuildContext context) {
return Container(
color: Colors.cyan[100],
alignment: Alignment.bottomCenter,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"Aeologic Technology",
style: TextStyle(
fontSize:20.0,
color: Colors.black,
),
),
SizedBox(height: 10,),
FlatButton(
onPressed: () {
final foldingCellState = context
.findAncestorStateOfType<SimpleFoldingCellState>();
foldingCellState?.toggleFold();
},
child: Text(
"OPEN",
),
textColor: Colors.white,
color: Colors.indigoAccent[100],
splashColor: Colors.white.withOpacity(0.5),
),
],
),
);
},
);
}
Widget _buildInnerBottomWidget() {
return Builder(
builder: (context) {
return Container(
color: Colors.blueGrey[50],
alignment: Alignment.bottomCenter,
child: Padding(
padding: EdgeInsets.only(bottom: 10),
child: FlatButton(
onPressed: () {
final foldingCellState = context
.findAncestorStateOfType<SimpleFoldingCellState>();
foldingCellState?.toggleFold();
},
child: Text(
"Close",
),
textColor: Colors.white,
color: Colors.redAccent[100],
splashColor: Colors.white.withOpacity(0.5),
),
),
);
}
);
}
Widget _buildInnerWidget(int index) {
return Builder(
builder: (context) {
return Container(
color: Colors.pink[100],
padding: EdgeInsets.only(top: 10),
child: Align(
alignment: Alignment.center,
child: Text(
_technologyList[index].title,
style: TextStyle(
fontSize:20.0,
color: Colors.black,
),
),
),
);
},
);
}
}
class TechnologyModel {
String title;
TechnologyModel({
required this.title,
});
}
For some reason they've created only a named constructor.
return SimpleFoldingCell.create(
frontWidget: _buildFrontWidget(index),
innerWidget: _buildInnerWidget(index),
// innerTopWidget: _buildInnerWidget(index),
// innerBottomWidget: _buildInnerBottomWidget(),
cellSize: Size(MediaQuery.of(context).size.width, 125),
padding: EdgeInsets.all(15),
animationDuration: Duration(milliseconds: 200),
borderRadius: 10,
onOpen: () => print('$index cell opened'),
onClose: () => print('$index cell closed'),
);
It looks like the demo you're looking at is a bit outdated, since some of those properties don't exist anymore (see commented code).
I'm writing a program that uses floatingActionButton.
When OriginFloatingActionButton() called, showDialog() is called in the method.
Profile calls first.
#immutable
class Profile extends StatefulWidget {
const Profile({Key? key}) : super(key: key);
#override
_Profile createState() => _Profile();
}
class _Profile extends State<Profile> {
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: OriginFloatingActionButton(),
.......
);
}
}
Below code is showing floatingActionButton, and show dialog when it pushed.
In this dialog, when ElevatedButton pushed, add strings list element with setState.
However amount of element in ListView.builder isn't updated.
When I close dialog and re-open it, it updated.
How can I update ListView.builder when push ElevatedButton.
class OriginFloatingActionButton extends StatefulWidget {
const OriginFloatingActionButton({Key? key}) : super(key: key);
#override
_OriginFloatingActionButton createState() => _OriginFloatingActionButton();
}
class _OriginFloatingActionButton extends State<OriginFloatingActionButton> {
List<String> strings = <String>[
"abc"
];
#override
Widget build(BuildContext context) {
return Container(
margin: const EdgeInsets.only(bottom: 30.0, right: 30),
width: 140,
height: 55,
child: SingleChildScrollView(
child: FloatingActionButton.extended(
label: const Text("Post"),
icon: const Icon(Icons.add),
backgroundColor: Colors.blue,
foregroundColor: Colors.white,
onPressed: () {
showDialog(
context: context,
builder: (BuildContext context) {
return Dialog(
elevation: 16,
child: Container(
height: 700,
width: 500,
child: Center(
child: Column(
children: <Widget>[
Center(
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(
width: 300,
child: Expanded(
child: ListView.builder(
shrinkWrap: true,
itemCount:
strings.length,
itemBuilder:
(BuildContext context,
int index) {
return TextField(
decoration: InputDecoration(
label: Text(
"Artist Name " +
index
.toString()),
border:
const OutlineInputBorder()),
);
}))),
const SizedBox(
width: 5,
),
ElevatedButton(
child: const Icon(Icons.add),
style: ElevatedButton.styleFrom(
primary: Colors.white,
onPrimary: Colors.black,
shape: const CircleBorder(
side: BorderSide(
color: Colors.black,
width: 1,
style: BorderStyle.solid))),
onPressed: () {
setState(() {
if (mounted) {
strings
.add("ABC");
}
});
},
),
........
Is this because that I call OriginFloatingActionButton() in floatingActionButton:?
So far no errors have occurred.
How can I update the ListView without refreshing the Dialog?
Use StatefulBuilder to use setState inside Dialog
showDialog(
context: context,
builder: (context) {
return StatefulBuilder(
builder: (context, setState) {
return AlertDialog(
title: Text("Title of Dialog"),
content: Text(contentText),
actions: <Widget>[
TextButton(
onPressed: () => Navigator.pop(context),
child: Text("Cancel"),
),
TextButton(
onPressed: () {
setState(() {
///this will update
});
},
child: Text("Change"),
),
],
);
},
);
},
);
I have the numOfItems set in this class and I want to use it in another class AddToCart, but I cant pass the variable successfully.. here is a sample code, please how can I do this, I cannot seem to figure it out, What I want to know is the best way to pass data after I have setState to the other class..
static int numOfItems = 1;
#override
Widget build(BuildContext context) {
return Row(
children: <Widget>[
buildOutlineButton(
icon: Icons.remove,
press: () {
if(numOfItems > 1){
setState(() {
numOfItems--;
});
}
},
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: kDefaultPaddin / 2),
child: Text(
//"01",
numOfItems.toString().padLeft(2, "0"),
style: Theme.of(context).textTheme.headline,
),
),
buildOutlineButton(
icon: Icons.add,
press: () {
setState(() {
numOfItems++;
});
}),
],
);
}
SizedBox buildOutlineButton({IconData icon, Function press}) {
return SizedBox(
width: 32,
height: 32,
child: OutlineButton(
padding: EdgeInsets.zero,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
onPressed: press,
child: Icon(icon),
),
);
}
}```
here is the second class where I want to use the numOfItems in the second class, how can I access the variable in this class.
```class AddToCart extends StatelessWidget {
const AddToCart({
Key key,
}) : super(key: key);
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return Padding(
padding: const EdgeInsets.symmetric(vertical: kDefaultPaddin),
child: Row(
children: <Widget>[
Container(
margin: EdgeInsets.only(right:kDefaultPaddin),
height:50,
width: size.width * 0.3,
decoration: BoxDecoration(
border: Border.all(color:primaryColorDark),
borderRadius: BorderRadius.circular(18),
),
child: IconButton(
icon: SvgPicture.asset(
"assets/icons/add_to_cart.svg", color: primaryColorDark,), //svgPicture.asser
onPressed: () {
// on press of the cart button
},
),
),
Expanded(
child: SizedBox(
height:50,
child: FlatButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18)
),
color: primaryColor,
onPressed: (){
addProductToCart(context);
},
child: Text(
"Buy Now".toUpperCase(),
style: TextStyle(
fontSize: 17,
fontWeight: FontWeight.bold,
color: Colors.white,
)
),
),
),
)
],
),
);
}
void addProductToCart(BuildContext context) {
String quantityToSend = numOfItems
}
}
}```
What I want to know is the best way to pass data after I have setState to the other class..
You can use constructor to pass variable
Example:
Screen1:
class _TabsPageState extends State<TabsPage> {
int args = 3;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: FlatButton(
color: Colors.blueAccent,
child: Text('Navigate to home', style: TextStyle(color: Colors.white),),
onPressed: () {
print('123');
Navigator.pushReplacement(context, MaterialPageRoute(builder: (_) => Tab2Page(args)));
},
),
),
);
}
}
Screen2:
class Tab2Page extends StatelessWidget {
final int args;
Tab2Page(this.args);
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Text(args.toString()),
),
);
}
}
If you need only this variable " If it widget " just use the name of class x and then . then the name of static variable
i.e x.numOfItems
If this a another screen and you want to pass the data to this screen you can do it like this
class SecondScreen{
var anyVariable;
XScreen(this.anyVariable);
.......
......
}
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SecondScreen(anyVariable :numOfItems),
),
);
},