I am trying to implement a Progress Indicator in Flutter but I am not sure whether I need to put in the if condition to show Progress Indicator while the item is still Loading.
class HomePageNewArrival extends StatefulWidget {
final List<Product> productList;
HomePageNewArrival({this.productList});
#override
_HomePageNewArrivalState createState() => _HomePageNewArrivalState();
}
class _HomePageNewArrivalState extends State<HomePageNewArrival> {
#override
Widget build(BuildContext context) {
return Container(
height: 550,
child: GridView.builder(
physics: NeverScrollableScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: 2 / 3.2,
crossAxisSpacing: 1,
mainAxisSpacing: 1,
),
itemCount: this.widget.productList.length,
itemBuilder: (context, index) {
if (index.) {
return HomenewArrivalProducts(this.widget.productList[index]);
} else {
return new CircularProgressIndicator();
}
}),
);
}
}
Building widgets in flutter is instant
i think what you wanna do is to show a circular spinner while images are loading in HomenewArrivalProducts() Widget if you have a Image.network() try this:
child: Image.network(
'https://example.com/image.jpg',
loadingBuilder: (BuildContext context, Widget child, ImageChunkEvent loadingProgress) {
if (loadingProgress == null)
return child;
return Center(
child: CircularProgressIndicator(
value: loadingProgress.expectedTotalBytes != null
? loadingProgress.cumulativeBytesLoaded / loadingProgress.expectedTotalBytes
: null,
),
);
},
),
and if you wanna just to make an illusion of something is loading you can use FutureBuilder()
FutureBuilder(
future: Future.delayed(Duration(milliseconds: 500)),
builder: (ctx, snapshot) =>
snapshot.connectionState == ConnectionState.waiting
? CircularProgressIndicator()
: GridView.builder(...),
);
Related
Know the problem as the function need to return a Widget but now sure how can I solve this in my code , thanks for the help
class PhotoGrid extends StatefulWidget {
const PhotoGrid({super.key});
#override
State<PhotoGrid> createState() => _PhotoGridState();
}
class _PhotoGridState extends State<PhotoGrid> {
final Stream<QuerySnapshot> _photoStream =
FirebaseFirestore.instance.collection('photos').snapshots();
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: StreamBuilder<QuerySnapshot>(
stream: _photoStream,
builder:
(BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) {
return const Text('Something went wrong');
}
if (snapshot.connectionState == ConnectionState.waiting) {
return const Text("Loading");
}
return GridView.builder(
gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 120,
crossAxisSpacing: 20,
childAspectRatio: 3 / 2,
mainAxisSpacing: 20,
),
itemCount: snapshot.data!.docs.length,
itemBuilder: (context, index) {
var data = snapshot.data!.docs
.map((DocumentSnapshot documents) {
var data = documents.data()! as Map<String, dynamic>;
return Container(
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage('${data['ImgUrl']}'),
),
),
);
})
.toList()
.cast();
},
);
},
),
),
);
}
}
enter code here
Know the problem as the function need to return a Widget but now sure how can I solve this in my code , thanks for the help Know the problem as the function need to return a Widget but now sure how can I solve this in my code , thanks for the help
return GridView.builder(
gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 120,
crossAxisSpacing: 20,
childAspectRatio: 3 / 2,
mainAxisSpacing: 20,
),
itemCount: snapshot.data!.docs.length,
itemBuilder: (context, index) {
var data = snapshot.data!.docs[index].data()! as Map<String, dynamic>;
return Container(
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage('${data['ImgUrl']}'),
),
),
);
},
);
The error was caused by the fact that the item builder function in the GridView.builder widget was not returning anything and it should return a Widget. To fix it, the function was modified to return a Container widget, containing a DecorationImage showing the image from the ImgUrl key of the data map from the Firebase Query.
So I use Firebase as my backend.
The String about which Im talking looks like this:
When I add this String as a variable in my Text Widget
Text("${beschreibung}")
the text doesn't automatically line break, its just cut off by the right side of the screen
How can I achieve a behaviour where this doesn't happen & get flutter to detect the spaces to automatically line break?
Additional Details
Here Im getting the data from firebase and passing it on:
class Produkte extends StatelessWidget {
final Stream<QuerySnapshot> data =
FirebaseFirestore.instance.collection("products").snapshots();
#override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
child: Container(
width: MediaQuery.of(context).size.width,
child: StreamBuilder<QuerySnapshot>(
stream: data,
builder: ((BuildContext context,
AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) {
return Text("Some error");
}
if (snapshot.connectionState == ConnectionState.waiting) {
return Text("loading");
}
final data = snapshot.requireData;
return Container(
height: 800,
child: GridView.builder(
itemCount: data.size,
itemBuilder: (context, index) {
return ProductTile(
titel: data.docs[index]["Name"].isNotEmpty
? data.docs[index]["Name"]
: " ",
beschreibung:
data.docs[index]["Beschreibung"].isNotEmpty
? data.docs[index]["Beschreibung"]
: " ");
},
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
mainAxisSpacing: 5,
crossAxisSpacing: 2),
));
}),
),
),
),
);
}
}
& here Im using the data
class Produkt extends StatelessWidget {
Produkt({required this.titel, required this.beschreibung});
final List<String> beschreibung;
final String titel;
#override
Widget build(BuildContext context) {
return Scaffold(body:
Container(
height: 350,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: beschreibung.length,
itemBuilder: (context, index) {
return Text("${beschreibung[index]}");
},
),
),
);
}
}
Add width to the container so the text knows where to break and use a new line and remove the axis horizontal..
return Scaffold(body:
Container(
height: 350,
width: MediaQuery.of(context).size.width,
child: ListView.builder(
itemCount: beschreibung.length,
itemBuilder: (context, index) {
return Text("${beschreibung[index]}");
},
),
),
If you wish to keep the horizontal scroll but still have the text in one screen then add a container to the text
return Scaffold(body:
Container(
height: 350,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: beschreibung.length,
itemBuilder: (context, index) {
return Container( width: MediaQuery.of(context).size.width,
child : Text("${beschreibung[index]}")
);
},
),
),
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(),
)
],
);
}
I don't have much experience with flutter.
I would like to use the language_tool library (https://pub.dev/packages/language_tool) for Dart and Flutter.
To show the data obtained from the tool() function, I created a FutureBuilder with a ListView.builder inside, which returns a Column.
I would like there to be 2 children inside the column:
1- a Text with mistake.issueDescription as text (for each "mistake")
2- another ListView that returns the elements of the List mistake.replacements for each "mistake"
Anyone know how I can fix it?
Below I put the code I created, which works fine until I put the Listview builder inside the first ListView builder.
import 'package:flutter/material.dart';
import 'package:language_tool/language_tool.dart';
void main() => runApp(mainApp());
class mainApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return const MaterialApp(
home: Chat(),
);
}
}
class Chat extends StatefulWidget {
const Chat({Key? key}) : super(key: key);
#override
_ChatState createState() => _ChatState();
}
class _ChatState extends State<Chat> {
String text = 'Henlo i am Gabriele';
Future<List<WritingMistake>> tool(String text) async {
var tool = LanguageTool();
var result = tool.check(text);
var correction = await result;
List<WritingMistake> mistakes = [];
for (var m in correction) {
WritingMistake mistake = WritingMistake(
message: m.message,
offset: m.offset,
length: m.length,
issueType: m.issueType,
issueDescription: m.issueDescription,
replacements: m.replacements,
);
mistakes.add(mistake);
}
print(mistakes.length);
print(mistakes);
return mistakes;
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Column(
children: [
Container(
color: Colors.red,
height: 150.0,
width: double.infinity,
child: Center(
child: Text(text, style: const TextStyle(fontSize: 20.0))),
),
FutureBuilder(
future: tool(text),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.data == null) {
return const Center(
child: Text('Loading...'),
);
} else {
return SizedBox(
height: 200.0,
child: ListView.builder(
itemCount: snapshot.data.length,
itemBuilder:
(BuildContext context, int mistakeIdIndex) {
return Column(
children: [
Text(snapshot
.data[mistakeIdIndex].issueDescription),
// this is where the problems begin
ListView.builder(
itemCount: snapshot.data[mistakeIdIndex]
.replacements.length,
scrollDirection: Axis.horizontal,
itemBuilder:
(BuildContext context, int index) {
return Text(snapshot.data[mistakeIdIndex]
.replacements[index]);
}),
],
);
}),
);
}
}),
],
),
),
);
}
}
I hope I was clear and that someone can help me.
Thank you :)
You cannot give a listview-builder as a child for a column try changing the Column widget to a ListView and set its shrinkWrap property to true.
ListView(
children: [
Container(
color: Colors.red,
height: 150.0,
width: double.infinity,
child: Center(
child: Text(text, style: const TextStyle(fontSize: 20.0))),
),
FutureBuilder(
future: tool(text),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.data == null) {
return const Center(
child: Text('Loading...'),
);
} else {
return SizedBox(
height: 200.0,
child: ListView.builder(
shrinkWrap:true,
itemCount: snapshot.data.length,
itemBuilder:
(BuildContext context, int mistakeIdIndex) {
return ListView(
shrinkWrap:true,
children: [
Text(snapshot
.data[mistakeIdIndex].issueDescription),
// this is where the problems begin
ListView.builder(
shrinkWrap:true,
itemCount: snapshot.data[mistakeIdIndex]
.replacements.length,
scrollDirection: Axis.horizontal,
itemBuilder:
(BuildContext context, int index) {
return Text(snapshot.data[mistakeIdIndex]
.replacements[index]);
}),
],
);
}),
);
}
}),
],
),
),
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),
),
),
],
);
},
),
);
}
}