i want to asking about my problem, i want to make a stack of card with ifinite loop when stack card on last index on array, i want to make it loop to first index. i use satck widget and page builder for it, i have a list of data :
import 'package:flutter/material.dart';
List<String> images = [
'assets/images/trivia/bedroom.png',
'assets/images/trivia/digital-signature.png',
];
List<String> title = [
'“41 percent of job seekers search for jobs while in bed”',
'“Digital signatures are legally recognized.”',
];
List<Color> colorList = [
Color(0xffa605ad),
Color(0xffe0991e),
];
and my flutter code :
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'data.dart';
import 'dart:math';
void main() => runApp(MaterialApp(
home: Trivia(),
debugShowCheckedModeBanner: false,
));
class Trivia extends StatefulWidget {
#override
_TriviaState createState() => new _TriviaState();
}
var cardAspectRatio = 12.0 / 16.0;
var widgetAspectRatio = cardAspectRatio * 1.2;
class _TriviaState extends State<Trivia> {
var currentPage = images.length - 1.0;
#override
Widget build(BuildContext context) {
PageController controller = PageController(initialPage: images.length - 1);
controller.addListener(() {
setState(() {
currentPage = controller.page;
});
});
return Container(
decoration: BoxDecoration(
color: Colors.white,
),
child: Scaffold(
backgroundColor: Colors.transparent,
body: Column(
children: <Widget>[
SizedBox(
height: 70,
),
Container(
alignment: Alignment.center,
child: Text(
'Please Wait',
textAlign: TextAlign.center,
),
),
SizedBox(
height: 60,
),
Stack(
children: <Widget>[
CardScrollWidget(currentPage),
Positioned.fill(
child: PageView.builder(
itemCount: images.length,
controller: controller,
reverse: true,
itemBuilder: (context, index) {
return Container();
},
),
),
],
),
],
),
),
);
}
}
class CardScrollWidget extends StatelessWidget {
double currentPage;
var padding = 20.0;
var verticalInset = 20.0;
CardScrollWidget(this.currentPage);
#override
Widget build(BuildContext context) {
return new AspectRatio(
aspectRatio: widgetAspectRatio,
child: LayoutBuilder(builder: (context, contraints) {
var width = contraints.maxWidth;
var height = contraints.maxHeight;
var safeWidth = width - 2 * padding;
var safeHeight = height - 2 * padding;
var heightOfPrimaryCard = safeHeight;
var widthOfPrimaryCard = heightOfPrimaryCard * cardAspectRatio;
var primaryCardLeft = safeWidth - widthOfPrimaryCard;
var horizontalInset = primaryCardLeft / 2;
List<Widget> cardList = new List();
for (var i = 0; i < images.length; i++) {
var delta = i - currentPage;
bool isOnRight = delta > 0;
var start = padding +
max(
primaryCardLeft -
horizontalInset * -delta * (isOnRight ? 15 : 1),
0.0);
var cardItem = Positioned.directional(
top: padding + verticalInset * max(-delta, 0.0),
bottom: padding + verticalInset * max(-delta, 0.0),
start: start,
textDirection: TextDirection.rtl,
child: ClipRRect(
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16.0),
border: Border.all(color: colorList[i], width: 2)),
child: AspectRatio(
aspectRatio: cardAspectRatio,
child: Stack(
fit: StackFit.expand,
children: <Widget>[
Text(
'Fun Fact',
textAlign: TextAlign.center,
style: TextStyle(
decorationColor: Colors.black,
fontSize: 22,
fontFamily: 'Poppins-ExtraBold'),
),
Image.asset(
images[i],
scale: 3,
),
Align(
alignment: Alignment.bottomLeft,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Padding(
padding: EdgeInsets.symmetric(
horizontal: 16.0, vertical: 8.0),
child: Text(title[i],
textAlign: TextAlign.center,
style: TextStyle(
color: colorList[i],
fontSize: 18.0,
fontFamily: 'TTCommons')),
),
SizedBox(
height: 10.0,
),
],
),
)
],
),
),
),
),
);
cardList.add(cardItem);
}
return Stack(
children: cardList,
);
}),
);
}
}
i want to make the card loopable by array. thank you anyway
You can do this using an PageView, the default is loop, unless you provide an item count for PageView. Example
final controller = new PageController(initialPage: 999);
...
new PageView.builder(
controller: controller,
itemBuilder: (context, index) {
return new Center(
child: new Text('${index % 5}'),
);
},
)
I don't know if you need exactly the stack and can't do with PageView.. but if you can't do with PageView, i'll try searching an answer to you.
I Hope i have helped you!
Related
I use firestore to save the data. So, I use 'set'method. but It can't save the data. I get the error cannot get a field on a DocumentSnapshotPlatform which does not exist. How can I solve this error?
this my code. first code is input the title and content code. '''
class WritePage extends StatefulWidget {
#override
_WritePageState createState() => _WritePageState();
}
class _WritePageState extends State<WritePage> {
DataBase dataBase = new DataBase();
String title = ' '; //제목
String content = ' '; //내용
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text("글쓰기"),
),
body: Center(
child: ListView(
children: <Widget>[
Column(
children: <Widget>[
Padding(
padding: EdgeInsets.fromLTRB(20, 20, 20, 5),
child: TextField(
onChanged: (String text) {
if(text != null) {
title = text;
}else{title = 'null';}
},
keyboardType: TextInputType.multiline,
decoration: InputDecoration(
hintText: '제목을 적어주세요',
border: OutlineInputBorder(),
labelText: "제목을 입력하세요.",
),
),
),
Padding(
padding: EdgeInsets.fromLTRB(20, 20, 20, 5),
child: TextField(
onChanged: (String text) {
if(text != null) {
content = text;
}else{content = 'null';}
},
keyboardType: TextInputType.multiline,
maxLines: 20,
decoration: InputDecoration(
hintText: '내용을 적어주세요',
border: OutlineInputBorder(),
labelText: "내용을 입력하세요.",
),
),
),
Padding(
padding: EdgeInsets.fromLTRB(20, 5, 20, 5),
child: SizedBox(
height: 50,
width: 400,
child: TextButton(
onPressed: () async {
DataBase dataBase = new DataBase();
var now = DateTime.now();
await dataBase.add(title, content, '$now');
Navigator.pop(context);
},
child: Text(
'글쓰기',
style: TextStyle(color: Colors.black),
),
style: TextButton.styleFrom(primary: Colors.blue),
),
),
),
],
)
],
),
),
);
}
}
''''
this is my code2. this code is to save the data in firestore.
but it does not work.
class DataBase {
FirebaseFirestore firestore = FirebaseFirestore.instance;
String collection = '게시판';
add(String title, String content, String date_time) {
firestore
.collection('카운트')
.doc('카운트')
.get().then((DocumentSnapshot ds) {
firestore.collection(collection).doc('${ds['카운트']!}').set(
{'제목': title, '내용': content,
'날짜': date_time, 'id': ds['카운트']!});
int id = ds['카운트']! + 1;
cntupdate(id);
});
}
void cntupdate(int _id) {
firestore.collection('카운트').doc('카운트').update({'id': _id,
'카운트': _id});
}
import 'package:flutter/material.dart';
import 'package:stone_recipe_app/homepage.dart';
import 'package:stone_recipe_app/models/recipe.dart';
import 'package:share_plus/share_plus.dart';
class DetailedScreen extends StatelessWidget {
DetailedScreen({Key? key, required this.recipe, required this.index}) : super(key: key);
List<Recipe>? recipe;
int index;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: Row(
children: [
IconButton(
icon: const Icon(Icons.arrow_back_ios),
onPressed: () {
Navigator.push(context, MaterialPageRoute(builder: (context) => HomePage()));
},
),
Text(
'Back',
style: TextStyle(color: Color(0xff007AFF)),
)
],
),
iconTheme: const IconThemeData(color: Color(0xff007AFF)),
title: Center(
child: Text(
recipe![index].recipe_name,
style: TextStyle(color: Colors.black),
),
),
backgroundColor: Colors.white,
elevation: 0,
),
body: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Column(
children: [
Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(200),
),
child: Container(
width: 400,
height: 200,
decoration: const BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(9.0)),
image: DecorationImage(
image: AssetImage("images/cook.jpg"),
fit: BoxFit.cover,
),
boxShadow: [
BoxShadow(
blurRadius: 5,
color: Colors.black,
)
],
),
),
),
Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
const Icon(
Icons.file_download_sharp,
color: Colors.blue,
size: 40,
),
const Icon(
Icons.document_scanner,
size: 40,
),
IconButton(
onPressed: () {
Share.share(recipe![index].recipe_prep);
},
icon: const Icon(
Icons.share,
color: Colors.blue,
size: 40,
)),
const Icon(
Icons.favorite,
color: Colors.red,
size: 40,
),
]),
SizedBox(
height: 500,
child: Card(
elevation: 4,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Center(
child: Text(
'Ingredients',
style: TextStyle(fontSize: 30, fontWeight: FontWeight.bold),
),
),
Column(
children: [
Text(recipe![index].recipe_ingrdients),
],
),
Center(
child: Text(
'Method',
style: TextStyle(fontSize: 30, fontWeight: FontWeight.bold),
),
),
Text(
recipe![index].recipe_prep,
style: TextStyle(
fontSize: 20,
),
)
],
),
),
)
],
),
),
);
// Scaffold(
// appBar: AppBar(
// title: Text(recipe![index].recipe_name),
// ),
// body: Center(
// child: SingleChildScrollView(
// child: Column(
// mainAxisSize: MainAxisSize.min,
// children: [
// SelectableText(recipe![index].recipe_cat),
// Text(recipe![index].recipe_prep),
// Text(recipe![index].recipe_id.toString()),
// Text(recipe![index].recipe_ingrdients),
// Text(recipe![index].image_name),
// OutlinedButton(
// onPressed: () {
// Share.share(recipe![index].recipe_prep);
// },
// child: Text('Share'))
// ],
// ),
// ),
// ),
// );
}
}
import 'package:flutter/material.dart';
import 'package:stone_recipe_app/detailedScreen.dart';
import 'package:stone_recipe_app/models/recipe.dart';
import 'package:stone_recipe_app/services/db_services.dart';
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
#override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
final dbservice = DataBaseService();
#override
void dispose() {
dbservice.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Recipe App')),
body: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: FutureBuilder<List<Recipe>>(
future: dbservice.getRecipe(),
builder: (context, snapshot) {
if (!snapshot.hasData) return Center(child: CircularProgressIndicator());
return ListView.builder(
shrinkWrap: true,
itemCount: snapshot.data?.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => DetailedScreen(
recipe: snapshot.data,
index: index,
)));
},
title: Text(snapshot.data![index].recipe_name, style: TextStyle(color: Colors.black)),
// trailing: Text(
// snapshot.data![index].recipe_cat,
// style: TextStyle(color: Colors.black),
// overflow: TextOverflow.fade,
// ),
);
},
);
},
)),
);
}
}
enter image description herei am trying to show data from sqlite db in flutter when user click on country category like india china after user click user navigate to other page which are recipe name related to chine or related to india i am trying to show data from sqlite db in flutter when user click on country category like india china after user click user navigate to other page which are recipe name related to chine or related to india enter image description here
add group_list_view: ^1.1.1 package in your pubspec.yaml file.
try below the example then implement it in your project
import 'package:flutter/material.dart';
import 'package:group_list_view/group_list_view.dart';
import 'package:group_listview_example/app_colors.dart';
void main() => runApp(MyApp());
Map<String, List> _elements = {
'Team A': ['Klay Lewis', 'Ehsan Woodard', 'River Bains'],
'Team B': ['Toyah Downs', 'Tyla Kane'],
'Team C': ['Marcus Romero', 'Farrah Parkes', 'Fay Lawson', 'Asif Mckay'],
'Team D': [
'Casey Zuniga',
'Ayisha Burn',
'Josie Hayden',
'Kenan Walls',
'Mario Powers'
],
'Team Q': ['Toyah Downs', 'Tyla Kane', 'Toyah Downs'],
};
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Group List View Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
appBar: AppBar(
title: Text('Group List View Demo'),
),
body: GroupListView(
sectionsCount: _elements.keys.toList().length,
countOfItemInSection: (int section) {
return _elements.values.toList()[section].length;
},
itemBuilder: _itemBuilder,
groupHeaderBuilder: (BuildContext context, int section) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 8),
child: Text(
_elements.keys.toList()[section],
style: TextStyle(fontSize: 18, fontWeight: FontWeight.w600),
),
);
},
separatorBuilder: (context, index) => SizedBox(height: 10),
sectionSeparatorBuilder: (context, section) => SizedBox(height: 10),
),
),
);
}
Widget _itemBuilder(BuildContext context, IndexPath index) {
String user = _elements.values.toList()[index.section][index.index];
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: Card(
elevation: 8,
child: ListTile(
contentPadding:
const EdgeInsets.symmetric(horizontal: 18, vertical: 10.0),
leading: CircleAvatar(
child: Text(
_getInitials(user),
style: TextStyle(color: Colors.white, fontSize: 18),
),
backgroundColor: _getAvatarColor(user),
),
title: Text(
_elements.values.toList()[index.section][index.index],
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w400),
),
trailing: Icon(Icons.arrow_forward_ios),
),
),
);
}
String _getInitials(String user) {
var buffer = StringBuffer();
var split = user.split(" ");
for (var s in split) buffer.write(s[0]);
return buffer.toString().substring(0, split.length);
}
Color _getAvatarColor(String user) {
return AppColors
.avatarColors[user.hashCode % AppColors.avatarColors.length];
}
}
so I want to have a List/Array that contains images and where each image has his own title.
The image and the title should be shown in two different buttons and the title should change when I tap on the image.
I already could solve the first two points (to show in different places and that the title changes)
But I don't know how to add images to my List, could you help me?
In addition to that, the List should be randomized, but the title should always "stay" with his image.
I hope you understand what I want and thank you for your help.
class Sachen {
String title;
String image;
Sachen(this.title, this.image);
}
final List<Sachen> infoBank = [
Sachen("Chips", "images/snack1.png",),
Sachen("Erdnussflips", "images/snack2.png",),
];
int bankNumber = Random().nextInt(2) +1;
#override
Widget build(BuildContext context) {
return Center(
child: Column(
children: [
Card(
margin: EdgeInsets.fromLTRB(50, 35, 50, 0),
elevation: 8,
color: Color(0xFF4caf50),
child: SizedBox(
height: 80,
width: 150,
child: Center(
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 18),
child: GestureDetector(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => Rezept('Rezept'),
),
);
},
child: SizedBox(
height: 125,
width: 150,
child: Center(
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 18),
child: Text(
infoBank[bankNumber].title,
style: GoogleFonts.rubik(
fontSize: 20,
color: Colors.white,
),
),
),
),
),
),
),
),
),
),
Row(
children: [
Expanded(
child: TextButton(
onPressed: () {
setState(() {
bankNumber++;
});
changeDiceNumber();
print('LeftDiceNumber = $DiceNumber');
},
child: Container(
margin: EdgeInsets.fromLTRB(10, 20, 10, 20),
decoration: BoxDecoration(
border: Border.all(
width: 2,
color: Colors.grey.shade700,
),
),
height: 350,
width: 350,
child: Image.asset('images/snack$DiceNumber.png',
fit: BoxFit.cover,
),
),
),
),
],
),
],
),
);
}
}
have you tried using Flutter's ListViewBuilder?
Like alread said ListView().builder will be a good usage.
Instead of building the widget you can just use ListTile or Card there you already have trailing, leading, and title for the positioning of your images.
Althou i would change the class Sachen with a final Icon or IconData to directly add it to your List. In The Constructor please use required for the parameters its for better reading and don't do mistakes
This is my first idea to use this
class Sachen {
final String title;
final String image;
Sachen({
required this.title,
required this.image,
});
}
final List<Sachen> liste = [
Sachen(title: "title", image: "name"),
Sachen(title: "title1", image: "name1"),
];
return ListView.builder(itemBuilder: (context, index) {
return ListTile(
leading: Image.asset(liste[index].image),
title: Text(liste[index].title),
onTap: (){
//Do On Tap
//remember to use SetState when you want to rebuild some changes
},
);
});
Other Idea maybe a little bit better:
class Sachen {
final String title;
final Image image;
Sachen({
required this.title,
required this.image,
});
}
final List<Sachen> liste = [
Sachen(title: "title", image: Image.asset("name")),
Sachen(title: "title1", image: Image.asset("name1")),
];
#override
Widget build(BuildContext context) {
return ListView.builder(itemBuilder: (context, index) {
return ListTile(
leading: liste[index].image,
title: Text(liste[index].title),
onTap: () {
//Do On Tap
//remember to use SetState when you want to rebuild some changes
},
);
});
}
I have an form (writeUrltoFirestore) which is working except for an array of urls which has to be taken from storage and added to firestore document.
Currently for every file url added in form I have new document at firestore.
So if I select 5 documents and click on "Create" button it will create 5 exactly same documents with only difference their "url" in (writeUrltoFirestore).
As I mentioned it has to create single document in firestore with array of urls for each file stored in storage.
BTW Iam not a programmer - didn't read any book, just always wanted to learn how to make an working app (kinda a dream) so please explain like to a moron if you can and don't get mad if you see something stupid.
Thanks to anyone which is willing to help me.
I need result like this link
Here is code below with some explanations.
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:file_picker/file_picker.dart';
import 'dart:io' show File;
class Fields extends StatefulWidget {
const Fields({Key? key}) : super(key: key);
#override
_FieldsState createState() =>
_FieldsState();
}
class _FieldsState extends State<Fields> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(child: _Body111()),
);
}
}
class _Body111 extends StatefulWidget {
#override
__Body111State createState() => __Body111State();
}
class __Body111State extends State<_Body111> {
final FirebaseStorage _firebaseStorage = FirebaseStorage.instance;
List<UploadTask> uploadedTasks = [];
List<File> selectedFiles = [];
//-----------------------------------------------------------------------------
// Select files to be uploaded to Storage
Future selectFileTo() async {
try {
FilePickerResult? result = await FilePicker.platform
.pickFiles(allowMultiple: true, type: FileType.any);
if (result != null) {
selectedFiles.clear();
for (var selectedFile in result.files) {
File file = File(selectedFile.path ?? '');
selectedFiles.add(file);
}
} else {
print("User has cancelled the selection");
}
} catch (e) {
print(e);
}
}
//---------------------------------------------------------------------------
// Upload selected files to Storage
uploadFileToStorage(File file) {
UploadTask task = _firebaseStorage
.ref()
.child("files/${DateTime.now().toString()}")
.putFile(file);
return task;
}
//----------------------------------------------------------------------------
// Save files to Storage and get files Urls
saveImageUrlToFirebase(UploadTask task) {
task.snapshotEvents.listen((snapShot) {
if (snapShot.state == TaskState.success) {
snapShot.ref.getDownloadURL().then((urls) =>
writeUrltoFirestore(urls));
}
});
}
//--------------------------------------------------------------------------
// Save files Urls to Firestore document
writeUrltoFirestore(urls) {
Map<String, dynamic> firestoredocData = {
"issue type": selectedValue,
"description": descriptionController.text,
"location": 'Building A',
"category": selectedCategory,
"subcategory": selectedSubcategory,
"uid": firebaseUser!.uid,
//----------------------------------------------------------------------
//----------------------------------------------------------------------
"url": urls, // HERE I HAVE TO STORE ARRAY OF URLS FROM STORAGE
//----------------------------------------------------------------------
//----------------------------------------------------------------------
};
CollectionReference collectionReference =
FirebaseFirestore.instance.collection('issues');
collectionReference.add(firestoredocData);
}
//--------------------------------------------------------------------------
// Button that triggers all
addData() async {
for (var file in selectedFiles) {
final UploadTask task = uploadFileToStorage(file);
saveImageUrlToFirebase(task);
setState(() {
uploadedTasks.add(task);
});
}
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('created successfully')));
Navigator.pop(context);
}
//----------------------------------------------------------------------------
// Other fields from Map above
List<String> categories = ['111', '222', '333'];
List<String> generalSubcategory = ['1111111', '2222222', '333333333'];
List<String> cleaningSubcategory = [
'1',
'2',
'3'
];
List<String> othersSubcategory = ['01', '02', '03'];
List<String> subcategory = [];
String? selectedCategory;
String? selectedSubcategory;
final TextEditingController descriptionController = TextEditingController();
var firebaseUser = FirebaseAuth.instance.currentUser;
String? selectedValue;
List<String> arrayList = [
'Individual ',
'Maintenance '
];
Widget _description() {
return Padding(
padding: const EdgeInsets.fromLTRB(0, 35, 0, 0),
child: TextFormField(
controller: descriptionController,
decoration: InputDecoration(
hintText: 'Here you can describe ...',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(20.0),
borderSide: const BorderSide(color: Colors.grey),
),
),
maxLines: 8,
),
);
}
#override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (context, constraints) =>
Stack(
children: [
GestureDetector(
onTap: () {
FocusScope.of(context).unfocus();
},
child: SingleChildScrollView(
child: Container(
color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.only(
left: 20.0, right: 20.0),
child: _description(),
),
Padding(
padding: const EdgeInsets.only(
left: 20.0, right: 20.0, top: 20.0),
child: Container(
padding: const EdgeInsets.fromLTRB(13, 0, 25, 0),
decoration: BoxDecoration(
color: Colors.white,
boxShadow: const [
BoxShadow(
color: Colors.grey,
spreadRadius: 2,
blurRadius: 2,
offset:
Offset(5, 5), // changes position of shadow
),
],
border: Border.all(
color: Colors.grey, width: 1.0),
borderRadius:
const BorderRadius.all(Radius.circular(20)),
),
child: DropdownButtonHideUnderline(
child: DropdownButton<String>(
dropdownColor: Colors.white,
borderRadius: BorderRadius.circular(20),
hint: const Padding(
padding: EdgeInsets.fromLTRB(10, 0, 0, 0),
child: Text(
'Categories',
style: TextStyle(),
)),
value: selectedCategory,
isExpanded: true,
items: categories.map((String value) {
return DropdownMenuItem<String>(
value: value,
child: Padding(
padding:
const EdgeInsets.fromLTRB(25, 0, 0, 0),
child: Text(
value,
textAlign: TextAlign.center,
style: const TextStyle(),
),
),
);
}).toList(),
onChanged: (category) {
if (category == '222') {
subcategory = cleaningSubcategory;
} else if (category == '111') {
subcategory = generalSubcategory;
} else if (category == '333') {
subcategory = othersSubcategory;
} else {
subcategory = [];
}
setState(() {
selectedSubcategory = null;
selectedCategory = category;
});
},
),
),
),
),
Padding(
padding: const EdgeInsets.only(
left: 20.0, right: 20.0, top: 20.0),
child: Container(
padding: const EdgeInsets.fromLTRB(20, 0, 25, 0),
decoration: BoxDecoration(
color: Colors.white,
boxShadow: const [
BoxShadow(
color: Colors.grey,
spreadRadius: 2,
blurRadius: 2,
offset:
Offset(5, 5), // changes position of shadow
),
],
border: Border.all(
color: Colors.grey, width: 1.0),
borderRadius:
const BorderRadius.all(Radius.circular(20)),
),
child: DropdownButtonHideUnderline(
child: DropdownButton<String>(
dropdownColor: Colors.white,
borderRadius: BorderRadius.circular(20),
hint: const Padding(
padding: EdgeInsets.fromLTRB(10, 0, 0, 0),
child: Text(
'Subcategories',
style: TextStyle(),
)),
value: selectedSubcategory,
isExpanded: true,
items: subcategory.map((String value) {
return DropdownMenuItem<String>(
value: value,
child: Padding(
padding:
const EdgeInsets.fromLTRB(10, 0, 0, 0),
child: Text(value),
),
);
}).toList(),
onChanged: (subcategory) {
setState(() {
selectedSubcategory = subcategory;
});
},
),
),
),
),
Padding(
padding: const EdgeInsets.only(
left: 20.0, right: 20.0, top: 20.0),
child: Container(
padding: const EdgeInsets.fromLTRB(20, 0, 25, 0),
decoration: BoxDecoration(
color: Colors.white,
boxShadow: const [
BoxShadow(
color: Colors.grey,
spreadRadius: 2,
blurRadius: 2,
offset:
Offset(5, 5), // changes position of shadow
),
],
border: Border.all(
color: Colors.grey, width: 1.0),
borderRadius:
const BorderRadius.all(Radius.circular(20)),
),
child: DropdownButtonHideUnderline(
child: DropdownButtonFormField<String>(
dropdownColor: Colors.white,
decoration: const InputDecoration(
enabledBorder: InputBorder.none,
),
validator: (value) =>
selectedValue == null
? 'Please select type'
: null,
hint: const Padding(
padding: EdgeInsets.fromLTRB(10, 0, 0, 0),
child: Text(
'Type',
),
),
value: selectedValue,
isExpanded: true,
icon: const Icon(Icons.arrow_drop_down),
items: arrayList.map((String string) {
return DropdownMenuItem<String>(
value: string,
child: Padding(
padding:
const EdgeInsets.fromLTRB(10, 0, 0, 0),
child: Text(string),
),
);
}).toList(),
onChanged: (String? string) {
setState(() {
selectedValue = string;
});
},
),
),
),
),
const Padding(
padding: EdgeInsets.only(
left: 20.0, right: 20.0, top: 20.0)),
IconButton(
onPressed: selectFileTo,
icon: const Icon(
Icons.camera_alt_outlined,
size: 30,
color: Colors.grey,
)),
const Padding(
padding: EdgeInsets.only(
left: 20.0, right: 20.0, top: 20.0)),
Padding(
padding: const EdgeInsets.only(
left: 30.0, right: 30.0, top: 5.0),
child: ElevatedButton(
style: ButtonStyle(
padding: MaterialStateProperty.all(
const EdgeInsets.all(0)),
shape: MaterialStateProperty.all<
RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0),
)),
backgroundColor: MaterialStateProperty.all<
Color>(
Colors.transparent),
shadowColor: MaterialStateProperty.all<Color>(
Colors.transparent)),
onPressed: addData,
child: Container(
decoration: const BoxDecoration(
borderRadius:
BorderRadius.all(Radius.circular(20)),
),
constraints: const BoxConstraints(
minWidth: 120, minHeight: 40),
alignment: Alignment.center,
child: const Center(
child: Text(
"Create",
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontSize: 20,
),
),
),
),
),
),
],
),
),
),
),
],
),
);
}
}
// End of dart file
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Firebase API (separate dart file)
import 'dart:io';
import 'dart:typed_data';
import 'package:firebase_storage/firebase_storage.dart';
class FirebaseApi {
static UploadTask? uploadFile(String destination, File file) {
try {
final ref = FirebaseStorage.instance.ref(destination);
return ref.putFile(file);
} on FirebaseException catch (e) {
return null;
}
}
static UploadTask? uploadBytes(String destination, Uint8List data) {
try {
final ref = FirebaseStorage.instance.ref(destination);
return ref.putData(data);
} on FirebaseException catch (e) {
return null;
}
}
}
//-----------------------------------------------------------------------------
You should call writeUrltoFirestore at last of all upload. Maintain an List at top.
List<String> _urls = [];
in saveImageUrlToFirebase
saveImageUrlToFirebase(UploadTask task) {
task.snapshotEvents.listen((snapShot) {
if (snapShot.state == TaskState.success) {
snapShot.ref.getDownloadURL().then((url) =>
_urls.add(url.toString()));
}
});
}
In final upload task simply call
writeUrltoFirestore(_urls);
In short, users can choose their interests during onboarding, UI changes and the interests are added to a list.
When user navigates to another page ie settings, how can the chosen interests be selected alrdy (bool isChosen = true)?... and then users can update their interests from there again?
any guidance is appreciated, thanks!
Attached is my truncated code for a particular theme of interests, all the themes have the same code just different list.
Let's say my data has a list of [ "🏡 Home-body", "🏃♀️ Running", "🧘🏻♀️ Yoga", "🎭 Theaters", "😸 Anime & Manga",].
What can be done so that the bubble UI of this chosen list is shown as bool isChosen (so yellow color, compared to the other dark ones)? Following which users can select and unselect again?
final List<String> artsInterests = [
blah blah blah
];
class ArtsInterests extends StatelessWidget {
const ArtsInterests({
Key key,
#required this.artsInterests,
}) : super(key: key);
final List<String> artsInterests;
#override
Widget build(BuildContext context) {
final height = MediaQuery.size.height;
final width = MediaQuery.size.width;
return Column(children: [
Container(
margin: EdgeInsets.only(
left: width * 0.045,
top: height * 0.033),
child: Align(
alignment: Alignment.centerLeft,
child: Text(
'🎨 Arts',
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 21),
)),
),
Column(
children: [
Padding(
padding: EdgeInsets.only(
left: width * 0.03,
top: height * 0.012),
child: Container(
width: width,
height: height * 0.045,
child: ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
padding: const EdgeInsets.all(1),
itemCount: 7,
itemBuilder: (context, int index) {
return Interests2(AvailableInterestChosen(
artsInterests[index],
isChosen: false,
));
}),
),
),
Padding(
padding: EdgeInsets.only(
left: width * 0.03,
top: height * 0.003),
child: Container(
width: width,
height: height * 0.045,
child: ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
padding: const EdgeInsets.all(1),
itemCount: artsInterests.length - 7,
itemBuilder: (context, int index) {
return Interests2(AvailableInterestChosen(
artsInterests[7 + index],
isChosen: false,
));
}),
),
),
],
),
]);
}
}
List<String> chosenInterests = [ "🏡 Home-body", "🏃♀️ Running", "🧘🏻♀️ Yoga", "🎭 Theaters", "😸 Anime & Manga",];
List<String> chosenArtsInterests = [];
class Interests2 extends StatefulWidget {
final AvailableInterestChosen viewInterest;
Interests2(this.viewInterest);
String id = 'Interests2';
#override
Interests2State createState() => Interests2State();
}
class Interests2State extends State<Interests2> {
#override
Widget build(BuildContext context) {
final height = MediaQuery.size.height;
final width = MediaQuery.size.width;
Container container = Container(
height: height * 0.03,
padding: EdgeInsets.symmetric(
horizontal: width * 0.027,
vertical:height * 0.003),
// padding: EdgeInsets.fromLTRB(12, 6, 12, 6),
margin: EdgeInsets.fromLTRB(
width * 0.012,
height * 0.003,
width * 0.012,
height * 0.003),
decoration: BoxDecoration(
color: widget.viewInterest.isChosen && chosenInterests.length < 9
? Color(0xff0B84FE)
: Colors.white.withOpacity(0.87),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.69),
spreadRadius: 1,
blurRadius: 3,
offset: Offset(0, 1), // changes position of shadow
),
],
borderRadius: BorderRadius.circular(9),
),
child: Text(
'${widget.viewInterest.title}',
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.w600,
color: widget.viewInterest.isChosen && chosenInterests.length < 9
? Colors.white
: Colors.black),
));
if (widget.viewInterest.isChosen && chosenInterests.length < 9) {
chosenArtsInterests.add('${widget.viewInterest.title}');
var chosenInterests = chosenSportsInterests +
chosenEntertainmentInterests +
chosenCharacterInterests +
chosenArtsInterests +
chosenWellnessInterests +
chosenLanguageInterests;
print(chosenInterests);
} else {
chosenArtsInterests.remove('${widget.viewInterest.title}');
var chosenInterests = chosenSportsInterests +
chosenEntertainmentInterests +
chosenCharacterInterests +
chosenArtsInterests +
chosenWellnessInterests +
chosenLanguageInterests;
print(chosenInterests);
}
return GestureDetector(
onTap: () {
setState(() {
widget.viewInterest.isChosen = !widget.viewInterest.isChosen;
});
},
child: container,
);
}
}
class AvailableInterestChosen {
bool isChosen;
String title;
AvailableInterestChosen(this.title, {this.isChosen = false});
}
You can pass the values to another widget as arguments but that is not possible in this case since there are so many values. You have to use a state management solution. For starter you can use provider