Related
I have a page where I crop and trim the video.
When I initialize a VideoEditorController and for example edit the video, or just navigate back to previous page. And then I get method channel error and all CachedVideoPlayer widgets show a black screen. if we rebuild the widget with CachedVideoPlayer it'll play. And if we try to repeat the same process again for some strange reason CachedVideoPlayers won't crash.
I'm testing on a real device(Iphone 12 mini).
Error:
MissingPluginException(No implementation found for method cancel on channel flutter.io/videoPlayer/videoEvents171)
How I initialize VideoEditorController
#override
void initState() {
super.initState();
_controller = VideoEditorController.file(widget.file,
maxDuration: const Duration(seconds: 30))
..initialize().then((_) => setState(() {
_controller.preferredCropAspectRatio = widget.aspectRatio;
showTrimmer = true;
}));
}
CropScreen
class CropScreen extends StatefulWidget {
const CropScreen({
Key? key,
required this.file,
required this.exportedFile,
required this.aspectRatio,
}) : super(key: key);
final File file;
final double aspectRatio;
final Function(File) exportedFile;
#override
State<CropScreen> createState() => _CropScreenState();
}
class _CropScreenState extends State<CropScreen> {
late VideoEditorController _controller;
final double height = 60;
bool showTrimmer = false;
final ValueNotifier<bool> _isLoadingNotifier = ValueNotifier(false);
void show() {
_isLoadingNotifier.value = true;
}
void hide() {
_isLoadingNotifier.value = false;
}
#override
void initState() {
super.initState();
_controller = VideoEditorController.file(widget.file,
maxDuration: const Duration(seconds: 30))
..initialize().then((_) => setState(() {
_controller.preferredCropAspectRatio = widget.aspectRatio;
showTrimmer = true;
}));
}
#override
void dispose() {
// TODO: implement dispose
super.dispose();
_controller.dispose();
}
#override
Widget build(BuildContext context) {
return ValueListenableBuilder<bool>(
valueListenable: _isLoadingNotifier,
builder: (context, value, child) {
return Stack(
children: [
Stack(
children: [
Scaffold(
backgroundColor: Colors.black,
body: SafeArea(
child: Padding(
padding: const EdgeInsets.all(30),
child: Column(children: [
Row(children: [
Expanded(
child: IconButton(
onPressed: () => _controller
.rotate90Degrees(RotateDirection.left),
icon: const Icon(
Icons.rotate_left,
color: white,
),
),
),
Expanded(
child: IconButton(
onPressed: () => _controller
.rotate90Degrees(RotateDirection.right),
icon: const Icon(
Icons.rotate_right,
color: white,
),
),
)
]),
const SizedBox(height: 15),
Expanded(
child: CropGridViewer(
controller: _controller, horizontalMargin: 60),
),
const SizedBox(
height: 15,
),
showTrimmer
? Column(
mainAxisAlignment: MainAxisAlignment.center,
children: _trimSlider(context))
: SizedBox(height: 100),
const SizedBox(height: 15),
Row(children: [
Expanded(
child: IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: Center(
child: Text(
"Cancel",
style: MainTheme.of(context)
.bodyText1
.copyWith(fontWeight: FontWeight.w600),
),
),
),
),
buildSplashTap("21:9", 21 / 9,
padding:
const EdgeInsets.symmetric(horizontal: 10)),
buildSplashTap("1:1", 1 / 1),
buildSplashTap("4:5", 4 / 5,
padding:
const EdgeInsets.symmetric(horizontal: 10)),
buildSplashTap("NO", null,
padding: const EdgeInsets.only(right: 10)),
Expanded(
child: IconButton(
onPressed: () async {
//2 WAYS TO UPDATE CROP
//WAY 1:
show();
_controller.updateCrop();
await _controller.exportVideo(
onCompleted: (file) {
print(file!.path);
widget.exportedFile(file);
hide();
Navigator.pop(context);
});
/*WAY 2:
controller.minCrop = controller.cacheMinCrop;
controller.maxCrop = controller.cacheMaxCrop;
*/
},
icon: Center(
child: Text(
"Crop",
style: MainTheme.of(context)
.bodyText1
.copyWith(fontWeight: FontWeight.w600),
),
),
),
),
]),
]),
),
),
),
],
),
if (value)
BackdropFilter(
filter: ImageFilter.blur(sigmaX: 4.0, sigmaY: 4.0),
child: const Opacity(
opacity: 0.8,
child:
ModalBarrier(dismissible: false, color: Colors.black),
),
),
if (value)
Center(
child: FutureBuilder(
future: Future.delayed(Duration(milliseconds: 500)),
builder: (context, snapshot) {
return const SpinKitFadingCircle(
size: 60, color: primary);
},
),
),
],
);
});
}
Widget buildSplashTap(
String title,
double? aspectRatio, {
EdgeInsetsGeometry? padding,
}) {
return InkWell(
onTap: () => _controller.preferredCropAspectRatio = aspectRatio,
child: Padding(
padding: padding ?? EdgeInsets.zero,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Icon(Icons.aspect_ratio, color: Colors.white),
Text(
title,
style: const TextStyle(fontWeight: FontWeight.bold, color: white),
),
],
),
),
);
}
List<Widget> _trimSlider(BuildContext context) {
return [
AnimatedBuilder(
animation: _controller.video,
builder: (_, __) {
final duration = _controller.video.value.duration.inSeconds;
final pos = _controller.trimPosition * duration;
final start = _controller.minTrim * duration;
final end = _controller.maxTrim * duration;
return Padding(
padding: EdgeInsets.symmetric(horizontal: height / 4),
child: Row(children: [
Text(
formatter(Duration(seconds: pos.toInt())),
style: MainTheme.of(context).bodyText1,
),
const Expanded(child: SizedBox()),
OpacityTransition(
visible: _controller.isTrimming,
child: Row(mainAxisSize: MainAxisSize.min, children: [
Text(
formatter(Duration(seconds: start.toInt())),
style: MainTheme.of(context).bodyText1,
),
const SizedBox(width: 10),
Text(
formatter(Duration(seconds: end.toInt())),
style: MainTheme.of(context).bodyText1,
),
]),
)
]),
);
},
),
Container(
width: MediaQuery.of(context).size.width,
margin: EdgeInsets.symmetric(vertical: height / 4),
child: TrimSlider(
controller: _controller,
height: height,
horizontalMargin: height / 4,
child: TrimTimeline(
controller: _controller,
margin: const EdgeInsets.only(top: 10))),
)
];
}
String formatter(Duration duration) => [
duration.inMinutes.remainder(60).toString().padLeft(2, '0'),
duration.inSeconds.remainder(60).toString().padLeft(2, '0')
].join(":");
}
To use VideoEditorController you need to add this package:
video_editor: ^1.4.1
Dart SDK:
sdk: ">=2.16.1 <3.0.0"
I want to change color of every icon after pressing. But all of icons in a ExpandableContainerchange after pressing one of them.
class _ExpandableListViewState extends State<ExpandableListView> {
bool expandFlag = false;
Color _iconColor = Colors.white;
#override
Widget build(BuildContext context) {
return new Container(
margin: new EdgeInsets.symmetric(vertical: 1.0),
child: new Column(
children: <Widget>[
new Container(
.
.
.
),
new ExpandableContainer(
expanded: expandFlag,
expandedHeight: ...
child: new ListView.builder(
itemBuilder: (BuildContext context, int index) {
return new Container(
decoration:
new BoxDecoration(border: new Border.all(width: 1.0, color: Colors.grey), color: Colors.black),
child: new ListTile(
title: ...
leading: new IconButton(
icon: Icon(Icons.star, color: _iconColor),
onPressed: () {
setState(() {
_iconColor = _iconColor == Colors.white ? Colors.yellow : Colors.white;
});
},
),
subtitle: ...
),
);
},
itemCount: ...,
))
],
),
);
}
}
class ExpandableContainer extends StatelessWidget {
final bool expanded;
final double expandedHeight;
final Widget child;
ExpandableContainer({
#required this.child,
this.expandedHeight,
this.expanded = true,
});
#override
Widget build(BuildContext context) {
.
.
.
}
Whole code:
import 'package:flutter/material.dart';
import 'data.dart';
void main() {
runApp(new MaterialApp(home: new Home()));
}
class Home extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new Scaffold(
backgroundColor: Colors.grey,
appBar: new AppBar(
title: new Text("Expandable List", style: TextStyle(color: Colors.black)),
backgroundColor: Colors.lightGreen,
),
body: new ListView.builder(
itemBuilder: (BuildContext context, int index) {
return new ExpandableListView(title: broadcast[index].title, ind: index);
},
itemCount: broadcast.length,
),
);
}
}
class ExpandableListView extends StatefulWidget {
final String title;
final int ind;
const ExpandableListView({this.title, this.ind});
#override
_ExpandableListViewState createState() => new _ExpandableListViewState();
}
class _ExpandableListViewState extends State<ExpandableListView> {
bool expandFlag = false;
Color _iconColor = Colors.white;
#override
Widget build(BuildContext context) {
return new Container(
margin: new EdgeInsets.symmetric(vertical: 1.0),
child: new Column(
children: <Widget>[
new Container(
color: Colors.blue[300],
padding: new EdgeInsets.symmetric(horizontal: 5.0),
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
new IconButton(
icon: new Container(
height: 50.0,
width: 50.0,
decoration: new BoxDecoration(
color: Colors.deepOrange,
shape: BoxShape.circle,
),
child: new Center(
child: new Icon(
expandFlag ? Icons.keyboard_arrow_up : Icons.keyboard_arrow_down,
color: Colors.white,
size: 30.0,
),
),
),
onPressed: () {
setState(() {
expandFlag = !expandFlag;
});
}),
new Text(
widget.title,
style: new TextStyle(fontWeight: FontWeight.bold,fontSize: 20.0, color: Colors.black87),
)
],
),
),
new ExpandableContainer(
expanded: expandFlag,
expandedHeight: 90.0 * (broadcast[widget.ind].contents.length < 4 ? broadcast[widget.ind].contents.length : 4), // + (0.0 ?: 29.0),
child: new ListView.builder(
itemBuilder: (BuildContext context, int index) {
return new Container(
decoration:
new BoxDecoration(border: new Border.all(width: 1.0, color: Colors.grey), color: Colors.black),
child: new ListTile(
title: new Text(
broadcast[widget.ind].contents[index],
style: new TextStyle(fontWeight: FontWeight.bold, color: Colors.lightGreen),
textAlign: TextAlign.right,
),
leading: new IconButton(
icon: Icon(Icons.star, color: _iconColor),
onPressed: () {
setState(() {
_iconColor = _iconColor == Colors.white ? Colors.yellow : Colors.white;
});
},
),
subtitle: new Text ('${broadcast[widget.ind].team[index]}\n${broadcast[widget.ind].time[index]} ${broadcast[widget.ind].channel[index]}',
textAlign: TextAlign.right, style:TextStyle(color: Colors.white)),
isThreeLine: true,
),
);
},
itemCount: broadcast[widget.ind].contents.length,
))
],
),
);
}
}
class ExpandableContainer extends StatelessWidget {
final bool expanded;
final double expandedHeight;
final Widget child;
//final Color iconColor;
ExpandableContainer({
#required this.child,
this.expandedHeight,
this.expanded = true,
//this.iconColor,
});
#override
Widget build(BuildContext context) {
double screenWidth = MediaQuery.of(context).size.width;
return new AnimatedContainer(
duration: new Duration(milliseconds: 100),
curve: Curves.easeInOut,
width: screenWidth,
height: expanded ? expandedHeight : 0.0,
child: new Container(
child: child,
decoration: new BoxDecoration(border: new Border.all(width: 1.0, color: Colors.blue)),
),
);
}
}
You need to make the list item a StatefulWidget in which you have the state _iconColor
Stateful List Tile
class StatefulListTile extends StatefulWidget {
const StatefulListTile({this.subtitle, this.title});
final String subtitle, title;
#override
_StatefulListTileState createState() => _StatefulListTileState();
}
class _StatefulListTileState extends State<StatefulListTile> {
Color _iconColor = Colors.white;
#override
Widget build(BuildContext context) {
return new Container(
decoration: new BoxDecoration(
border: new Border.all(width: 1.0, color: Colors.grey),
color: Colors.black),
child: new ListTile(
title: new Text(
widget?.title ?? "",
style: new TextStyle(
fontWeight: FontWeight.bold, color: Colors.lightGreen),
textAlign: TextAlign.right,
),
leading: new IconButton(
icon: Icon(Icons.star, color: _iconColor),
onPressed: () {
setState(() {
_iconColor =
_iconColor == Colors.white ? Colors.yellow : Colors.white;
});
},
),
subtitle: new Text(widget?.subtitle ?? "",
textAlign: TextAlign.right, style: TextStyle(color: Colors.white)),
isThreeLine: true,
),
);
}
}
Usage
class ExpandableListView extends StatefulWidget {
final String title;
final int ind;
const ExpandableListView({this.title, this.ind});
#override
_ExpandableListViewState createState() => new _ExpandableListViewState();
}
class _ExpandableListViewState extends State<ExpandableListView> {
bool expandFlag = false;
Color _iconColor = Colors.white;
#override
Widget build(BuildContext context) {
return new Container(
margin: new EdgeInsets.symmetric(vertical: 1.0),
child: new Column(
children: <Widget>[
new Container(
color: Colors.blue[300],
padding: new EdgeInsets.symmetric(horizontal: 5.0),
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
new IconButton(
icon: new Container(
height: 50.0,
width: 50.0,
decoration: new BoxDecoration(
color: Colors.deepOrange,
shape: BoxShape.circle,
),
child: new Center(
child: new Icon(
expandFlag
? Icons.keyboard_arrow_up
: Icons.keyboard_arrow_down,
color: Colors.white,
size: 30.0,
),
),
),
onPressed: () {
setState(() {
expandFlag = !expandFlag;
});
}),
new Text(
widget.title,
style: new TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20.0,
color: Colors.black87),
)
],
),
),
new ExpandableContainer(
expanded: expandFlag,
expandedHeight: 90.0 *
(broadcast[widget.ind].contents.length < 4
? broadcast[widget.ind].contents.length
: 4), // + (0.0 ?: 29.0),
child: new ListView.builder(
itemBuilder: (BuildContext context, int index) {
return StatefulListTile(
title: broadcast[widget.ind].contents[index],
subtitle:
'${broadcast[widget.ind].team[index]}\n${broadcast[widget.ind].time[index]} ${broadcast[widget.ind].channel[index]}',
);
},
itemCount: broadcast[widget.ind].contents.length,
))
],
),
);
}
}
You should make the color property distinct for each element in the ListView, what you are doing is that the color is global and shared among all the icons in the ListView, for this reason all icons are changing their color when one icon is pressed.
class Broadcast {
final String title;
List<String> contents;
List<String> team = [];
List<String> time = [];
List<String> channel = [];
Color iconColor = Colors.white; //initialize at the beginning
Broadcast(this.title, this.contents, this.team, this.time, this.channel); //, this.icon);
}
edit your ExpandableListView
class ExpandableListView extends StatefulWidget {
final int ind;
final Broadcast broadcast;
const ExpandableListView({this.broadcast,this.ind});
#override
_ExpandableListViewState createState() => new _ExpandableListViewState();
}
edit your Home class
class Home extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new Scaffold(
backgroundColor: Colors.grey,
appBar: new AppBar(
title: new Text("Expandable List", style: TextStyle(color: Colors.black)),
backgroundColor: Colors.lightGreen,
),
body: new ListView.builder(
itemBuilder: (BuildContext context, int index) {
return new ExpandableListView(title: broadcast[index], ind: index);
},
itemCount: broadcast.length,
),
);
}
}
edit your _ExpandableListViewState
class _ExpandableListViewState extends State<ExpandableListView> {
bool expandFlag = false;
#override
Widget build(BuildContext context) {
return new Container(
margin: new EdgeInsets.symmetric(vertical: 1.0),
child: new Column(
children: <Widget>[
new Container(
color: Colors.blue[300],
padding: new EdgeInsets.symmetric(horizontal: 5.0),
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
new IconButton(
icon: new Container(
height: 50.0,
width: 50.0,
decoration: new BoxDecoration(
color: Colors.deepOrange,
shape: BoxShape.circle,
),
child: new Center(
child: new Icon(
expandFlag ? Icons.keyboard_arrow_up : Icons.keyboard_arrow_down,
color: Colors.white,
size: 30.0,
),
),
),
onPressed: () {
setState(() {
expandFlag = !expandFlag;
});
}),
new Text(
widget.broadcast.title,
style: new TextStyle(fontWeight: FontWeight.bold,fontSize: 20.0, color: Colors.black87),
)
],
),
),
new ExpandableContainer(
expanded: expandFlag,
expandedHeight: 90.0 * (broadcast[widget.ind].contents.length < 4 ? broadcast[widget.ind].contents.length : 4), // + (0.0 ?: 29.0),
child: new ListView.builder(
itemBuilder: (BuildContext context, int index) {
return new Container(
decoration:
new BoxDecoration(border: new Border.all(width: 1.0, color: Colors.grey), color: Colors.black),
child: new ListTile(
title: new Text(
broadcast[widget.ind].contents[index],
style: new TextStyle(fontWeight: FontWeight.bold, color: Colors.lightGreen),
textAlign: TextAlign.right,
),
leading: new IconButton(
icon: Icon(Icons.star, color: widget.broadcast.iconColor),
onPressed: () {
setState(() {
widget.broadcast.iconColor = widget.broadcast.iconColor == Colors.white ? Colors.yellow : Colors.white;
});
},
),
subtitle: new Text ('${broadcast[widget.ind].team[index]}\n${broadcast[widget.ind].time[index]} ${broadcast[widget.ind].channel[index]}',
textAlign: TextAlign.right, style:TextStyle(color: Colors.white)),
isThreeLine: true,
),
);
},
itemCount: broadcast[widget.ind].contents.length,
))
],
),
);
}
}
Edit:
Home Page - I'm fetching a list of strings from my firebase collection. I then want to make a call to firestore storage and get the downloadable image link and store it in a list that I will pass to Page 2. The code below is how i'm getting the downloadable links.
Future<List<String>> test(List images) async{
List<String> listOfImages = List<String>();
for(int i = 0; i < images.length; i++){
final ref = FirebaseStorage.instance.ref().child(images[i]);
var url = await ref.getDownloadURL();
listOfImages.add(url);
}
return listOfImages;
}
I'm then passing the list of Images in the following manner
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => CarDetailScreen(
carImages: test( car['images'])
)),
);
Page 2 - I'm receiving a Future> that I would like to convert to a List
List<T> map<T>(List list, Function handler) {
List<T> result = [];
for (var i = 0; i < list.length; i++) {
result.add(handler(i, list[i]));
}
return result;
}
new CarouselSlider(
items: ***["This is where I need a List"]***.map((url) {
return new Container(
margin: new EdgeInsets.all(5.0),
child:
new GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ViewCarImages(
carImages: _getImages(snapshot))),
);
},
child:
new ClipRRect(
borderRadius: new BorderRadius.all(new Radius.circular(5.0)),
child:
new Image.network(
url,
fit: BoxFit.cover,
width: 1000.0,
)
)
)
);
}).toList(),
viewportFraction: 0.9,
aspectRatio: 2.0,
autoPlay: false,
)
You can just return a List of Widget, like this:
Future<List<Widget>> test(List images) async{
List<Widget> listOfImages = List<Widget>();
for(int i = 0; i < images.length; i++){
final ref = FirebaseStorage.instance.ref().child(images[i]);
var url = await ref.getDownloadURL();
listOfImages.add(Image.network(url));
}
return listOfImages;
}
Below code will solve your problem. In carouselSlide class(check items variable) written below and you need to follow below procedure to work the Future object in carousel
#override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
appBar: AppBar(
backgroundColor: Colors.white,
title: Text("some text",
style: TextStyle(
fontWeight: FontWeight.normal,
color: Colors.black,
fontSize: 16.0)),
centerTitle: false,
actions: <Widget>[
IconButton(
tooltip: 'Search something',
icon: Icon(
Icons.search,
color: SharedColor().sapphireDarkBlue,
),
onPressed: () async {
var selected = await showSearch<int>(
context: context, delegate: _delegate);
if (selected != null && selected != _lastIntegerSelected) {
setState(() {
//pass the data from searchfield query to here
});
}
},
),
],
automaticallyImplyLeading: false,
),
body: _carouselBuild(),
);
}
FutureBuilder<caraouselImage> _carouselBuild() {
return FutureBuilder<caraouselImage>(
future: ImageRestApiManager().caraouselImage(myEmail),
builder: (context, AsyncSnapshot<caraouselImage> snapshot) {
if (snapshot.hasData) {
return CarouselSlider(
items: snapshot.data.collection.map((i) {
return Builder(builder: (BuildContext context) {
return Container(
margin: EdgeInsets.all(5.0),
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(5.0)),
child: Stack(children: <Widget>[
Image.network(i.imageurl,
fit: BoxFit.cover, width: 1000.0),
Positioned(
bottom: 0.0,
left: 0.0,
right: 0.0,
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Color.fromARGB(200, 0, 0, 0),
Color.fromARGB(0, 0, 0, 0)
],
begin: Alignment.bottomCenter,
end: Alignment.topCenter,
),
),
padding: EdgeInsets.symmetric(
vertical: 10.0, horizontal: 20.0),
child: Text(
_currentCookieSelected.toString(),
style: TextStyle(
color: Colors.white,
fontSize: 20.0,
fontWeight: FontWeight.bold,
),
),
),
),
]),
),
);
});
}).toList(),
autoPlay: false,
enlargeCenterPage: true,
viewportFraction: 0.9,
aspectRatio: 2.0,
onPageChanged: (index) {
setState(() {
_currentImageSelected = snapshot.data.collection[index].id;
});
});
} else {
return CircularProgressIndicator();
}
});
}
}
I solved using below youtube tutorial
https://www.youtube.com/watch?v=xBLtPDHvT44
A FutureBuilder should get you wht you're looking for. Here, I've wrapped your CarouselSlider in a FutureBuilder, and have the future property set to your carImages Future. When your list of Strings is ready, the FutureBuilder will create the CarouselSlider via its builder method, and all of the list items will be present then:
return FutureBuilder<List<String>>(
future: carImages,
initialData: [],
builder: (context, snapshot) {
return new CarouselSlider(
viewportFraction: 0.9,
aspectRatio: 2.0,
autoPlay: false,
items: snapshot.data.map((url) {
return new Container(
margin: new EdgeInsets.all(5.0),
child:
new GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => ViewCarImages(
carImages: _getImages(snapshot))),
);
},
child: new ClipRRect(
borderRadius: new BorderRadius.all(new Radius.circular(5.0)),
child: new Image.network(
url,
fit: BoxFit.cover,
width: 1000.0,
)
)
)
);
}).toList(),
);
}
);
This question already has answers here:
ListView does not refresh whereas attached list does (Flutter)
(2 answers)
Closed 4 years ago.
I'm trying to create an app where I am able to get data from Cloud Firestore and create multiple custom widgets with the data.
The custom widget is eventCardWidget
import 'package:flutter/material.dart';
import 'package:do_and_stuff/settings/theme.dart';
class EventCardWidget extends StatelessWidget {
EventCardWidget(this.eventImage, this.eventTitle, this.eventDescription,
this.eventAddress, this.eventDate, this.eventTime, this.peopleRequired);
String eventTitle;
String eventAddress;
String eventDate;
String eventImage;
String eventTime;
String eventDescription;
int peopleRequired;
#override
Widget build(BuildContext context) {
return Material(
child: GestureDetector(
child: InkWell(
splashColor: ThemeSettings.CardInkwell,
onTap: () {},
child: Card(
elevation: 1.0,
margin: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 14.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
margin: const EdgeInsets.only(right: 19.0),
width: 100.0,
height: 100.0,
child: Image.asset(this.eventImage, scale: .5),
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Row(
children: <Widget>[
Expanded(
child: Container(
margin: const EdgeInsets.only(
top: 12.0, bottom: 10.0),
child: Text(
eventTitle,
style: TextStyle(
fontSize: 18.0,
color: Colors.black,
fontWeight: FontWeight.bold,
),
),
),
),
Container(
margin: const EdgeInsets.only(right: 10.0),
child: Text(
this.eventAddress,
style: TextStyle(
fontSize: 16.0,
fontWeight: FontWeight.bold,
color: Colors.grey[600]),
),
),
],
),
Container(
margin: const EdgeInsets.only(right: 10.0),
child: Text(
this.eventDescription,
style: TextStyle(
fontSize: 16.0,
),
maxLines: 3,
overflow: TextOverflow.ellipsis,
),
),
Container(
padding: EdgeInsets.fromLTRB(0.0, 25.0, 0.0, 0.0),
margin: const EdgeInsets.only(top: 10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
this.eventDate,
style: TextStyle(
color: Colors.grey[500],
fontSize: 11.0,
),
),
Container(
margin: const EdgeInsets.only(right: 10.0),
child: Text(peopleRequired.toString())),
],
),
),
],
),
),
],
),
),
),
),
);
}
}
Now, above my Widget build(BuildContext context) {
I have
List<Widget> cards = [];
and then within the Widget build(BuildContext context) { I have children: cards,
So at this point, this page would open up with cards being initialized empty.
But, I now have
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) async {
final List results = await db.getEvent(
DateFormat("y-MM-dd").format(DateTime.now()),
DateFormat("y-MM-dd").format(DateTime.now().add(Duration(days: 20))),
2,
);
for (DocumentSnapshot result in results) {
cards.add(EventCardWidget(
"assets/flutter-icon.png",
result.data.values
.toList()[result.data.keys.toList().indexOf("name")],
result.data.values
.toList()[result.data.keys.toList().indexOf("description")],
"1 mi",
"2018-10-29",
// result.data.values
// .toList()[result.data.keys.toList().indexOf("eventDate")],
"Time",
result.data.values
.toList()[result.data.keys.toList().indexOf("num")],
));
setState(() {
return cards;
});
}
});
}
Now, in Android Studio, I am able to see that cards has more elements when I set breakpoints, but nothing updates on the screen.
Now what's weird, is that when I do something like
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) async {
final List results = await db.getEvent(
DateFormat("y-MM-dd").format(DateTime.now()),
DateFormat("y-MM-dd").format(DateTime.now().add(Duration(days: 20))),
2,
);
for (DocumentSnapshot result in results) {
setState(() {
return cards = List.generate(
3,
(i) => new EventCardWidget(
"assets/flutter-icon.png",
"Title",
"Description",
"12 mi",
"2018-10-29",
"Time",
5),
growable: true,
);
});
}
});
}
Then the text on the screen updates.
Any ideas?
This is not a duplicate because I have tried the solution Here and it still does not work
for (DocumentSnapshot result in results) {
setState(() {
cards = List.from(cards)
..add(EventCardWidget(
"assets/flutter-icon.png",
result.data.values
.toList()[result.data.keys.toList().indexOf("name")],
result.data.values
.toList()[result.data.keys.toList().indexOf("description")],
"1 mi",
"2018-10-29",
result.data.values.toList()[
result.data.keys.toList().indexOf("peopleRequired")],
));
});
}
Your code started working for me when I did this
for (DocumentSnapshot result in results) {
cards = List.from(cards)
..add(EventCardWidget(
"assets/flutter-icon.png",
result.data.values
.toList()[result.data.keys.toList().indexOf("name")],
result.data.values
.toList()[result.data.keys.toList().indexOf("description")],
"1 mi",
"2018-10-29",
"8:00pm",
result.data.values
.toList()[result.data.keys.toList().indexOf("peopleRequired")],
));
setState(() {
this.cards = cards;
});
}
Map item;
List data;
Future getdata() async{
http.Response response= await http.get(Uri.encodeFull("https://talaikis.com/api/quotes/"));
item=json.decode(response.body);
setState(() {
data=item["quotes"];
});
debugPrint(data.toString());
}
I want to display this request in stateful widget which is like this
#override
Widget build(BuildContext context) {
return new Scaffold(
drawer: drawerLeft(),
appBar: AppBar(
title: Text(
"IN TIME",
style: TextStyle(color: Colors.black, fontWeight: FontWeight.w700),
),
backgroundColor: clr,
elevation: 0.0,
leading: MaterialButton(
child: Icon(
Icons.view_headline,
color: Colors.black,
),
onPressed: () {
scaffoldKey.currentState.openDrawer();
},
)),
key: scaffoldKey,
body: AnimatedContainer(
padding: EdgeInsets.only(top: 50.0),
duration: Duration(milliseconds: 1000),
curve: Curves.ease,
color: clr,
child: PageView.builder(
itemCount: 7, //7days
onPageChanged: (int page) {
this.setState(() {
Random rnd;
rnd = new Random();
int r = 0 + rnd.nextInt(_colors.length - 0);
clr = _colors[r];
});
},
controller: pageViewController,
itemBuilder: (BuildContext context, int index) {
return Padding(
padding: const EdgeInsets.only(left: 10.0),
child: Stack(
children: <Widget>[
Container(
decoration: new BoxDecoration(
borderRadius: BorderRadius.circular(20.0),
color: Colors.white,
),
height:
MediaQuery.of(scaffoldKey.currentContext).size.height -
150.0,
width:
MediaQuery.of(scaffoldKey.currentContext).size.width -
20.0,
child: Stack(
children: <Widget>[
Positioned(
width: MediaQuery.of(scaffoldKey.currentContext)
.size
.width -
100.0,
left: index != currentPage
? getMappedValue(20.0, 100.0, 160.0, 20.0, pos)
: getMappedValue(20.0, 100.0, 20.0, -120.0, pos),
top: 20.0,
child: Opacity(
opacity: index != currentPage
? getMappedValue(20.0, 100.0, 0.0, 01.0, pos)
: getMappedValue(20.0, 100.0, 01.0, 00.0, pos),
child: Column(
children: <Widget>[
Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
_days[index],
maxLines: 1,
softWrap: true,
style: TextStyle(
color: Colors.deepOrange,
fontSize: 22.0,
fontWeight: FontWeight.w600),
),
],
),
Padding(
padding: const EdgeInsets.only(top: 15.0),
child: Text(
'Quote for the day',
softWrap: true,
style: TextStyle(
fontSize: 30.0,
fontWeight: FontWeight.w300),
),
),
],
),
),
),
],
),
),
],
),
);
},
),
),
);
}
}
*Please help me out *
If I understand, you want to display the quotes under some padding that are being retrieved to your List which I'll assume to be an inferenced List<String>. If so, you could just use a ListView within your widget tree to display every fetched item in that list, like so:
(...)
data != null
? Padding(
padding: const EdgeInsets.only(top: 15.0),
child: ListView.builder(
itemCount: data.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text(data[index]),
);
},
),
)
: Container(),
(...)