I need to change categories layout like this Flutter - flutter

I need to change categories layout like this Flutter
Its code of Multi Vendor - Flutter woocommerce app :
code:
class _ShopCategoryScreenState extends State<ShopCategoryScreen> {
void _toShopList(Category cat) {
final model = Provider.of<ShopCategoryModel>(context, listen: false);
model.setCatId(cat.id!);
model.getProducts();
Navigator.of(context).push(MaterialPageRoute(
builder: (_) => ShopProductListScreen.category(
name: cat.name,
ctx: context,
)));
}
Widget _catItem(Category cat) {
return InkWell(
onTap: () => _toShopList(cat),
child: Column(
children: [
Text(
cat.name ?? '',
style: Theme.of(context).textTheme.subtitle1,
),
],
),
);
}
#override
Widget build(BuildContext context) {
return Consumer<ShopCategoryModel>(
builder: (_, model, __) => GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: MediaQuery.of(context).orientation ==
Orientation.landscape ? 3: 2,
crossAxisSpacing: 8,
mainAxisSpacing: 8,
),
itemBuilder: (_, index) => model.isGettingCategories
? _catLoadingItem()
: _catItem(model.categories[index]),
itemCount: model.isGettingCategories ? 5 : model.categories.length,
),
);
}
}
Please help to change above code to same image that i shared ..thanks

Related

i want to add a row in listview.builder but it goes blank

i want to add a row ( list of buttons that do filter the list), i tried wrapping listTile in column, listview.builde in column but it doesn't work. tried wrapping GetBuilder also but it doesn't work.
enter image description here
My Code :-
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:quizzy/data_controller.dart';
import '../models/showQuestion.dart';
class AllQuestionBank extends StatefulWidget {
const AllQuestionBank({Key? key}) : super(key: key);
#override
State<AllQuestionBank> createState() => _AllQuestionBankState();
}
class _AllQuestionBankState extends State<AllQuestionBank> {
final DataController controller = Get.put(DataController());
#override
Widget build(BuildContext context) {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
controller.getQuestionList();
});
return Scaffold(
appBar: AppBar(
title: const Text(' Question Bank'),
),
body: GetBuilder<DataController>(
builder: (controller) => controller.QuestionList.isEmpty
? const Center(
child: Text('😔 NO DATA FOUND (: 😔'),
)
: ListView.builder(
itemCount: controller.QuestionList.length,
itemBuilder: (context, index) {
return ListTile(
title: showQuestion(controller.QuestionList[index]),
);
}),
),
);
}
}
You could redefine your ListView as:
ListView.builder(
itemCount: controller.QuestionList.length + 1,
itemBuilder: (context, index) {
if (index == 0) {
return WhateverRowYouWant();
}
return ListTile(
title: showQuestion(controller.QuestionList[index - 1]),
);
}),
You can just define the scroll direction to be horizontal.
ListView.builder(
itemCount: controller.QuestionList.length,
scrollDirection: Axis.horizontal, <- added this line
itemBuilder: (context, index) {
return ListTile(
title: showQuestion(controller.QuestionList[index]),
);
}),
You can also find an example from the official docs here
Try this.
physics: NeverScrollableScrollPhysics(), shrinkWrap: true,
To add Row() on top you need Column() widget for sure
After that, you have to wrap ListView.builder() with the Expanded() widget this will help you
Ex.
return Scaffold(
body: SafeArea(
child: Column(
children: [
Row(
children: [
TextButton(
onPressed: () {},
child: Text('Filter'),
),
],
),
Expanded(
child: GetBuilder<DataController>(
builder: (controller) => controller.QuestionList.isEmpty
? const Center(
child: Text('😔 NO DATA FOUND (: 😔'),
)
: ListView.builder(
shrinkWrap: true,
itemCount: controller.QuestionList.length,
itemBuilder: (context, index) {
return ListTile(
title: showQuestion(controller.QuestionList[index]),
);
},
),
),
),
],
),
),
);
Please, try this!!
This is the combination of GetxController and ListView with a top row I use:
class MyController extends GetxController {
var isRunning = true.obs; // set to isRunning.value = false; if done loading QuestionList
RxList<ProductModel> QuestionList = <ProductModel>[].obs;
}
Obx( () => controller.isRunning.isTrue
? 'Loading'
: ListView.builder(
itemCount: controller.QuestionList.length + 1,
itemBuilder: (BuildContext context, int index) {
if (index == 0) {
return Text('TOP ROW');
}
return ListTile(
title: showQuestion(controller.QuestionList[index - 1]),
);
}),
);

I need to change this ListView to GridView Flutter

I need to change this ListView to GridView Flutter .Thanks
#override
Widget build(BuildContext context) {
return Consumer<ShopCategoryModel>(
builder: (_, model, __) => ListView.separated(
shrinkWrap: true,
separatorBuilder: (_, index) => const Divider(),
itemBuilder: (_, index) => model.isGettingCategories
? _catLoadingItem()
: _catItem(model.categories[index]),
itemCount: model.isGettingCategories ? 5 : model.categories.length,
),
);
}
I have done minor modification to show it as a grid. Though if it is not as per you, please share the design you want to achieve.
GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: MediaQuery.of(context).orientation ==
Orientation.landscape ? 3: 2,
crossAxisSpacing: 8,
mainAxisSpacing: 8,
)
itemCount:model.isGettingCategories ? 5 : model.categories.length,
shrinkWrap: true,
itemBuilder: (_,index,) => model.isGettingCategories
? _catLoadingItem()
: _catItem(model.categories[index]),
)
Use Widget GridView for list Item and rebuild UI when change
var _isListView = true;
#override
Widget build(BuildContext context) {
return Column(
children: [
TextButton(
onPressed: () {
setState(() {
_isListView = !_isListView
});
},
child: Text("Switch"),
),
Consumer<ShopCategoryModel>(
builder: (_, model, __) =>
_isListView ? ListView.separated() : GridView.builder(),
)
],
);
}

How to build only specific objects in the screen

I have built an app that shows images like Pinterest
like that;
And, When I scroll down, after passing 25 images, my build widget refreshs the page and adds new 25 images to the screen and my screen has 50 images and so on. However, this takes me again the top of the screen because of adding new 25 images. because of that, I see again the images that I already see.
And, I want to don't refresh the page again while adding new 25 images but my builder widget works only in this way.
My class file that has builder widget;
class HomeView extends StatefulWidget {
#override
_HomeViewState createState() => _HomeViewState();
}
class _HomeViewState extends State<HomeView> {
HomeViewModel viewModel;
#override
Widget build(BuildContext context) {
return BaseView<HomeViewModel>(
onModelReady: (model) {
model.init();
model.setContext(context);
viewModel = model;
},
builder: (context, value) => buildScaffold,
model: HomeViewModel(),
);
}
Scaffold get buildScaffold {
return Scaffold(
body: CustomScrollView(
/* physics: BouncingScrollPhysics(), */
slivers: <Widget>[
buildSliverAppBar,
buildSliverStaggeredGrid,
],
),
);
}
SliverAppBar get buildSliverAppBar {
return SliverAppBar(
floating: true,
pinned: true,
snap: false,
backgroundColor: Colors.white,
title: buildSearchField,
actions: <Widget>[buildIconButtonClose, buildanotherbutton],
);
}
TextField get buildSearchField {
return TextField(
controller: viewModel.searchController,
decoration: InputDecoration(hintText: "Search...", border: InputBorder.none),
onSubmitted: (String keyword) => viewModel.loadImages(keyword),
);
}
IconButton get buildIconButtonClose {
return IconButton(
onPressed: () => viewModel.resetImages(),
icon: Icon(Icons.close, color: Colors.black),
);
}
IconButton get buildanotherbutton {
return IconButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Passaword()),
);
},
icon: Icon(Icons.ac_unit, color: Colors.black),
);
}
Widget get buildSliverStaggeredGrid {
return SliverPadding(
padding: EdgeInsets.all(0),
sliver: Observer(builder: (_) {
return viewModel.loadingImages
? SliverToBoxAdapter(
child: Center(child: CircularProgressIndicator()))
: SliverStaggeredGrid.countBuilder(
crossAxisCount: 2,
itemCount: viewModel.images.length,
itemBuilder: (BuildContext context, int index) =>
buildImageTile(index),
crossAxisSpacing: 5,
mainAxisSpacing: 10,
staggeredTileBuilder: (int index) {
return buildStaggeredTile(viewModel.images[index]);
},
);
}),
);
}
StaggeredTile buildStaggeredTile(UnsplashImage image) {
double aspectRatio = image.height / image.width;
double columnWidth = MediaQuery.of(context).size.width / 2;
return StaggeredTile.extent(1, aspectRatio * columnWidth);
}
Widget buildImageTile(int index) {
return FutureBuilder(
future: viewModel.loadImage(index),
builder: (context, snapshot) => ImageTileWidget(image: snapshot.data),
);
}
}
If you want my whole code, I can share with you. I thought my file that has builder widget code is enough to solve the problem.
my builder widget here;
Widget get buildSliverStaggeredGrid {
return SliverPadding(
padding: EdgeInsets.all(0),
sliver: Observer(builder: (_) {
return viewModel.loadingImages
? SliverToBoxAdapter(
child: Center(child: CircularProgressIndicator()))
: SliverStaggeredGrid.countBuilder(
crossAxisCount: 2,
itemCount: viewModel.images.length,
itemBuilder: (BuildContext context, int index) =>
buildImageTile(index),
crossAxisSpacing: 5,
mainAxisSpacing: 10,
staggeredTileBuilder: (int index) {
return buildStaggeredTile(viewModel.images[index]);
},
);
}),
);
}

How to implement checkbox over GridView correctly

I have checkbox for selecting and deselecting photos.
There is a visible loading screen for each tap.
_mediaList has the photo asset. mediaModel has the necessary methods to add and remove the path of selected and deselected photos respectively.
Widget build(BuildContext context) {
super.build(context);
return GridView.builder(
itemCount: _mediaList.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3, mainAxisSpacing: 4.0, crossAxisSpacing: 4.0),
itemBuilder: (BuildContext context, int index) {
final saved = mediaModel.getMedia().contains(
_mediaList[index].relativePath + '/' + _mediaList[index].title);
return FutureBuilder(
future: _mediaList[index].thumbDataWithSize(200, 200),
builder: (BuildContext context, snapshot) => snapshot.hasData
? GridTile(
header: saved
? Icon(Icons.check_circle, color: Colors.white,)
: Icon(Icons.check_circle_outline, color: Colors.white,),
child: GestureDetector(
child: Image.memory(
snapshot.data,
fit: BoxFit.cover,
),
onTap: () => setState(() => saved
? mediaModel.removeMedia(
_mediaList[index].relativePath +
'/' +
_mediaList[index].title)
: mediaModel.addMedia(
_mediaList[index].relativePath +
'/' +
_mediaList[index].title))),
)
: Container());
},
);
}
EDIT: After some analysis, I found out using Provider to load images might be the right way.
Can you help me in converting this code to Provider?
Thanks in advance!!!
Screenshot:
Full code:
class FooPage extends State<SoPage> {
static const int _count = 10;
final List<bool> _checks = List.generate(_count, (_) => false);
#override
Widget build(BuildContext context) {
return Scaffold(
body: GridView.builder(
itemCount: _count,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
itemBuilder: (_, i) {
return Stack(
children: [
Container(color: Colors.red[(i * 100) % 900]),
Align(
alignment: Alignment.topCenter,
child: Checkbox(
value: _checks[i],
onChanged: (newValue) => setState(() => _checks[i] = newValue),
),
),
],
);
},
),
);
}
}

how to create an icon on image with inkwell after Click on the image in flutter

I made a grid view in the flutter app. But like the Pictures on the below link , I want to create an icon on the picture and change the background color After tap the picture,
I've been looking for ways, but I've finally got a question. I'd appreciate it from the bottom of my heart if you'd let me know.
Please enter img link(below)
https://firebasestorage.googleapis.com/v0/b/instaclone-2-fd9de.appspot.com/o/post%2F12344.png?alt=media&token=89d46c03-83ba-4d30-b716-e9b718c1340b
Widget _bodyBuilder() {
// TODO : 그 예시를 어떻해 stream View로 보여줄것인가
return StreamBuilder <QuerySnapshot>(
stream: _commentStream(),
builder: (BuildContext context, AsyncSnapshot snapshot){
if(!snapshot.hasData){
return Center(child: CircularProgressIndicator());
}
var items = snapshot.data?.documents ??[];
var fF = items.where((doc)=> doc['style'] == "오피스룩").toList();
var sF = items.where((doc)=> doc['style'] == "로맨틱").toList();
var tF = items.where((doc)=> doc['style'] == "캐주").toList();
fF.addAll(sF);
fF.addAll(tF);
fF.shuffle();
return GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
childAspectRatio: 0.6,
mainAxisSpacing: 2.0,
crossAxisSpacing: 2.0),
itemCount: fF.length,
itemBuilder: (BuildContext context, int index) {
return _buildListItem(context, fF[index]);
});
},
);
}
Widget _buildListItem(context, document) {
return Ink.image(
image : NetworkImage(document['thumbnail_img']),
fit : BoxFit.cover,
child: new InkWell(
//I think we need to get something in here....
onTap: (){},
),
);
}
You should create List of Image which have isSelected value and when the user clicks on item them set true/false base of the old value which have imageURL and isSelected variable. First, you should store value in List Of Image obj. which coming from Firebase/API then flow below step. I have created a demo and post here. Please take reference.
Example code
class Demo extends StatefulWidget {
#override
_DemoState createState() => _DemoState();
}
class _DemoState extends State<Demo> {
List<ImageData> imageList;
#override
void initState() {
super.initState();
imageList = ImageData.getImage();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
childAspectRatio: 0.5,
crossAxisCount: 5,
crossAxisSpacing: 2.0,
mainAxisSpacing: 2.0),
itemCount: imageList.length,
itemBuilder: (builder, index) {
return InkWell(
onTap: () {
setState(() {
imageList[index].isSelected = !imageList[index].isSelected;
});
},
child: Stack(
children: [
_getImage(imageList[index].imageURL),
Opacity(
opacity: imageList[index].isSelected ? 1 : 0,
child: Stack(
children: [
Container(
width: double.infinity,
height: double.infinity,
color: Colors.black38,
),
Center(
child: CircleAvatar(
backgroundColor: Colors.greenAccent,
child: Icon(
Icons.check,
color: Colors.white,
),
),
)
],
),
)
],
));
},
),
);
}
_getImage(url) => Image.network(
url,
height: 500,
fit: BoxFit.fitHeight,
);
#override
void dispose() {
super.dispose();
}
}
class ImageData {
String imageURL;
bool isSelected;
int id;
ImageData(this.imageURL, this.isSelected, this.id);
static List<ImageData> getImage() {
return [
ImageData('https://picsum.photos/200', false, 1),
ImageData('https://picsum.photos/100', false, 2),
ImageData('https://picsum.photos/300', false, 3),
ImageData('https://picsum.photos/400', false, 4),
ImageData('https://picsum.photos/500', false, 5),
ImageData('https://picsum.photos/600', false, 6),
ImageData('https://picsum.photos/700', false, 7),
ImageData('https://picsum.photos/800', false, 8),
ImageData('https://picsum.photos/900', false, 9),
];
}
}
Output