I have an edit view which contains an image list.I'm using image picker to upload multiple images and created the image list.When the edit view comes I have displayed the previous uploaded images from the API and I need to edit this images(remove/add).I have done thee display and remove part but I can't use the image picker to upload more images in the edit view.Can someone please give me a solution to this.
This is the images I'm getting for edit view,
_imageGridEdit() {
return ChangeNotifierProvider.value(
value: _postGetNotifier,
child: Consumer<PostGetNotifier>(builder: (context, imgNtfr, child) {
if (imgNtfr.isLoading == true) {
return Container();
} else {
return imgNtfr.post?.images?.length == 0
? Container()
: GridView.builder(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: imgNtfr.post?.images?.length,
gridDelegate:
const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
crossAxisSpacing: 8,
mainAxisSpacing: 8),
itemBuilder: (BuildContext context, int index) {
return imgNtfr.post?.images?.length == 0
? Container()
: Stack(children: [
Container(
height: 150,
width: 150,
child: ClipRRect(
borderRadius: BorderRadius.circular(15.0),
child: Image.network(
'${Config.API_URL}/file/${imgNtfr.post?.images?[index].id}',
height: 150,
width: 200,
fit: BoxFit.cover,
)),
),
Align(
alignment: Alignment.topRight,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: 20,
width: 20,
child: FloatingActionButton(
heroTag: 'rem1',
backgroundColor: const Color(0xffED104D),
onPressed: () {
setState(() => imgNtfr.post?.images
?.removeAt(index));
},
child: const Icon(
Icons.close,
color: Colors.white,
size: 15,
),
),
),
),
)
]);
});
}
}));
}
This is how I'm displaying the images getting from image picker
_imageGrid() {
return GridView.builder(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: _imageFileList == null
? 0
: (_imageFileList!.length > 5 ? 5 : _imageFileList!.length),
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3, crossAxisSpacing: 8, mainAxisSpacing: 8),
itemBuilder: (BuildContext context, int index) {
return _imageFileList!.length == 0
? Container()
: Stack(children: [
Container(
height: 150,
width: 150,
child: ClipRRect(
borderRadius: BorderRadius.circular(15.0),
child: Image.file(
File(_imageFileList![index].path),
fit: BoxFit.cover,
)),
),
Align(
alignment: Alignment.topRight,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: 20,
width: 20,
child: FloatingActionButton(
heroTag: 'rem1',
backgroundColor: const Color(0xffED104D),
onPressed: () {
setState(() => _imageFileList?.removeAt(index));
},
child: const Icon(
Icons.close,
color: Colors.white,
size: 15,
),
),
),
),
)
]);
});
}
what I need is to use the image picker images and the edit displaying images from the API to show at the same time.
Related
I have a widget that displays icons from a server. I display all the icons in the list in one line with horizontal scrolling. I need to make sure that the icons are added in two rows at most, and if there are more of them, then add horizontal scrolling, how to do this?
Widget _amenities(PublicChargingStationModel station) {
List<Widget> assetsList = station.getAmenitiesAsset;
return SizedBox(
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: assetsList.length,
itemBuilder: (context, index) => Padding(
padding:
EdgeInsets.only(right: index == assetsList.length - 1 ? 0 : 8),
child: Container(
width: 30,
height: 30,
alignment: Alignment.center,
decoration: const BoxDecoration(
color: constants.Colors.purpleMain,
shape: BoxShape.circle,
),
child: assetsList[index],
),
),
),
);
}
Instead of using list view, you can use grid view. Like this:
SizedBox(
height: 100,
width: 300,
child: GridView.builder(
scrollDirection: Axis.horizontal,
itemCount: _list.length,
itemBuilder: (context, index) => Container(
width: 30,
height: 30,
alignment: Alignment.center,
decoration: const BoxDecoration(
color: Colors.purple,
shape: BoxShape.circle,
),
),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2, crossAxisSpacing: 8, mainAxisSpacing: 8),
),
)
I created a database using sqflite and I am rendering images from database with ImagePicker in a Staggered Grid View Builder and also on another tab with Grid View Builder. When I tap on a container, as you see, I load the images from that container.
The images are loaded after a few miliseconds, even if I am using loading bool variables. The problem is appearing when I switch the tabs, or when I enter in a container as you see below.
I dunno where is the problem, because the Grid View is created only after the images are loaded in a variable.
The code I think it's relevant:
#override
void initState() {
super.initState();
db = CleverClosetDatabase.instance;
refreshClosetOrganizer();
refreshImagesFromToBuy();
_tabController = TabController(length: 3, vsync: this, initialIndex: 0);
_tabController.addListener(_handleTabChange);
}
Future refreshClosetOrganizer() async {
setState(() => isLoadingClosetOrganizer = true);
cleverClosetOrganizer = await db.readAllClosetOrganizer();
setState(() => isLoadingClosetOrganizer = false);
}
Future refreshImagesFromClosetOrganizer(String closetOrganizer) async {
setState(() => isLoadingMyClosetAfterTap = true);
myClosetOrganizerTappedImages = await db.readAllCleverCloset(1, closetOrganizer);
setState(() => isLoadingMyClosetAfterTap = false);
}
TabBarView(
controller: _tabController,
children:[
isLoadingClosetOrganizer
? const Center(child: CircularProgressIndicator(
backgroundColor: Color(0xff393432),
valueColor: AlwaysStoppedAnimation(Color(0xffE4BCB4)),
strokeWidth: 6,
))
: !isClosetOrganizerTapped ? myClosetFirstPage() : isLoadingMyClosetAfterTap ?
const Center(child: CircularProgressIndicator(
backgroundColor: Color(0xff393432),
valueColor: AlwaysStoppedAnimation(Color(0xffE4BCB4)),
strokeWidth: 6,
))
: myClosetSecondPage(),
isLoadingToBuy ? const Center(child: CircularProgressIndicator(
backgroundColor: Color(0xff393432),
valueColor: AlwaysStoppedAnimation(Color(0xffE4BCB4)),
strokeWidth: 6,
)) :
toBuyWidgetPage(),
isLoadingOutfitPlanner ? const Center(child: CircularProgressIndicator(
backgroundColor: Color(0xff393432),
valueColor: AlwaysStoppedAnimation(Color(0xffE4BCB4)),
strokeWidth: 6,
)) :
const Text("A"),
]
),
Widget myClosetSecondPage() {
return myClosetOrganizerTappedImages.isNotEmpty ? Container(
margin: const EdgeInsets.fromLTRB(10, 65, 10, 10),
child: GridView.builder(
clipBehavior: Clip.none,
physics: const ScrollPhysics(),
shrinkWrap: true,
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
crossAxisSpacing: 5,
mainAxisSpacing: 5,
maxCrossAxisExtent: SizeConfig.screenWidth!/2,),
itemCount: myClosetOrganizerTappedImages.length,
itemBuilder: (BuildContext ctx, index) {
return Container(
decoration: const BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(20))
),
width: SizeConfig.screenWidth!/4,
height: SizeConfig.screenWidth!/4,
child: FittedBox(
child: CleverCloset.imageFromBase64String(myClosetOrganizerTappedImages[index].getImage!),
fit: BoxFit.fill,
),
);
}
),
) : Container();
}
Widget toBuyWidgetPage() {
return imagesFromToBuy.isNotEmpty ? Container(
margin: const EdgeInsets.fromLTRB(10, 10, 10, 10),
child: GridView.builder(
clipBehavior: Clip.none,
physics: const ScrollPhysics(),
shrinkWrap: true,
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
crossAxisSpacing: 5,
mainAxisSpacing: 5,
maxCrossAxisExtent: SizeConfig.screenWidth!/2,),
itemCount: imagesFromToBuy.length,
itemBuilder: (BuildContext ctx, index) {
return Container(
decoration: const BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(20))
),
width: SizeConfig.screenWidth!/4,
height: SizeConfig.screenWidth!/4,
child: FittedBox(
child: CleverCloset.imageFromBase64String(imagesFromToBuy[index].getImage!),
fit: BoxFit.fill,
),
);
}
),
) : Container();
}
I am trying to implement a search function in GridView, which is on SimpleDialog. When I perform a search, the GridView is not updating. But when I scroll through GridView, It updates.
Below is my code
Widget _showParentCategory() {
return SimpleDialog(
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: TextField(
onChanged: (value) {
finalList = myProducts
.where((product) => product["name"]
.toString()
.toLowerCase()
.contains(value.toLowerCase()))
.toList();
setState(() {
finalList;
});
},
decoration: const InputDecoration(suffixIcon: Icon(Icons.close)),
),
),
const SizedBox(
height: 20,
),
SizedBox(
height: MediaQuery.of(context).size.height * 0.7,
width: MediaQuery.of(context).size.width,
child: Container(
color: Colors.white,
child: GridView.builder(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
crossAxisSpacing: 5.0,
mainAxisSpacing: 5.0),
itemCount: finalList.length,
itemBuilder: (BuildContext context, index) {
return Column(
children: [
const CircleAvatar(
backgroundColor: Colors.red,
radius: 20.0,
),
Text(finalList[index]["name"])
],
);
},
),
),
)
],
);
}
I tried to print my finalist which is getting updated but it seems setState is not working.
How can I redraw/ refresh GridView?
is it possible to put the GridView into Carousel in flutter like this??
i don't understand about the carousel but i learn it and i get the Carousel more useful then grid-view if i follow my design?
this is my GridView Code
Container(
margin: EdgeInsets.all(2),
child: new StaggeredGridView.countBuilder(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
crossAxisCount: 2,
crossAxisSpacing: 12,
mainAxisSpacing: 12,
itemCount: imageList.length,
itemBuilder: (context, index) {
return Container(
decoration: BoxDecoration(
color: Colors.transparent,
borderRadius:
BorderRadius.all(Radius.circular(12))),
child: ClipRRect(
borderRadius:
BorderRadius.all(Radius.circular(12)),
child: FadeInImage.memoryNetwork(
placeholder: kTransparentImage,
image: imageList[index],
fit: BoxFit.cover,
),
),
);
},
staggeredTileBuilder: (index) {
return new StaggeredTile.count(
1, index.isEven ? 1 : 2);
}),
)
Yes you can simply use StaggeredGridView inside CarouselSlider. About the UI you are trying to archive, the first image(index=0) will be the large one. If we try to simplify the UI by dividing the pattern, we can see there are three GridItem can think as single bloc, and to get the left one larger we need to use StaggeredTile.count(1, index % 3 == 0 ? 2 : 1);. In this case staggeredTileBuilder will be
staggeredTileBuilder: (index) {
return StaggeredTile.count(1, index % 3 == 0 ? 2 : 1);
}),
Widget
return Scaffold(
body: CarouselSlider(
items: [
Container(
margin: EdgeInsets.all(2),
child: StaggeredGridView.countBuilder(
// physics: NeverScrollableScrollPhysics(), // it can use scollable if upper widget dont cause any issue
shrinkWrap: true,
crossAxisCount: 2,
crossAxisSpacing: 12,
mainAxisSpacing: 12,
itemCount: imageList.length,
itemBuilder: (context, index) {
return Container(
decoration: const BoxDecoration(
color: Colors.transparent,
borderRadius: BorderRadius.all(Radius.circular(12))),
child: ClipRRect(
borderRadius:
const BorderRadius.all(Radius.circular(12)),
child: Container(
color: Colors.amber,
alignment: Alignment.center,
child: Text(index.toString()),
)
// FadeInImage.memoryNetwork(
// // placeholder: kTransparentImage,
// image: imageList[index],
// fit: BoxFit.cover,
// ),
),
);
},
staggeredTileBuilder: (index) {
return StaggeredTile.count(1, index % 3 == 0 ? 2 : 1);
}),
),
Container(
color: Colors.deepPurple,
),
Container(
color: Colors.deepOrange,
),
],
options: CarouselOptions(aspectRatio: 1, viewportFraction: 1),
),
);
I would say practice with Text Widget with viewing index to understand what and how widget is changing and set the logic inside staggeredTileBuilder to get the outcome. And about the imagePath you aren't passing string value on that, debug/print the path to verify it.
For more about
carousel_slider
flutter_staggered_grid_view
Staggered Grid View on yt you can find many by searching
need some help between the word and images, I want them to space a little bit and dun want them to touch each other.
Example like this :
The output of my own code with images :
return Scaffold(
body: SafeArea(
child: Stack(
children: [
Column(
children: [
Expanded(
child: Card(
color: Colors.grey[200],
child: GridView.builder(
primary: false,
padding: const EdgeInsets.all(10),
gridDelegate:
const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisSpacing: 20,
mainAxisSpacing: 20,
crossAxisCount: 2),
itemCount: 10,
itemBuilder: (BuildContext context, int index) {
Widget widget;
switch (index) {
case 0:
widget = Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.grey[100],
),
child: GridTile(
child: Image.network(
'https://static.nike.com/a/images/t_prod_ss/w_640,c_limit,f_auto/qebbe6yb2crumsanfyu4/sacai-x-nike-ldwaffle-black-release-date.jpg',
),
footer: Container(
color: Colors.black54,
height: 40,
child: const GridTileBar(
title: Text('Sacai x Nike Ldwaffle Black',
maxLines: 2),
),
),
),
);
break;
Do not use Stack widget, just put Column, set parent base on the column.