I am currently displaying my icons like this:
Widget _buildPopupDialog(BuildContext context) {
List<IconData> _iconsTable = [
Icons.feedback,
Icons.eco,
Icons.support,
Icons.call,
Icons.nature_people,
Icons.directions_bike,
];
return new AlertDialog(
content: SingleChildScrollView(
child: new Container(
child: GridView.count(
children: new List.generate(6, (int index) {
return new Positioned(
child: new DailyButton(iconData: _iconsTable[index]),
);
}),
),
),
),
However, I am wanting to get the icon data from cloud firestore. I am very new to using both flutter and firebase so I am very unsure how I would be able to do this. So far, I have tried this but iconData: Icons.iconsData obviously doesnt work:
class MyApp3 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage3(),
);
}
}
class MyHomePage3 extends StatefulWidget {
#override
_MyHomePageState3 createState() {
return _MyHomePageState3();
}
}
class _MyHomePageState3 extends State<MyHomePage3> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: _buildBody(context),
);
}
Widget _buildBody(BuildContext context) {
return StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance.collection('icons').snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) return LinearProgressIndicator();
return _buildList(context, snapshot.data.docs);
},
);
}
Widget _buildList(BuildContext context, List<DocumentSnapshot> snapshot) {
return ListView(
children: snapshot.map((data) => _buildListItem(context, data)).toList(),
);
}
Widget _buildListItem(BuildContext context, DocumentSnapshot data) {
final record3 = Record3.fromSnapshot(data);
var _iconsData = record3.name;
return Padding(
key: ValueKey(record3.name),
child: Container(
child: Card(
child: new MoodButton(
onTap: () => print("Mood"),
iconData: Icons.iconsData,
),
// trailing: Text(record3.votes.toString()),
// onTap: () => record3.reference.update({'votes': record3.votes+1})
),
),
);
}
}
class Record3 {
final String name;
final int votes;
final DocumentReference reference;
Record3.fromMap(Map<String, dynamic> map, {this.reference})
: assert(map['name'] != null),
assert(map['votes'] != null),
name = map['name'],
votes = map['votes'];
Record3.fromSnapshot(DocumentSnapshot snapshot)
: this.fromMap(snapshot.data(), reference: snapshot.reference);
#override
String toString() => "Record<$name:$votes>";
}
Any help would be greatly appreciated!
If anyone is interested, I was able to figure it out:
Widget _buildListItem(BuildContext context, DocumentSnapshot data) {
final record3 = Record3.fromSnapshot(data);
int iconCode = record3.votes;
return Padding(
key: ValueKey(record3.name),
child: Container(
child: new Container(
child: new ListView(
scrollDirection: Axis.horizontal,
children: new List.generate(1, (int index) {
return new Positioned(
child: new MoodButton(
onTap: () => print("Mood"),
iconData: (IconData(iconCode, fontFamily: 'MaterialIcons')),
),
);
})),
),
),
);
Related
Hi I need some help with passing an image that is selected from my gallery to another screen.
When I go to the 'Pick Image' screen through the grid-tiled screen, I can select an image from my gallery app. As soon as I pick one, the image pops up on the 'Pick Image' screen and it should be passed to the previous screen(grid tiled) so the image can be displayed in a grid tile.
Anyone could handle this?
The relevant part of the code is right below.
Grid Tile screen
Widget build(BuildContext context) {
return GridView.count(crossAxisCount: 4,
children: List.generate(lastDay, (index){
return GridTile(
child: Card(
child: Column(
children: <Widget>[
Text('Day ' '$index'),
SizedBox(height: 20.0,),
IconButton(
icon: Icon(Icons.add),
onPressed: (){
Navigator.push(context,
MaterialPageRoute(builder: (context) => PickImage()));
},),
],
),
),
);
}),
);
}
Pick Image Screen
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'dart:io';
class PickImage extends StatefulWidget {
PickImage() : super();
final String title = "Pick Image";
#override
_PickImageState createState() => _PickImageState();
}
class _PickImageState extends State<PickImage> {
Future<File> imageFile;
pickImageFromGallery(ImageSource source) {
setState(() {
imageFile = ImagePicker.pickImage(source: source);
});
}
Widget showImage() {
return FutureBuilder<File>(
future: imageFile,
builder: (BuildContext context, AsyncSnapshot<File> snapshot) {
if (snapshot.connectionState == ConnectionState.done &&
snapshot.data != null) {
return Image.file(
snapshot.data,
width: 400,
height: 400,
);
} else if (snapshot.error != null) {
return const Text(
'Error Picking Image',
textAlign: TextAlign.center,
);
} else {
return const Text(
'No Image Selected',
textAlign: TextAlign.center,
);
}
},
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
showImage(),
RaisedButton(
child: Text("Select Image from Gallery"),
onPressed: () {
pickImageFromGallery(ImageSource.gallery);
},
),
],
),
),
);
}
}
You can copy paste run full code below
Step 1: Use Navigator.pop to return image
RaisedButton(
onPressed: () {
Navigator.pop(context, imageFileReturn);
},
child: Text('Selecct Finish, Go back '),
),
Step 2: Use Map<int, File> keep related index and image
Map<int, File> imageFileMap = {};
IconButton(
icon: Icon(Icons.add),
onPressed: () async {
imageFile = await Navigator.push(context,
MaterialPageRoute(builder: (context) => PickImage()));
imageFileMap[index] = imageFile;
setState(() {});
},
Step 3: Show image in Map
SizedBox(
height: 20.0,
child: imageFileMap[index] != null
? Image.file(
imageFileMap[index],
)
: Container()),
working demo
full code
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'dart:io';
class PickImage extends StatefulWidget {
PickImage() : super();
final String title = "Pick Image";
#override
_PickImageState createState() => _PickImageState();
}
class _PickImageState extends State<PickImage> {
Future<File> imageFile;
File imageFileReturn;
pickImageFromGallery(ImageSource source) {
setState(() {
imageFile = ImagePicker.pickImage(source: source);
});
}
Widget showImage() {
return FutureBuilder<File>(
future: imageFile,
builder: (BuildContext context, AsyncSnapshot<File> snapshot) {
imageFileReturn = snapshot.data;
if (snapshot.connectionState == ConnectionState.done &&
snapshot.data != null) {
return Image.file(
snapshot.data,
width: 400,
height: 400,
);
} else if (snapshot.error != null) {
return const Text(
'Error Picking Image',
textAlign: TextAlign.center,
);
} else {
return const Text(
'No Image Selected',
textAlign: TextAlign.center,
);
}
},
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
showImage(),
RaisedButton(
child: Text("Select Image from Gallery"),
onPressed: () {
pickImageFromGallery(ImageSource.gallery);
},
),
RaisedButton(
onPressed: () {
Navigator.pop(context, imageFileReturn);
},
child: Text('Selecct Finish, Go back '),
),
],
),
),
);
}
}
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> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Test(),
);
}
}
class Test extends StatefulWidget {
#override
_TestState createState() => _TestState();
}
class _TestState extends State<Test> {
int lastDay = 30;
Map<int, File> imageFileMap = {};
File imageFile;
#override
Widget build(BuildContext context) {
return GridView.count(
crossAxisCount: 4,
children: List.generate(lastDay, (index) {
return GridTile(
child: Card(
child: Column(
children: <Widget>[
Text('Day ' '$index'),
SizedBox(
height: 20.0,
child: imageFileMap[index] != null
? Image.file(
imageFileMap[index],
)
: Container()),
IconButton(
icon: Icon(Icons.add),
onPressed: () async {
imageFile = await Navigator.push(context,
MaterialPageRoute(builder: (context) => PickImage()));
imageFileMap[index] = imageFile;
setState(() {});
},
),
],
),
),
);
}),
);
}
}
flutter , I Want Change Qty List From StreamController ?
I want action ontap
IconButton Change data
Text(poduct[index].qty.toString()),
from StreamController
I don't want to use setState(() {});
import 'package:flutter/material.dart';
import 'dart:async';
void main() {
runApp(new MaterialApp(title: "Simple Material App", home: new MyHome()));
}
class MyHome extends StatefulWidget {
#override
MyHomeState createState() => new MyHomeState();
}
class Product {
String productName;
int qty;
Product({this.productName, this.qty});
}
class MyHomeState extends State<MyHome> {
List<Product> poduct = [Product(productName: "Nike",qty: 20),Product(productName: "Vans",qty: 30),];
var listPoduct = StreamController<List<Product>>();
#override
void initState() {
listPoduct.sink.add(poduct);
super.initState();
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("test stream"),
),
body: Container(
padding: EdgeInsets.all(8.0),
child: StreamBuilder(
stream: listPoduct.stream,
builder: (context, snapshot) {
return ListView.builder(
itemCount: poduct.length,
padding: EdgeInsets.all(10),
itemBuilder: (BuildContext context, int index){
return Padding(
padding: const EdgeInsets.only(top: 20.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(poduct[index].productName,style: TextStyle(fontSize: 24.0),),
new IconButton(icon: new Icon(Icons.remove), onPressed: (){
// How to Add ? listPoduct.sink ?
}),
Text(poduct[index].qty.toString()), /// <<< I Want Change Qty List Form StreamController
new IconButton(icon: new Icon(Icons.add), onPressed: (){
// How to Add ? listPoduct.sink ?
}),
Divider(),
],
),
);
},
);
}
),
));
}
}
I want action ontap
IconButton Change data
Text(poduct[index].qty.toString()),
from StreamController
I don't want to use setState(() {});
void main() {
runApp(new MaterialApp(title: "Simple Material App", home: new MyHome()));
}
class MyHome extends StatefulWidget {
#override
MyHomeState createState() => new MyHomeState();
}
class Product {
String productName;
int qty;
Product({this.productName, this.qty});
}
class MyHomeState extends State<MyHome> {
List<Product> poduct = [ // <<<<<<<< TYPO HERE
Product(productName: "Nike",qty: 20),
Product(productName: "Vans",qty: 30)];
var listPoduct = StreamController<List<Product>>();
#override
void initState() {
listPoduct.sink.add(poduct);
super.initState();
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("test stream"),
),
body: Container(
padding: EdgeInsets.all(8.0),
child: StreamBuilder(
stream: listPoduct.stream,
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data.length, // <<<<<<<< . note that listbuilder relies on snapshot not on your poduct property
padding: EdgeInsets.all(10),
itemBuilder: (BuildContext context, int index){
return Padding(
padding: const EdgeInsets.only(top: 20.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(poduct[index].productName,style: TextStyle(fontSize: 24.0),), // <<<<<<<< you can also use here the snapshot.data
new IconButton(icon: new Icon(Icons.remove), onPressed: () {
_update(index, -1);
}),
Text(poduct[index].qty.toString()), // <<<<<<<< you can also use here the snapshot.data
new IconButton(icon: new Icon(Icons.add), onPressed: (){
_update(index, 1);
}),
Divider(),
],
),
);
},
);
} else {
return Container()
}
}
),
));
}
_update(int index, int difference) {
for (int i = 0; i < poduct.length; i++ ) {
if (i == index) {
poduct[i] =
Product(productName: poduct[i].productName,
qty: poduct[i].qty + difference);
}
}
listPoduct.add(poduct);
}
}
some helpful links:
StreamBuilder-class
Example
I am new on dart, I just want to add a list of my data using map (store.state.availablePage.map) to the children of ListView, but I already have some item on the ListView.
Here the sample code I want :
class MgDrawer extends StatelessWidget {
#override
Widget build(BuildContext context) {
return StoreBuilder<AppState>(
builder: (context, store) {
return Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: <Widget>[
Text("Title"),
store.state.availablePage.map((value) {
return ListTile(
title: Text("Title"),
onTap: () {},
);
}).toList(),
],
),
);
},
);
}
}
Please help me how I can achieve that?
Update: the code above is not compiled.
Updates Dart Lang version > 2.2.2, can be achieve using below code :
class MgDrawer extends StatelessWidget {
#override
Widget build(BuildContext context) {
return StoreBuilder<AppState>(
builder: (context, store) {
return Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: <Widget>[
Text("Title"),
...store.state.availablePage.map((value) {
return ListTile(
title: Text("Title"),
onTap: () {},
);
}).toList(),
],
),
);
},
);
}
}
You ListView is having Text(Widget) and a Array of ListTile(Array of Widgets) which means ListView(children: [Widget, [Widget]]).
But it should be ListView(children: [Widget1, Widget2, Widget3,...]). Below code might help
class MgDrawer extends StatelessWidget {
#override
Widget build(BuildContext context) {
return StoreBuilder<AppState>(
builder: (context, store) {
List<Widget> list = store.state.availablePage.map((value) {
return ListTile(
title: Text("Title"),
onTap: () {},
);
}).toList();
list.insert(0, Text("Title"));
return Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: list,
),
);
},
);
}
}
If for some reason someone is unable to use "..." operator, there is also another solution. It is not as elegant as "..." operator, but it also works.
You can just use ..addAll(list) at the end of the list.
Here is how it would look like in given example:
class MgDrawer extends StatelessWidget {
#override
Widget build(BuildContext context) {
return StoreBuilder<AppState>(
builder: (context, store) {
return Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: <Widget>[
Text("Title"),
]..addAll(store.state.availablePage.map((value) {
return ListTile(
title: Text("Title"),
onTap: () {},
);
}).toList(),),
),
);
},
);
}
}
I get the list of files from the user's folder. The names of the files I transfer to the ListView.builder. It's work, but I think, this is bad architecture.
A method _getFilesFromDir() call with a high frequency.
How to make the correct list generation, so as not to update the interface without changing the file list?
class CharacteristList extends StatefulWidget {
#override
_CharacteristListState createState() => new _CharacteristListState();
}
class _CharacteristListState extends State<CharacteristList> {
List<String> filesList = new List<String>();
List<String> filesL = new List<String>();
#override
void initState() {
super.initState();
filesList = [];
}
Future<List<String>> _getFilesFromDir() async{
filesL = await FilesInDirectory().getFilesFromDir();
setState(() {
filesList = filesL;
});
return filesList;
}
_getFilesCount(){
_getFilesFromDir();
int count = filesList.length;
return count;
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: const Text('Список документов'),
),
body: new Column(
children: <Widget>[
new Expanded(
child: new ListView.builder(
//TODO не успевает сформировать список файлов
itemCount: _getFilesCount(),
itemBuilder: (context, index){
return new CharacteristListItem(filesList[index]);
},
),
),
],
),
floatingActionButton: new FloatingActionButton(
onPressed: () {
Navigator.push(context,
new MaterialPageRoute(builder: (context)
=> new StartScreen()),
);},
child: new Icon(Icons.add),
),
);
}
}
// add dependancy in pubspec.yaml
path_provider:
import 'dart:io' as io;
import 'package:path_provider/path_provider.dart';
//Declare Globaly
String directory;
List file = new List();
#override
void initState() {
// TODO: implement initState
super.initState();
_listofFiles();
}
// Make New Function
void _listofFiles() async {
directory = (await getApplicationDocumentsDirectory()).path;
setState(() {
file = io.Directory("$directory/resume/").listSync(); //use your folder name insted of resume.
});
}
// Build Part
#override
Widget build(BuildContext context) {
return MaterialApp(
navigatorKey: navigatorKey,
title: 'List of Files',
home: Scaffold(
appBar: AppBar(
title: Text("Get List of Files with whole Path"),
),
body: Container(
child: Column(
children: <Widget>[
// your Content if there
Expanded(
child: ListView.builder(
itemCount: file.length,
itemBuilder: (BuildContext context, int index) {
return Text(file[index].toString());
}),
)
],
),
),
),
);
}
Don't call _getFilesCount() in build(). build() can be called very frequently. Call it in initState() and store the result instead of re-reading over and over again.
I changed the architecture of the class - I used FutureBuilder.
class _CharacteristListState extends State<CharacteristList> {
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: const Text('Список документов'),
),
body: new Center(
child: new Column(
children: <Widget>[
new FutureBuilder(
future: _inFutureList(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if(snapshot.connectionState == ConnectionState.waiting){
return new Text('Data is loading...');
}
else{
return customBuild(context, snapshot);
}
}
)
],
),
),
floatingActionButton: new FloatingActionButton(
onPressed: () {
Navigator.push(context,
new MaterialPageRoute(builder: (context)
=> new StartScreen()),
);},
child: new Icon(Icons.add),
),
);
}
Widget customBuild(BuildContext context, AsyncSnapshot snapshot){
List<String> values = snapshot.data;
return new Container(
child: new Expanded(
child: new ListView.builder(
itemCount: values.length,
itemBuilder: (context, index){
return new CharacteristListItem(values[index]);
},
),
)
);
}
Future<List<String>>_inFutureList() async{
var filesList = new List<String>();
filesList = await FilesInDirectory().getFilesFromDir();
await new Future.delayed(new Duration(milliseconds: 500));
return filesList;
}
}
// add dependancy in pubspec.yaml
path_provider:
import 'dart:io' as io;
import 'package:path_provider/path_provider.dart';
//Declare Globaly
String directory;
List file = new List();
#override
void initState() {
// TODO: implement initState
super.initState();
_listofFiles();
}
// Make New Function
void _listofFiles() async {
directory = "/storage/emulated/0/Android/data/"; //Give your folder path
setState(() {
file = io.Directory("$directory/resume/").listSync(); //use your folder name insted of resume.
});
}
// Build Part
#override
Widget build(BuildContext context) {
return MaterialApp(
navigatorKey: navigatorKey,
title: 'List of Files',
home: Scaffold(
appBar: AppBar(
title: Text("Get List of Files with whole Path"),
),
body: Container(
child: Column(
children: <Widget>[
// your Content if there
Expanded(
child: ListView.builder(
itemCount: file.length,
itemBuilder: (BuildContext context, int index) {
return Text(file[index].toString());
}),
)
],
),
),
),
);
}
I'm trying to create a Radio in a showDialog, however the animation that occurs on Radio does not appear in showDialog.
For example: when tapped in foo2 nothing happens, and when you exit in showDialog and go back to it, foo2 is selected.
Below is the code and a gif showing what is happening:
import "package:flutter/material.dart";
void main() {
runApp(new ControlleApp());
}
class ControlleApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: "My App",
home: new HomePage(),
);
}
}
class HomePage extends StatefulWidget {
#override
HomePageState createState() => new HomePageState();
}
enum _RadioGroup {
foo1,
foo2
}
class HomePageState extends State<HomePage> {
_RadioGroup _itemType = _RadioGroup.foo1;
void changeItemType(_RadioGroup type) {
setState(() {
_itemType = type;
});
}
void showDemoDialog<T>({ BuildContext context, Widget child }) {
showDialog<T>(
context: context,
child: child,
);
}
#override
Widget build(BuildContext context){
return new Scaffold(
appBar: new AppBar(backgroundColor: new Color(0xFF26C6DA)),
body: new Container(
child: new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new InkWell(
onTap: (){
showDemoDialog<String>(
context: context,
child: new SimpleDialog(
title: const Text("show"),
children: <Widget>[
new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Radio<_RadioGroup>(
groupValue: _itemType,
value: _RadioGroup.foo1,
onChanged: changeItemType
),
const Text("foo1"),
new Radio<_RadioGroup>(
groupValue: _itemType,
value: _RadioGroup.foo2,
onChanged: changeItemType
),
const Text("foo2"),
],
)
],
)
);
},
child: new Container(
margin: new EdgeInsets.only(top: 16.0, bottom: 8.0),
child: new Text("Show"),
),
)
],
),
)
);
}
}
Remember that components are immutable.
When you call showDialog, the content of that dialog won't change even if HomePage does.
The solution is easy. You need to refactor a bit your code to something like :
showDialog(
context: context,
builder: (context) => MyForm()
)
and instead of changing the state of HomePage, you instead change the state of MyForm.
example :
class Test extends StatelessWidget {
void onSubmit(String result) {
print(result);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: RaisedButton(
onPressed: () => showDialog(context: context, builder: (context) => MyForm(onSubmit: onSubmit)),
child: Text("dialog"),
),
),
);
}
}
typedef void MyFormCallback(String result);
class MyForm extends StatefulWidget {
final MyFormCallback onSubmit;
MyForm({this.onSubmit});
#override
_MyFormState createState() => _MyFormState();
}
class _MyFormState extends State<MyForm> {
String value = "foo";
#override
Widget build(BuildContext context) {
return SimpleDialog(
title: Text("My form"),
children: <Widget>[
Radio(
groupValue: value,
onChanged: (value) => setState(() => this.value = value),
value: "foo",
),
Radio(
groupValue: value,
onChanged: (value) => setState(() => this.value = value),
value: "bar",
),
FlatButton(
onPressed: () {
Navigator.pop(context);
widget.onSubmit(value);
},
child: new Text("submit"),
)
],
);
}
}