Flutter - Not able to scroll Listview - flutter

I'm trying to write basic Listview example, however not able to scroll down, screen is fixed not able to view all items.
Tried with working example from flutter official documentation (displaying Listview till items29) https://api.flutter.dev/flutter/widgets/ListView-class.html
Not able to figure out Whether it is settings issue or other.
import 'package:flutter/material.dart';
class mySquare extends StatelessWidget {
String child;
mySquare({required this.child});
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Container(height: 200, color: Colors.amber, child: Text(child)),
);
}
}
class HomePage extends StatelessWidget {
List posts = ['post1', 'post2', 'post3', 'post4', 'post5', 'post6'];
Widget build(BuildContext context) {
return Scaffold(
body: ListView.builder(
itemCount: posts.length,
itemBuilder: ((BuildContext context, index) {
return mySquare(
child: posts[index],
);
}),
),
);
}
}

I launched your code on Android emulator and it works as expected.
If the device is big enough for all items ListView wouldn't scroll

Related

How to avoid streambuilder executes unnecessarytimes

I'm trying to display a list of documents which works, but I read that one good practice is to manage states (which I'm trying currently to understand too). In this case every time I change of screen using the bottomNavigationBar the streamBuilder executes (I always see the CircularProgressIndicator).
I tried call the collection reference in the intState but still the same issue, my code:
class Deparments extends StatefulWidget {
Deparments({Key? key, required this.auth}) : super(key: key);
final AuthBase auth;
#override
_DeparmentsState createState() => _DeparmentsState();
}
class _DeparmentsState extends State<Deparments> {
late final Stream<QuerySnapshot<Object?>> _widget;
Stream<QuerySnapshot<Object?>> getProds(){
CollectionReference ref = FirebaseFirestore.instance.collection("Departamentos");
return ref.snapshots();
}
#override
void initState() {
super.initState();
_widget = getProds();
}
#override
Widget build(BuildContext context) {
return Scaffold(
drawer: SideMenu(auth: widget.auth),
appBar: AppBar(
title: Text("Departamentos"),
centerTitle: true,
backgroundColor: Colors.green,
),
body: Container(
child: StreamBuilder<QuerySnapshot> (
stream: _widget,
builder: (BuildContext context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(),
);
} else {
List deparments =
snapshot.data!.docs.map((doc) => doc.id).toList();
return Column(
children: [
Expanded(
child: ListView.builder(
padding: EdgeInsets.only(top: 10),
scrollDirection: Axis.vertical,
itemCount: deparments.length,
itemBuilder: (context, index) {
return SingleChildScrollView(
child: Card(
child: Text(deparments[index]),
),
);
}),
)
],
);
}
}),
),
);
}
}
Update: for those who are facing the same issue Tayan provides a useful solution and he has a video showing the solution https://stackoverflow.com/a/64057210/9429407
Init state will not help you to avoid rebuilds because on changing tabs Flutter rebuilds your Screen. So we need some way to keep our screen alive, so here comes AutomaticKeepAliveClientMixin.
class _HomeState extends State<Home> with AutomaticKeepAliveClientMixin<Home> {
#override
bool get wantKeepAlive => true;
#override
Widget build(BuildContext context) {
//Make sure to include the below method
super.build(context);
return SomeWidget();
}
}
The above implementation keeps all of your tab state persists and does not rebuilds the tabs again. Well this may serve your purpose but it may not be idle because this loads all the tabs at once even if the user actually didnt visited a tab, so to avoid the build unless a tab is clicked, use the above method in combination with pageview.
Check out pageView implementation
Also, if you want a better way to manage state and save some of your read calls to Firestore, then you should store data locally and fetch only those needed and/or use paginations.
Initialize your stream in initState just like this answer:
StreamBuilder being called numerous times when in build

How can I automatically add widgets to the body of my scaffold?

I'm trying to have the body of my scaffold return list Tiles that are built automatically, much like posts on a social media app. However, it only returns and empty container, with only its background colour.
Widget _buildListingWidgets(List<Widget> listing) {
return ListView.builder(
itemBuilder: (BuildContext context, int index) => listing[index],
itemCount: listing.length,
);
}
#override
Widget build(BuildContext context) {
final listing = <Listing>[];
for (var i = 0; i < _listingNames.length; i++) {
listing.add(Listing(
describe: _describe[i],
building: _building[i],
location: _location[i],
availability: _availability[i],
));
}
final listView = Container(
color: Colors.black,
padding: EdgeInsets.symmetric(horizontal: 8.0),
child: _buildListingWidgets(listing),
);
...
return Scaffold(
appBar: appBar,
body: listView,
...
);
Keep you code as it now, and modify the ListViewBuilder to look like this:
Widget _buildListingWidgets(List<Widget> listing) {
return ListView.builder(
itemCount: listing.length,
itemBuilder: (BuildContext context, int index) {
return Container(child:
Text(listing[index].describe),
);
}
);
}
It should work.
You seem to have overly complicated how to build your ListView, without using it's inherent functionality. You can do it this way:
class Issue66841743 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
color: Colors.black,
padding: EdgeInsets.symmetric(horizontal: 8.0),
child: MyList(listingNames: listing,),
);
}
}
class MyList extends StatelessWidget {
final List listingNames;
const MyList({Key key, this.listingNames}) : super(key: key);
#override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: listingNames.length,
itemBuilder: (context, index) {
return Listing(
describe: _describe[i],
building: _building[i],
location: _location[i],
availability: _availability[i],
);
}
);
}
}
Have in mind that you did not provide us with the other Lists, _describe, _building, _location and _availability. These also signal me that there are further issues in your code. As you very well could have a class with all the properties pertaining to a certain listing.

Flutter - Using Dismissible on a PageView creates an ugly animation

with the following example code, is get a very ugly animation.
I would even say, it's no animation at all.
The next Page will just appear after the setstate is called.
How can I create a smooth delete animation using PageView?
If it is not possible via PageView, is there any alternative, that has the "snapping cards" feature?
Here is my code:
class SwipeScreen extends StatefulWidget {
const SwipeScreen({Key key}) : super(key: key);
static const routeName = '/swipe';
#override
_SwipeScreenState createState() => _SwipeScreenState();
}
class _SwipeScreenState extends State<SwipeScreen> {
List<String> content = ['one', 'two', 'three', 'four', 'five'];
#override
Widget build(BuildContext context) {
return Scaffold(
body: PageView.builder(
scrollDirection: Axis.vertical,
itemCount: content.length,
controller: PageController(viewportFraction: 0.8),
itemBuilder: (context, index) {
return Dismissible(
key: ValueKey(content[index]),
child: Card(
child: Container(
height: MediaQuery.of(context).size.height * 0.8,
child: Text('test'),
),
),
onDismissed: (direction) {
setState(() {
content = List.from(content)..removeAt(index);
});
},
);
},
),
);
}
}
Replacing PageView.builder() with ListView.builder() will create a smoother animation.
Hopefully this is what you're looking for!
Unfortunately, the PageView widget is not intended to be used with the Dismissible widget as the animation when the dismiss is complete is not implemented.
You can still change your PageView to a ListView and set a physics to PageScrollPhysics() to get the animation on dismiss but you will probably encounter some other issues on Widget sizes

The render frames goes crazy with multiple image in scroll

Hello I was trying to do something like the Instagram Stories, but when I use more than 6 pictures the Flutter Performance of Android Studio goes crazy, also my Pc. And I was wondering if there is something to prevent it.
Main Widget
class Story extends StatelessWidget {
#override
Widget build(BuildContext context) {
return SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: <Widget>[
AddStory(),
PeopleStories(),
],
),
);
}
}
Second Widget
class PeopleStories extends StatelessWidget {
final List<String> storiesPic = [
'https://images.unsplash.com/photo-1536896407451-6e3dd976edd1?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1234&q=80',
'https://images.unsplash.com/photo-1553457055-88e354f1257c?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1234&q=80',
'https://images.unsplash.com/photo-1545064189-2d901f702a28?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1234&q=80',
'https://images.unsplash.com/photo-1501943416256-08140ba03763?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1436&q=80',
'https://images.unsplash.com/photo-1572151510493-38eb612d23be?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1268&q=80',
'https://images.unsplash.com/photo-1548536154-b47a70d27d8e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1234&q=80',
// 'https://images.unsplash.com/photo-1582129617595-c657a072c9b9?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=3662&q=80',
// 'https://images.unsplash.com/photo-1559870904-406aeea0a89c?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=934&q=80'
];
#override
Widget build(BuildContext context) {
return Row(
children: _buildStoriesList(),
);
}
List<StoryDesign> _buildStoriesList() {
List<StoryDesign> widgets = [];
int i = 0;
storiesPic.forEach((pic) {
++i;
widgets.add(StoryDesign(pic));
});
return widgets;
}
}
Design of the widget, if there is something it could do the multiple rendering.
class StoryDesign extends StatelessWidget {
StoryDesign(this.profilePic);
final String profilePic;
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(
left: kMediumSeparation / 2,
top: kCommonSeparation,
right: kMediumSeparation / 2,
bottom: kHugeSeparation),
child: InkWell(
onTap: () => print('profile bubble tapped'),
borderRadius: BorderRadius.all(Radius.circular(35.0)),
child: CircleAvatar(
backgroundImage: NetworkImage(profilePic),
radius: 35.0,
backgroundColor: kDefaultColorLoading,
),
),
);
}
}
I think the most probable reason could be the big size of your images.
Also use CachedNetworkImage to load your images faster.
I think it is because of one the image is to big, this one https://images.unsplash.com/photo-1582129617595-c657a072c9b9?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=3662&q=80

Is possible to make Multiple flutter pages in one app?

I went to convert book to android app the book has 100 page ,
should I create page(activity) for each page ? or any other ways to do this?
You can use PageView or its builder constructor for this, here is the basic example
PageView.builder(
itemCount: 100,
itemBuilder: (_, index) => YourPage(list[index]),
)
Update:
Create two widgets like this.
// It only shows Text
class TextPage extends StatelessWidget {
final String text;
const TextPage({#required this.text});
#override
Widget build(BuildContext context) {
return Text(text, style: TextStyle(fontSize: 20));
}
}
// It only shows Image from assets
class ImagePage extends StatelessWidget {
final String image;
const ImagePage({#required this.image});
#override
Widget build(BuildContext context) {
return Image.asset(image);
}
}
Now in your main class, use them as
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: PageView(
children: <Widget>[
TextPage(text: "This screen only has text"), // 1st screen only text
ImagePage(image: "assets/images/chocolate_pic.png"), // 2nd screen only image
Column( // 3rd screen will have both
children: <Widget>[
TextPage(text: "This is the text followed by an image"),
ImagePage(image: "assets/images/chocolate_pic.png"),
],
),
],
),
);
}