How to Use Download Functionality in a while Loop? - loops

I have below code, the objective is to put a download button below each image and download that particular image on being clicked. however when I run the code, for all buttons it is attempting to download Image number 9, whereas the loop run tills only i =8 that is for 8 images. Please help how to resolve this issue?
Widget getWidgets(int index, String name) {
List<Widget> list = new List<Widget>();
int i = 1;
while (i <= index) {
list.add(new Column(
children: <Widget>[
SizedBox(
height: 15.0,
),
BeforeAfter(
beforeImage: Image.asset(
'assets/$name/OG$i.jpg',
//fit: BoxFit.cover,
),
afterImage: Image.asset(
'assets/$name/$i.jpg',
//fit: BoxFit.cover,
),
isVertical: false,
),
SizedBox(
height: 10.0,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text("$name $i",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 17,
fontFamily: 'Raleway',
color: Colors.black)),
Container(
margin: EdgeInsets.only(left: 100.0),
width: 120.0,
height: 35.0,
child: FlatButton(
onPressed: () async {
final status = await Permission.storage.request();
if (status.isGranted) {
final externalDir = await getExternalStorageDirectory();
FlutterDownloader.enqueue(
url: 'assets/$name/$i.dng',
savedDir: externalDir.path,
fileName: '$name$i.dng',
showNotification: true,
openFileFromNotification: true,
);
} else {
print("Permission Denied");
}
},
child: Text('Download',
style: TextStyle(color: Colors.black, fontSize: 17)),
textColor: Colors.white,
shape: RoundedRectangleBorder(
side: BorderSide(
color: Colors.teal, width: 2, style: BorderStyle.solid),
borderRadius: BorderRadius.circular(50)),
),
),
],
),
],
));
i++;
}
return Column(children: list);
}

Actually, at the end of the loop, i is 9, that is why you see the behaviour you have. You have to make a local copy of i so this variable stays at the value it has for the loop when it gets captured:
while (i <= index) {
final localIndex = i;
// rest of your code, use localIndex here instead of i
i++;
}

Related

How to separate data into different databases?

I have a database where I want to add and store information about a particular destination or activity. In the insert information page, I have a section where user can select either destination or activity as its category. However, all these are being stored into one database but I want to have different ones for each.
This is the current code that adds them into one database:
void addDestOrAct(String name, String details, var category) {
String key = destdatabaseref
.child('Database')
.child('DestinationsandActivities')
.push()
.key;
destdatabaseref
.child('Database')
.child('DestinationsandActivities')
.child(name)
.set({
'id': key,
'name': name,
'description': details,
'category': category
});
nameController.clear();
descriptionController.clear();
Fluttertoast.showToast(
timeInSecForIosWeb: 4,
gravity: ToastGravity.CENTER,
msg: "It has been added!");
Navigator.pop(context);
}
I want to put something like if (category = 'Activity') then add into destdatabaseref.child('Database').child('Activities') instead of .child('DestinationsandActivities').
Selection of category and inserting data code:
Padding(
padding: const EdgeInsets.only(right: 290),
child: Text(
'Category :',
style: TextStyle(fontSize: 15, color: Colors.grey),
),
),
SizedBox(height: 13),
Container(
height: 40,
child: ListView(
scrollDirection: Axis.horizontal,
children: [
_categoryType('Destination'),
SizedBox(width: 10),
_categoryType('Activity'),
],
),
),
SizedBox(height: 40),
ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Color(0xFF3d5a89),
padding:
EdgeInsets.symmetric(horizontal: 45, vertical: 10),
textStyle: TextStyle(
fontWeight: FontWeight.w500,
color: Colors.white,
fontSize: 15)),
onPressed: () {
if (_formKey.currentState!.validate()) {
if (nameController.text.isNotEmpty &&
descriptionController.text.isNotEmpty) {
addDestOrAct(nameController.text,
descriptionController.text, _categorySelected);
} else
return null;
}
},
child: Text('Add')
)
Category type widget code:
Widget _categoryType(String title) {
return InkWell(
child: Container(
height: 70,
width: 120,
decoration: BoxDecoration(
color: _categorySelected == title
? Color(0xFF5a893d)
: Color(0xFF3d5a89),
borderRadius: BorderRadius.circular(15),
),
child: Center(
child: Text(
title,
style: TextStyle(fontSize: 13, color: Colors.white),
),
),
),
onTap: () {
setState(() {
_categorySelected = title;
});
},
);
}
How can I can add information into different databases based on category? I have the database 'DestinationsandActivities' for now but would really prefer it to be 'Destinations' and 'Activities'.
Thanks to #Frank van Puffelen, it was simply :
if (category == 'Activity') {
//code here
});
}
if (category == 'Destination') {
//code here
});
}

Randomly display values from an array excluding value in index 0 in flutter

I am a beginner in flutter. I was building an app as a part of learning and came across this confusion. I have an array with some names and I wanna display those names randomly on button press. I left the index 0 value as null so that every time the app loads no names are displayed. The problem is when i press the button this null value is also displaying. Please help me.
class _FoodieState extends State<Foodie> {
List<String> foodieName = ['','foodie1', 'foodie2', 'foodie3', 'foodie4', 'foodie5','foodie6','foodie7'];
int foodieNumber=0;
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.white,
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
CircleAvatar(
radius: 120.0,
backgroundImage: AssetImage('images/burger.jpg'),
),
ElevatedButton(
child: Text('Who will buy today\'s\ lunch ?'),
style: ElevatedButton.styleFrom(
primary: Colors.yellow[800],
onPrimary: Colors.white,
shape: const BeveledRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(5)),
),
textStyle: TextStyle(
fontFamily: 'Rancho',
fontSize: 35,
color: Colors.grey,
),
),
onPressed: () {
setState(() {
foodieNumber=Random().nextInt(foodieName.length);
});
},
),
Padding(
padding: const EdgeInsets.only(top: 20.0),
child: Text(
foodieName[foodieNumber],
style: TextStyle(
fontFamily: 'Pacifico',
fontSize: 30,
color: Colors.red,
fontWeight: FontWeight.bold),
),
),
],
),
),
),
);
}
}
This doesnt display first index:
foodieNumber=Random().nextInt(foodieName.length - 1) + 1;

Unable to create data tables dynamically using TextField input

I am trying out to create an invoice application, wherein the user is entering the data, and then it should come up listed as a table.
What I have achieved so far is just a single row with just a single user input detail like with errors in it as well...
I wanted the application to
HardCoded Code:
class Sixth extends StatefulWidget {
#override
State<StatefulWidget> createState() {
// TODO: implement createState
return SixthState();
}
}
class SixthState extends State<Sixth> {
final pdf = pw.Document();
String path;
share() async {
Share.shareFiles([path]);
}
create() async {
print('creating');
pdf.addPage(pw.MultiPage(
pageFormat: PdfPageFormat.a4,
margin: pw.EdgeInsets.all(12),
build: (pw.Context context) {
return <pw.Widget>[
pw.Paragraph(
text: 'SOLUTION HUB\nVENDORS',
style: pw.TextStyle(fontWeight: pw.FontWeight.bold)),
pw.Paragraph(
padding: pw.EdgeInsets.only(left: 450),
text: 'Billing Address:',
style: pw.TextStyle(fontWeight: pw.FontWeight.bold)),
pw.Row(children: [
pw.Paragraph(
text: 'wrqijwqiojqwoirjq\nirjorwiuroeriuwor\noerweo8rw',
padding: pw.EdgeInsets.only(top: 10)),
pw.SizedBox(width: 370),
pw.Paragraph(
text: 'wrqijwqiojqwoirjq\nirjorwiuroeriuwor\noerweo8rw',
padding: pw.EdgeInsets.only(top: 10))
]),
pw.Paragraph(
padding: pw.EdgeInsets.only(top: 15),
text: 'PAN No. ${panvalue}',
style: pw.TextStyle(fontWeight: pw.FontWeight.bold)),
pw.Paragraph(
padding: pw.EdgeInsets.only(top: 15),
text: 'GST Registration No. ${gstvalue}',
style: pw.TextStyle(fontWeight: pw.FontWeight.bold)),
pw.Paragraph(
padding: pw.EdgeInsets.only(top: 15),
text: 'Order No. ${ordernovalue}',
style: pw.TextStyle(fontWeight: pw.FontWeight.bold)),
pw.Paragraph(
padding: pw.EdgeInsets.only(top: 15),
text: 'Order Date. ${orderdatevalue}',
style: pw.TextStyle(fontWeight: pw.FontWeight.bold)),
pw.Paragraph(
padding: pw.EdgeInsets.only(left: 450),
text: 'INVOICE NUMBER\n03950234982042980',
style: pw.TextStyle(fontWeight: pw.FontWeight.bold)),
pw.SizedBox(height: 20),
pw.Table.fromTextArray(data: <List<String>>[
<String>[
'SI\nNo.',
'Description',
'Unit\nPrice',
'Qty',
'Net Amount',
'Tax\nRate',
'Tax\nType',
'Tax\nAmt',
'Total\nAmt'
],
<String>[
'1',
'${SecondState.descriptionController.text}',
'${ThirdState.unitpriceController.text}',
'1',
'500',
'${FourthState.taxrateController.text}',
'${FourthState.taxtypeController.text}',
'${FourthState.taxamountController.text}',
'276.6'
],
])
];
},
));
}
Future save() async {
print('sacing');
Directory directory = await getApplicationDocumentsDirectory();
String documentpath = directory.path;
File file = File("$documentpath/example.pdf");
setState(() {
path = "$documentpath/example.pdf";
});
file.writeAsBytesSync(pdf.save());
}
int _value = 1;
AnimationController animationController;
Animation<Offset> offset;
static var panvalue;
static var gstvalue;
static var ordernovalue;
static var orderdatevalue;
static var descriptionvalue;
static var unitpricevalue;
static var quantityvalue;
static var taxratevalue;
static var taxtypevalue;
static var taxamtvalue;
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
drawer: Drawer(),
appBar: AppBar(
centerTitle: true,
title: Text('ORDER DETAILS'),
backgroundColor: Colors.blueGrey,
actions: <Widget>[
Padding(
padding: EdgeInsets.all(2),
child: IconButton(
onPressed: () {}, //USER PROFILE
icon: Icon(Icons.supervised_user_circle),
iconSize: 30,
),
)
],
),
body: SingleChildScrollView(
child: SafeArea(
child: Column(children: <Widget>[
Container(
padding: EdgeInsets.only(right: 220, top: 20),
child: Text(
'SOLUTION HUB \n VENDORS',
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16),
),
),
Container(
padding: EdgeInsets.only(left: 240),
child: Text(
'Billing Adress:',
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16),
),
),
SizedBox(
height: 15,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Container(
padding: EdgeInsets.only(left: 30),
child:
Text('Ubga wjpw wiqjoiw\n owqkdw qwok qoqkw \nojq vpoqk'),
),
Container(
padding: EdgeInsets.only(right: 15),
child: Text('oefkwpfoke 20-32 \n 032902 0239 \n 0392230'),
)
],
),
Container(
width: 800,
padding: EdgeInsets.only(left: 35, right: 10, top: 45),
child: Text(
"Pan No. ${panvalue}",
style: TextStyle(fontWeight: FontWeight.bold),
),
),
Container(
width: 800,
padding: EdgeInsets.only(left: 35, right: 10, top: 25),
child: Text(
"GST REGISTRATION NO. ${gstvalue}",
style: TextStyle(fontWeight: FontWeight.bold),
),
),
Container(
width: 800,
padding: EdgeInsets.only(left: 35, right: 10, top: 25),
child: Text(
"Order No. ${ordernovalue} ",
style: TextStyle(fontWeight: FontWeight.bold),
),
),
Container(
width: 400,
padding: EdgeInsets.only(left: 35, right: 20, top: 25),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
"Order Date: ${orderdatevalue}",
style: TextStyle(fontWeight: FontWeight.bold),
),
Text(
'INVOICE NUMBER',
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 14),
)
],
),
),
Container(
padding: EdgeInsets.only(left: 250, top: 5),
child: Text('5920384283429')),
Row(
children: <Widget>[
Expanded(
child: SingleChildScrollView(
child: DataTable(columnSpacing: 4, columns: [
DataColumn(
label: Text(
'Si\nNo.',
textAlign: TextAlign.left,
)),
DataColumn(label: Text('Description')),
DataColumn(label: Text('Unit\nPrice')),
DataColumn(label: Text('Qty')),
DataColumn(label: Text('Net\namount')),
DataColumn(label: Text('Tax\nRate')),
DataColumn(label: Text('Tax\nType')),
DataColumn(label: Text('Tax\nAmt')),
DataColumn(label: Text('Total\nAmt'))
], rows: [
DataRow(cells: [
DataCell(Wrap(
children: <Widget>[
Text(
'1',
textAlign: TextAlign.start,
)
],
)),
DataCell(Text(
'${SecondState.descriptionController.text}',
textAlign: TextAlign.center,
)),
DataCell(Wrap(
children: <Widget>[
Text(
'${ThirdState.unitpriceController.text}',
textAlign: TextAlign.center,
)
],
)),
DataCell(Text('${ThirdState.quantityController.text}')),
DataCell(Text('500')),
DataCell(Text('${FourthState.taxrateController.text}')),
DataCell(Text('${FourthState.taxtypeController.text}')),
DataCell(Text('${FourthState.taxamountController.text}')),
DataCell(Text('500')),
])
]))),
],
),
SizedBox(
height: 150,
),
ButtonTheme(
minWidth: 110,
height: 50,
child: RaisedButton(
color: Colors.blue[300],
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18)),
onPressed: () {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text("COMPLETE ACTION USING"),
content: Container(
height: 150,
width: 100,
child: Column(
children: <Widget>[
FlatButton(
onPressed: () async {
create();
await save();
share();
},
child: Text('WhatsApp'),
),
FlatButton(
onPressed: () {},
child: Text('Gmail'),
),
FlatButton(
onPressed: () {},
child: Text("Download"),
)
],
),
),
);
});
},
child: Text('Share'),
),
)
]),
),
),
));
}
}
What I want to achieve is this
It should automatically add rows as user inputs enter details
Errors I have encountered:
Whenever I going to add more items the previous data are stored in the text fields.
There are more colors on the right side but am unable to view it.
Please help me solve this issue

How to scroll a text?

I have a text and I've tried a lot to make it scrollable, what I want is to make the postDesc text scrollable I've tried to wrap it with single child scroll view and listview and expanded but not worked.
please give me a solution
I want to make the screen or the container scrollable or to scroll the text only.
I've seen many solutions but it didn't work for me.
My project has been stopped because of that.
For any details you want please leave a comment.
thanks,
My Code:
#override
Widget build(BuildContext context) {
final userimage = InkWell(
child: Container(
margin: EdgeInsets.only(right: 10.0),
height: 40.0,
width: 40.0,
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage('${widget.userPhoto}'),
fit: BoxFit.cover,
),
borderRadius: BorderRadius.circular(7.0),
),
),
);
final headerDesc = Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'${widget.writer}',
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold,
),
),
Text(
'25 minutes ago',
style: TextStyle(
color: Colors.grey.withOpacity(0.6),
fontWeight: FontWeight.bold,
),
)
],
);
final header = Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[userimage, headerDesc],
);
final descriptionText = Text(
'${widget.postTitle}',
textAlign: TextAlign.center,
style: TextStyle(
fontFamily: 'Amiri',
color: Colors.black87,
fontWeight: FontWeight.w600,
fontSize: MediaQuery.of(context).size.width / 20,
),
);
final divider = Divider(
thickness: 0.5,
color: Colors.grey,
);
final footer = Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
IconButton(
onPressed: () {
print(null);
},
icon: Icon(
Icons.share,
color: Theme.of(context).primaryColor,
),
),
Row(
children: <Widget>[
SizedBox(
width: 30.0,
),
StreamBuilder<QuerySnapshot>(
stream: _firestore.collection('posts').snapshots(),
builder: (context, snapshot) {
var documents = snapshot.data.documents;
var likes;
for (var document in documents) {
if (document.documentID == widget.uid) {
likes = document['likes'];
}
}
return Text(
'$likes',
);
}),
SizedBox(
width: 3.0,
),
Icon(
Icons.favorite,
color: Colors.red,
),
],
),
],
);
return Scaffold(
body: SafeArea(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: MediaQuery.of(context).size.height,
child: Stack(
children: <Widget>[
GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ImagePreview(
image: widget.networkImage,
),
),
);
},
child: Material(
elevation: 5.0,
borderRadius: BorderRadius.circular(14.0),
child: Container(
height: MediaQuery.of(context).size.height / 5,
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(14.0),
image: DecorationImage(
image: widget.networkImage.image,
fit: BoxFit.cover,
),
),
),
),
),
Positioned(
top: 90.0,
left: 0.0,
right: 0.0,
child: Padding(
padding: EdgeInsets.only(left: 10.0, right: 10.0),
child: Material(
elevation: 5.0,
shadowColor: Colors.white,
borderRadius: BorderRadius.circular(14.0),
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(14.0),
),
child: Padding(
padding: EdgeInsets.only(
top: 20.0,
bottom: 00.0,
left: 20.0,
right: 20.0,
),
child: ListView(
shrinkWrap: true,
children: <Widget>[
header,
SizedBox(
height: 10.0,
),
descriptionText,
SizedBox(
height: 5,
),
divider,
Padding(
padding: const EdgeInsets.all(20),
child: SingleChildScrollView(
child: Text(
'${widget.postDesc}',
),
),
),
footer,
SizedBox(
height: 10,
),
],
),
),
),
),
),
)
],
),
),
),
),
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.red,
child: Icon(
Icons.favorite,
color: Colors.white,
),
onPressed: () async {
await likePost();
},
),
);
}
I might be wrong here, but I think the problem is that you have a SingleChildScrollView inside a ListView. If you just want to scroll the postDesc, you might want to add this to your ListView:
ListView(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
children: [...]
),

How to dynamically arrange cards in a row?

I want to put two cards in a row and have them dynamically resized based on phone size. As seen in the image, the right card has overflow error because the phone dimension is small. Looks fine on a bigger phone.
Ignore the first overflow error
I have tried wrapping the container using Expanded() or Flexible() but it gives an error saying my parent is using a GestureDetector() and it does not allow that.
Widget _showSecondRow(){
return new Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
new GestureDetector(
child: Card(
elevation: 1,
semanticContainer: true,
clipBehavior: Clip.antiAliasWithSaveLayer,
child: Container(
color: Colors.grey.shade200,
padding: EdgeInsets.all(45.0),
child: new Column(
children: <Widget>[
new Icon(Icons.drafts, size: 30.0, color: Colors.black),
new Text("Private\nMessages", textAlign: TextAlign.center, style: TextStyle(color: widget.appModel.getPrimaryTextColor, fontSize: 18.0, fontWeight: FontWeight.bold),)
],
),
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
)
),
new GestureDetector(
onTap: () => Navigator.push(context, new MaterialPageRoute(builder: (context) =>
new SubscribedScreen()
)),
child: Card(
elevation: 1.0,
semanticContainer: true,
clipBehavior: Clip.antiAliasWithSaveLayer,
child: Container(
color: Colors.grey.shade200,
padding: EdgeInsets.all(45.0),
child: new Column(
children: <Widget>[
new Icon(Icons.star, size: 30.0, color: Colors.black),
new Text("Subscribed\nThreads", textAlign: TextAlign.center, style: TextStyle(color: Colors.black, fontSize: 18.0, fontWeight: FontWeight.bold), overflow: TextOverflow.ellipsis,)
],
),
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
)
),
],
);
}
I expect both cards to be dynamically resized regardless of phone size and fit the width of the phone. Doesnt matter if there's gap in the middle.
Wrap each GestureDetector in Expanded or Flexible

Resources