Flutter ListView item's image changes temporarily each other - flutter

Hello I want to make the Listview when I tapped the item, it removes and insert that item in the last of the item list.
removing and inserting is working, but the problem is image.
I use item's image.
If I tapped the item, it reordered by removing and inserting.
during the removing and inserting, Item's image changes each other temporarily.
It seems like flickering. I used AnimatedList first, I think that AnimatedList is the reason for the problem. So, I changed it ListView. But It has same problem. I use image by circleAvatar. and i use CachedNetworkImageProvider.
my english is short and it is first use of stackoverflow.
thank you for understanding.
This is my problem
and this is my Listview
companionListView(List<Companion> companions) {
return Container(
height: 60,
width: 60.0 * (companions.length),
child: Center(
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: companions.length,
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
if (companions[index].id == 0) {
return Align(
widthFactor: 0.57,
child: SizedBox(
width: index == 0 || index == companions.length - 1 ? 50 : 100,
height: 30,
),
);
} else {
return companionSelection[companions[index].id] == true
? Align(
widthFactor: 0.57,
child: Stack(
overflow: Overflow.visible,
children: [
GestureDetector(
onTap: () {
removeCompanion(companions, index);
if (selectedList.isEmpty) {
Provider.of<SelectionText>(context, listen: false).unselected();
} else if (selectedList.length != customerCompanions.length) {
Provider.of<SelectionText>(context, listen: false).coexist();
} else {
Provider.of<SelectionText>(context, listen: false).allSelected();
}
print('selectedList');
print(selectedList);
},
child: CircleAvatar(
backgroundColor: Color(0xFFffffff),
radius: 30,
backgroundImage: companions[index].image.isNotEmpty
? CachedNetworkImageProvider(companions[index].image)
: AssetImage('assets/images/abcd.png'),
),
),
Positioned(
top: 0,
left: 0,
child: Image.asset('assets/images/border_check_y.png', width: 20, height: 20))
],
),
)
: Align(
widthFactor: 0.57,
child: Stack(
overflow: Overflow.visible,
children: [
GestureDetector(
onTap: () {
removeCompanion(companions, index);
if (selectedList.isEmpty) {
Provider.of<SelectionText>(context, listen: false).unselected();
} else if (selectedList.length != customerCompanions.length) {
Provider.of<SelectionText>(context, listen: false).coexist();
} else {
Provider.of<SelectionText>(context, listen: false).allSelected();
}
print('selectedList');
print(selectedList);
},
child: ColorFiltered(
colorFilter: ColorFilter.mode(Colors.grey[300], BlendMode.modulate),
child: CircleAvatar(
backgroundColor: Color(0xFFffffff),
radius: 30,
backgroundImage: companions[index].image.isNotEmpty
? CachedNetworkImageProvider(companions[index].image)
: AssetImage('assets/images/abcd.png'),
),
),
),
Positioned(
top: 0,
left: 0,
child: Image.asset('assets/images/border_check_g.png', width: 20, height: 20))
],
),
);
}
},
),
),
);
}
code for removing and inserting item
removeCompanion(List<Companion> companions, int index) {
for (int i = 0; i < companions.length; i++) {
if (companions[i].id == 0) {
idx = i;
break;
}
}
companionSelection[companions[index].id] == false
? companionSelection.update(companions[index].id, (value) => true)
: companionSelection.update(companions[index].id, (value) => false);
if (idx < index) {
companions.insert(idx, companions[index]);
companions.removeAt(index + 1);
selectedList.add(companions[index]);
} else {
companions.add(companions[index]);
companions.remove(companions[index]);
selectedList.removeAt(index);
}
}

need code your widgets tree. May be toy not use Key in itemList widgets?

Related

Refreshing ListView.builder with ToggleButton flutter

Basically, I'm trying to make an app, that on one of the screens - the content of a listview will be updated by choosing one of the options listed in the toggleButtons (One shows only upcoming events and the second option is events that have been passed). But when I try to set the new state, it doesn't reload the listview and doesn't colour the selected option in the ToggleButtons. How can I refresh both?
For reference:
List filteredCands = []; //Starts empty, gets filled with events when clicking one of the buttons
List isSelected = [true, false];
ToggleButtons and setState(():
child: ToggleButtons(
isSelected: isSelected,
selectedColor: Colors.white,
color: Color(0xFF33CCCC),
fillColor: Color(0xFF33CCCC),
renderBorder: true,
borderWidth: 1.5,
borderRadius: BorderRadius.circular(10),
children: const [
Padding(
padding: EdgeInsets.symmetric(horizontal: 12),
child: Icon(FontAwesomeIcons.calendarXmark, size: 25),
),
Padding(
padding: EdgeInsets.symmetric(horizontal: 12),
child: Icon(FontAwesomeIcons.calendarDay, size: 25),
),
],
onPressed: (int newIndex) {
final data = listViewGetCandListByManagerResponse
.jsonBody['candList'] as List;
List<CandModel> cands = data.map((e) => CandModel.fromJson(e))
.toList();
DateTime now = new DateTime.now();
DateTime currentDate = new DateTime(now.year, now.month, now.day);
setState(() {
//looping through the list of bool values
for (int index = 0; index < isSelected.length; index++)
{
//Checking for the index value
if (index == newIndex)
{
isSelected[index] = true;
if (index == 0)
{
for (var i = 0; i < cands.length; i++) {
DateTime expirationDate = DateTime.parse(cands[i].dateEvent);
final bool isExpired = expirationDate.isBefore(currentDate);
if (isExpired == true) {
filteredCands.add(cands[i]);
}
}
}
if (index == 1)
{
for (var i = 0; i < cands.length; i++) {
DateTime expirationDate = DateTime.parse(cands[i].dateEvent);
final bool isFuture = currentDate.isBefore(expirationDate);
if (isFuture == true) {
filteredCands.add(cands[i]);
}
}
}
}
else
{isSelected[index] = false;}
}
});
},
),
That's the ListView:
child: Padding(
padding: EdgeInsetsDirectional.fromSTEB(0, 8, 0, 0),
child: FutureBuilder<ApiCallResponse>(
future: GetCandListByManagerCall.call(
entityId: widget.entityId,
),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: SizedBox(
width: 50,
height: 50,
child: CircularProgressIndicator(
color:
FlutterFlowTheme.of(context).primaryColor,
),
),
);
}
return Builder(
builder: (context) {
if (filteredCands.isEmpty) {
return Center(
child: Text('Error - Looks like there are no events available'
),
);
}
return ListView.builder(
padding: EdgeInsets.zero,
scrollDirection: Axis.vertical,
itemCount: filteredCands.length,
itemBuilder: (context, dataIndex) {
if (!snapshot.hasData) {
return Center(
child: SizedBox(
width: 50,
height: 50,
child: CircularProgressIndicator(
color: FlutterFlowTheme.of(context).primaryColor,
),
),
);
}
int count = 0;
String date = (filteredCands[dataIndex].dateEvent).toString();
DateTime tempDate = DateTime.parse(date);
String dmy = DateFormat.yMMMd().format(tempDate);
String exDate = dmy; //Date Formatting
return InkWell(
child: SworkerContainerWidget(
desc: filteredCands[dataIndex].descEvent,
fname: filteredCands[dataIndex].wfirstName,
lname: filteredCands[dataIndex].wlastName,
dateEvent: exDate,
),
);
},
);
},
);
And the results:
As you can see, I'm clicking the 2nd option and it doesn't colour it nor refreshing the listview
Check where you first declared on your list. this might be the cause of the problem (found out I misplaced it) it need to go under class __widgetstate and not under builder.
Also would recommend to clear the listview everytime the button gets clicked, unless you want infinite events on your list haha

How to get the image path after selecting multiple images using pickMultiImage of image_picker in flutter

I'm trying to select multiple images so for this i used pickMultiImage method of image_picker.
Images are displaying on screen, but i need their path so that i can use it to upload on cloudinary.com.
here is my code
List<XFile>? _imageFileList3 = [];
Future pickMultipleImage() async {
if (_imageFileList3!.length == 4) {
showDialog(
context: context,
builder: (BuildContext context) {
return LoginSucessDailog(
text: 'You can\'t add more than 4 images.',
title: 'Warning.',
img: 'assets/img/alert.png');
});
} else {
try {
var image = await _picker.pickMultiImage();
//here i'll be using cloudinary code
setState(() {
_imageFileList3!.addAll(image!);
});
print(image);
print(_imageFileList3!.length);
setState(() {
isImageLoading = false;
});
} on CloudinaryException catch (e) {}
}
}
this is the part of code i'm using to upload images on Cloudinary using cloudinary_public package
CloudinaryResponse response = await cloudinary.uploadFile(
CloudinaryFile.fromFile(image!.path,
resourceType: CloudinaryResourceType.Image),
);
displaying images like this
addProductsImages() {
if (_imageFileList3!.length != 0) {
return SizedBox(
height: 80,
width: MediaQuery.of(context).size.width * 0.9,
child: GridView.builder(
shrinkWrap: true,
itemCount: _imageFileList3!.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 4,
),
itemBuilder: (BuildContext context, int index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Stack(children: [
ClipRRect(
borderRadius: BorderRadius.circular(10.0),
child: Image.file(
File((_imageFileList3![index].path)),
width: MediaQuery.of(context).size.width * 0.35,
height: MediaQuery.of(context).size.height * 0.17,
fit: BoxFit.cover,
),
),
Align(
alignment: Alignment.topRight,
child: buildCancelIcon(Colors.white, () {
setState(() {
// _imageFileList!.removeAt(index);
});
}, Icons.cancel))
]));
}));
} else {
return Padding(
padding: const EdgeInsets.only(left: 70),
child:
Row(crossAxisAlignment: CrossAxisAlignment.center, children: []));
}
}
please help how to do this, or is there any way to select multiple images at once and upload them on cloudinary.
Please refer to below example code where user can pick maximum 5 images
Using these packages
images_picker: ^1.2.4
flutter_image_compress: ^0.7.0
class PickMultipleImagesScreen extends StatefulWidget {
const PickMultipleImagesScreen({Key key}) : super(key: key);
#override
_PickMultipleImagesScreenState createState() =>
_PickMultipleImagesScreenState();
}
class _PickMultipleImagesScreenState extends State<PickMultipleImagesScreen> {
final ValueNotifier<bool> attachMultipleImages = ValueNotifier<bool>(false);
List compressedPhotosList = ["place_holder"];
int maxImagesCount = 5;
pickPhotos() async {
List<Media> photosList = [];
photosList = await ImagesPicker.pick(
count: (compressedPhotosList != null &&
(compressedPhotosList.isNotEmpty) &&
(compressedPhotosList.length > 1))
? (maxImagesCount + 1 - compressedPhotosList.length)
: maxImagesCount,
pickType: PickType.all,
language: Language.System,
cropOpt: CropOption(
aspectRatio: CropAspectRatio(600, 400),
),
);
if (photosList != null && photosList.isNotEmpty && photosList.length > 0) {
for (int i = 0; i < photosList.length; i++) {
File photoCompressedFile =
await compressImage(File(photosList[i].path));
print("Images List: $photosList");
print("Path of UnCompressed File: ${photosList[i].path}");
compressedPhotosList.insert(
0,
photoCompressedFile.path.toString(),
);
print("Path of Compressed File: ${photoCompressedFile.path}");
print("Compressed Images List: $compressedPhotosList");
}
attachMultipleImages.value = !attachMultipleImages.value;
}
}
Future<File> compressImage(File file) async {
final filePath = file.absolute.path;
final lastIndex = filePath.lastIndexOf(new RegExp(r'.png|.jp'));
final splitted = filePath.substring(0, (lastIndex));
final outPath = "${splitted}_out${filePath.substring(lastIndex)}";
if (lastIndex == filePath.lastIndexOf(new RegExp(r'.png'))) {
final compressedImage = await FlutterImageCompress.compressAndGetFile(
filePath, outPath,
minWidth: 1000,
minHeight: 1000,
quality: 50,
format: CompressFormat.png);
return compressedImage;
} else {
final compressedImage = await FlutterImageCompress.compressAndGetFile(
filePath,
outPath,
minWidth: 1000,
minHeight: 1000,
quality: 50,
);
return compressedImage;
}
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: ValueListenableBuilder<bool>(
valueListenable: attachMultipleImages,
builder: (context, snapshot, child) {
return Scaffold(
body: (compressedPhotosList != null &&
compressedPhotosList.isNotEmpty &&
compressedPhotosList.length > 1)
? GridView.builder(
itemCount: (compressedPhotosList != null &&
compressedPhotosList.isNotEmpty &&
compressedPhotosList.length > 1 &&
(compressedPhotosList.length - 1 == maxImagesCount))
? compressedPhotosList.length - 1
: compressedPhotosList.length,
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
crossAxisSpacing: 4.0,
mainAxisSpacing: 4.0),
itemBuilder: (BuildContext context, int index) {
return ((compressedPhotosList[index] == "place_holder") &&
compressedPhotosList.length - 1 != maxImagesCount)
? InkWell(
onTap: () async {
if (compressedPhotosList.length - 1 !=
maxImagesCount) {
pickPhotos();
}
},
child: Container(
margin: EdgeInsets.all(
5.0,
),
width: ScreenUtil().screenWidth,
height: ScreenUtil().setHeight(105.0),
color: Colors.blueAccent,
child: Center(
child: Icon(
Icons.add,
size: ScreenUtil().setSp(24.0),
color: Colors.grey,
),
),
),
)
: Stack(
clipBehavior: Clip.none,
children: [
ClipRRect(
borderRadius: BorderRadius.circular(4.0),
child: Image.file(
File(compressedPhotosList[index]),
fit: BoxFit.fitHeight,
width: ScreenUtil().screenWidth,
height: ScreenUtil().setHeight(105.0),
filterQuality: FilterQuality.low,
errorBuilder: (context, error, stackTrace) {
return Container(
width: ScreenUtil().screenWidth,
height: ScreenUtil().setHeight(105.0),
color: Colors.black,
);
},
),
),
Positioned(
bottom: 10,
right: 8,
child: InkWell(
onTap: () async {
compressedPhotosList.removeAt(index);
attachMultipleImages.value =
!attachMultipleImages.value;
},
child: CircleAvatar(
radius: 15.0,
backgroundColor: Colors.black45,
child: Icon(
Icons.delete_forever,
color: Colors.white,
size: 20,
),
),
),
)
],
);
},
)
: Center(
child: InkWell(
onTap: () {
pickPhotos();
},
child: Text("Attach Images"),
),
),
);
}
),
);
}
}

Flutter FutureBuilder calling function continuously

I have simple function which is calling data from firestore and filtering data. But issue is my futurebuilder keeps on loader situation (Data is called successfully i can see in console but now showing in future) I think its because my fucntion is calling in loop or something i have try to print something in my function which indicates me that my function is not stopping and thats why i think my futureBuilder keeps on loading.
My code
Future<List> getCustomerList() async {
print('calling');
String uUid1 = await storage.read(key: "uUid");
String uName1 = await storage.read(key: "uName");
String uNumber1 = await storage.read(key: "uNumber");
setState(() {
uUid = uUid1;
uName = uName1;
uNumber = uNumber1;
});
CollectionReference _collectionRef =
FirebaseFirestore.instance.collection('Customers');
QuerySnapshot querySnapshot = await _collectionRef.get();
// Get data from docs and convert map to List
List allData = querySnapshot.docs
.where((element) => element['sellerUID'] == uUid)
.map((doc) => doc.data())
.toList();
double gGive = 0;
double gTake = 0;
double gCal = 0;
for (int i = 0; i < allData.length; i++) {
// print(allData[i]);
// print('give ${double.parse(allData[i]['give'].toString()) }');
// print('take ${double.parse(allData[i]['take'].toString()) }');
double.parse(allData[i]['give'].toString()) -
double.parse(allData[i]['take'].toString()) >
0
? gGive += double.parse(allData[i]['give'].toString()) -
double.parse(allData[i]['take'].toString())
: gTake += double.parse(allData[i]['give'].toString()) -
double.parse(allData[i]['take'].toString());
}
// print(gGive);
// print(gTake);
setState(() {
Gtake = gGive.toString().replaceAll("-", "");
Ggive = gTake.toString().replaceAll("-", "");
});
if (greenBox) {
var check = allData.where((i) => i['take'] > i['give']).toList();
return check;
} else if (redBox) {
var check = allData.where((i) => i['give'] > 1).toList();
return check;
} else {
return allData;
}
}
And my futureBuilder look like this
Expanded(
child: Container(
height: Height * 0.5,
child: FutureBuilder(
future: getCustomerList(),
builder: (context, snapshot) {
if (snapshot.hasData) {
list = snapshot.data;
return SingleChildScrollView(
child: Column(
children: [
Container(
height: Height * 0.5,
child: ListView.builder(
shrinkWrap: true,
itemCount: list.length,
itemBuilder:
(BuildContext context,
int index) {
var showThis = list[index]
['give'] -
list[index]['take'];
return list[index]
['customerName']
.toString()
.contains(searchString)
? GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
CustomerData(
data: list[
index])),
);
},
child: Padding(
padding:
const EdgeInsets
.only(
left: 13,
right: 13),
child: Container(
decoration:
BoxDecoration(
border: Border(
top: BorderSide(
color: Colors
.grey,
width:
.5)),
),
child: Padding(
padding:
const EdgeInsets
.all(
13.0),
child: Row(
mainAxisAlignment:
MainAxisAlignment
.spaceBetween,
children: [
Row(
children: [
CircleAvatar(
child:
Text(
list[index]['customerName'][0]
.toString(),
style:
TextStyle(fontFamily: 'PoppinsBold'),
),
backgroundColor:
Color(0xffF7F9F9),
),
SizedBox(
width:
20,
),
Text(
list[index]['customerName']
.toString(),
style: TextStyle(
fontFamily:
'PoppinsMedium'),
),
],
),
Text(
'RS ${showThis.toString().replaceAll("-", "")}',
style: TextStyle(
fontFamily:
'PoppinsMedium',
color: list[index]['give'] - list[index]['take'] <
0
? Colors.green
: Colors.red),
),
],
),
),
),
),
)
: Container();
},
),
)
],
),
);
} else
return Center(
heightFactor: 1,
widthFactor: 1,
child: SizedBox(
height: 70,
width: 70,
child: CircularProgressIndicator(
strokeWidth: 2.5,
),
),
);
}),
),
),
I am damn sure its because futurebuilder keeps calling function which is returning data but because of keeps calling functions my Futurebuilder keeps showing loading.
You should not call setState inside the future that you are giving to the FutureBuilder.
The state actualization will cause the FutureBuilder to re-build. Meaning triggering the future again, and ... infinite loop !

change story items as dynamic widgets in flutter

I want to implement story items as different widgets. Like in this example:
In this picture, only images are changed, but I want to change as whole widgets as story items.
I have tried the story_view package. But, in this package, only images and videos can be added. Is there any other library for that?
As explained by https://stackoverflow.com/users/8164116/daksh-gargas, story view can be easily implemented using stack pageview and a simple gesture detector.
Made a simple story view -
import 'package:flutter/material.dart';
class CustomStoryView extends StatefulWidget{
#override
_CustomStoryViewState createState() => _CustomStoryViewState();
}
class _CustomStoryViewState extends State<CustomStoryView> with SingleTickerProviderStateMixin {
final List _colorsList = [Colors.blue, Colors.red, Colors.green, Colors.yellow, Colors.grey, Colors.brown];
final PageController _controller = PageController();
double _progressIndicators;
int _page = 0;
AnimationController _animationController;
bool dragEnded = true;
Size _pageSize;
#override
void initState() {
_animationController = AnimationController(vsync: this, duration: Duration(seconds: 2));
_animationController.addListener(animationListener);
_animationController.forward();
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
_pageSize = MediaQuery.of(context).size;
_progressIndicators = (_pageSize.width - 100) / 6;
});
super.initState();
}
#override
void dispose() {
_animationController?.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: [
PageView.builder(
controller: _controller,
physics: NeverScrollableScrollPhysics(),
itemBuilder: (context, index)=>GestureDetector(
onLongPressStart: _onLongPressStart,
onLongPressEnd: _onLongPressEnd,
onHorizontalDragEnd: _onHorizontalDragEnd,
onHorizontalDragStart: _onHorizontalDragStart,
onHorizontalDragUpdate: _onHorizontalDragUpdate,
onTapUp: _onTapDown,
child: Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
color: _colorsList[index],
child: Center(child: InkWell(
onTap: (){
print("thiswasclicked $index");
},
child: Text("Somee random text", style: TextStyle(fontSize: 36),)),),
),
),
itemCount: _colorsList.length,
),
Positioned(
top: 48,
left: 0,
right: 0,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: ([0,1,2,3,4,5].map((e) =>
(e == _page) ? Stack(
children: [
Container(
width: _progressIndicators,
height: 8 ,
color: Colors.black54,
),
AnimatedBuilder(
animation: _animationController,
builder: (ctx, widget){
return AnimatedContainer(
width: _progressIndicators * _animationController.value,
height: 8 ,
color: Colors.white,
duration: Duration(milliseconds: 100),
);
},
),
],
): Container(
width: _progressIndicators,
height: 8 ,
color: (_page >= e) ? Colors.white : Colors.black54,
)).toList()),
),)
],
),
);
}
animationListener(){
if(_animationController.value == 1){
_moveForward();
}
}
_moveBackward(){
if(_controller.page != 0){
setState(() {
_page = (_controller.page - 1).toInt();
_page = (_page < 0) ? 0 : _page;
_controller.animateToPage(_page, duration: Duration(milliseconds: 100), curve: Curves.easeIn);
_animationController.reset();
_animationController.forward();
});
}
}
_moveForward(){
if(_controller.page != (_colorsList.length - 1)){
setState(() {
_page = (_controller.page + 1).toInt();
_controller.animateToPage(_page, duration: Duration(milliseconds: 100), curve: Curves.easeIn);
_animationController.reset();
_animationController.forward();
});
}
}
_onTapDown(TapUpDetails details) {
var x = details.globalPosition.dx;
(x < _pageSize.width / 2) ? _moveBackward() : _moveForward();
}
_onHorizontalDragUpdate(d){
if (!dragEnded) {
dragEnded = true;
if (d.delta.dx < -5) {
_moveForward();
} else if (d.delta.dx > 5) {
_moveBackward();
}
}
}
_onHorizontalDragStart(d) {
dragEnded = false;
}
_onHorizontalDragEnd(d) {
dragEnded = true;
}
_onLongPressEnd(_){
_animationController.forward();
}
_onLongPressStart(_){
_animationController.stop();
}
}
This can be easily achieved with Stack, Container, and a GestureDetector to switch between pages/stories.
Why Stacks?
Flutter's Stack is useful if you want to overlap several
children in a simple way, for example, having some text and an image,
overlaid with a gradient and a button attached to the bottom.
To handle your "fixed" views, which are, in this case:
Top Progress bar... you can create your custom progress bar if you want.
That image and the user name...
Let's call them myTopFixedWidgets()
Row(children: [CircleAvatar(...),Column(children: [Text(...),Text(...)],)],)
Now, put your Widget that you want to display and that changes (your "story") as the first item of the Stacks and place the Widgets 1. and 2. (mentioned above) in the second item of the list.
Maintain a variable index to choose the widget that you want to display.
Stack(
children: <Widget>[
widgetsToShowAsAStory[index],
myTopFixedWidgets() //mentioned above
],
)
Wrap it inside GestureDetector
List<Widget> widgetsToShowAsAStory = [];
var index = 0;
....
GestureDetector(
onTap: () {
//If the tap is on the LEFT side of the screen then decrement the value of the index
index-= 1; //(check for negatives)
//If the tap is on the RIGHT side of the screen then increment the value of the index
index+= 1; //(check for the size of list)
//call
setState() {}
},
child: Stack(
children: <Widget>[
widgetsToShowAsAStory[index],
myTopFixedWidgets()
],
),)
and boom, you're good to go!
I found solutions from the story_view. But it doesnot match my requirement. We can only show different widgets as stories items in story_view.We can't perform any actions on widgets. To implement this story_view and to show different widgets as stories. Do like this.
First import story_view flutter dependencies from here.
Then import this in main.dart file.
import "package:story_view/story_view.dart";
StoryView(
controller: controller,
storyItems: [
StoryItem.inlineImage(
url:
"https://images.unsplash.com/photo-1536063211352-0b94219f6212?ixid=MXwxMjA3fDB8MHxzZWFyY2h8MXx8YmVhdXRpZnVsJTIwZ2lybHxlbnwwfHwwfA%3D%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=500&q=60",
controller: controller,
),
StoryItem(
new Container(
margin: EdgeInsets.all(12),
child: StaggeredGridView.countBuilder(
crossAxisCount: 2,
crossAxisSpacing: 10,
mainAxisSpacing: 12,
itemCount: imageList.length,
itemBuilder: (context, index) {
return Container(
decoration: BoxDecoration(
color: Colors.transparent,
borderRadius: BorderRadius.all(
Radius.circular(15))),
child: ClipRRect(
borderRadius: BorderRadius.all(
Radius.circular(15)),
child: FadeInImage.memoryNetwork(
placeholder: kTransparentImage,
image: imageList[index],
fit: BoxFit.cover,
),
),
);
},
staggeredTileBuilder: (index) {
return StaggeredTile.count(
1, index.isEven ? 1.2 : 1.8);
}),
),
duration: aLongWeekend,
shown: true),
StoryItem(
new Container(
margin: EdgeInsets.all(12),
child: StaggeredGridView.countBuilder(
crossAxisCount: 2,
crossAxisSpacing: 10,
mainAxisSpacing: 12,
itemCount: imageList.length,
itemBuilder: (context, index) {
return Container(
decoration: BoxDecoration(
color: Colors.transparent,
borderRadius: BorderRadius.all(
Radius.circular(15))),
child: ClipRRect(
borderRadius: BorderRadius.all(
Radius.circular(15)),
child: FadeInImage.memoryNetwork(
placeholder: kTransparentImage,
image: imageList[index],
fit: BoxFit.cover,
),
),
);
},
staggeredTileBuilder: (index) {
return StaggeredTile.count(
1, index.isEven ? 1.2 : 1.8);
}),
),
duration: aLongWeekend,
shown: true),
],
onStoryShow: (s) {
print("Showing a story");
},
onComplete: () {
print("Completed a cycle");
},
progressPosition: ProgressPosition.top,
repeat: false,
inline: false,
),

GestureDetector not detecting inside of List.generate

I have the following streambuilder below. If I put the GestureDetector on the Row widget (as indicated below) it receives the gesture. However, when I put it as shown, it does not. My current theory is that it is due to the List.generation there, however, I guess it could be because there are other widgets above it? It's in a Stack widget...although, if that's the case, why would the GestureDetector work on the Row widget?)
return StreamBuilder<List<List<Event>>>(
stream: widget.controller.stream.map(_filter),
initialData: Provider.of<CalendarData>(context).dayEvents,
builder: (context, snapshot) {
return Row(
//GESTUREDETECTOR WORKS HERE
children: List.generate(8, (col) {
if (col == 0) {
return Expanded(
child: GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () {
print('tapped: beer'); //<-- col
},
onScaleStart: (scaleDetails) => setState(() {
print('previousNumOfDays:$previousNumOfDays');
print('numberOfDays:$numberOfDays');
// dayIndexScaleCenter = col;
print('dayIndexScaleCenter: $dayIndexScaleCenter');
previousNumOfDays = numberOfDays;
}),
onScaleUpdate: (ScaleUpdateDetails scaleDetails) {
setState(() {
int newNumberOfDays =
(previousNumOfDays / scaleDetails.scale).round();
print('previousNumOfDays:$previousNumOfDays');
print('numberOfDays:$numberOfDays');
print('newNumberOfDays:$newNumberOfDays');
if (newNumberOfDays <= 14 && newNumberOfDays > 1) {
numberOfDays = newNumberOfDays;
}
});
},
child: Column(
children: List.generate(
hours.length,
(row) => Container(
height: Provider.of<CalendarData>(context).rowHeight,
decoration: BoxDecoration(
color: ColorDefs.colorTimeBackground,
border: Border(
top: BorderSide(
width: 1.0,
color: ColorDefs.colorCalendarHeader),
),
),
child: Center(
child: AutoSizeText(hours[row],
maxLines: 1,
group: timeAutoGroup,
minFontSize: 5,
style: ColorDefs.textSubtitle2),
),
),
),
),
),
);
}