When I open a page in pageview builder then this page will show around a second and then the desire page will show any have idea how this blank page show before the real one
PdfDocumentLoader.openAsset(
'asset/15line.pdf',
documentBuilder: (context, pdfDocument, pageCount) => LayoutBuilder(
builder: (context, constraints) => PageView.builder(
physics: CustomPageViewScrollPhysics(),
// controller: PageController(
// viewportFraction: 1.044,
// ),
scrollDirection: Axis.horizontal,
itemCount: widget.totalpages,
reverse: true,
itemBuilder: (context, index) => PdfPageView(
pdfDocument: pdfDocument,
pageNumber: index + widget.startpageno,
),
),
),
);
}
}
Related
I have a Widget list with millions of widgets and some of them are wider than screen.
I need to use ListView.builder() and ListTile to save time while running like this:
ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
controller: scrollController,
itemCount: widgetList.length,
itemBuilder: (context, i) =>
ListTile(
title: widgetList[i]
)
);
But when I run it, those ListTile that their title is wider than screen will overflow on the right because ListView.builder() not wide enough.
If I assign a big width to ListView.builder() like this will works fine but will remain a lot of blank even if all widgets in list are short:
ListView(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
children: [
Container(
width: 2000,
child: ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
controller: scrollController,
itemCount: widgetList.length,
itemBuilder: (context, i) =>
ListTile(
title: widgetList[i]
)
))]);
Any idea to improve this function?
---------------update-----------
My widgetList contains Column/Row etc.
But let's start with only one Text().
Example:
ListView.builder(
restorationId: 'sampleItemListView',
itemCount: 1000000,
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text(
"abcdefghijklmnopqrstuvwxyz"
"abcdefghijklmnopqrstuvwxyz"
"abcdefghijklmnopqrstuvwxyz",
maxLines: 1,
),
);
},
)
The text is too long but I don't want it change line .
What can I do to read full text?
Use like below, do not specify the hight and width for the widgets
#override
Widget build(BuildContext context) {
var items = List<SampleItem>.generate(
1000,
(i) => const SampleItem(
'范植勝',
'Showing long widget list using ListView.builder() and ListTile',
Icons.favorite,
));
return Scaffold(
body: ListView.builder(
restorationId: 'sampleItemListView',
itemCount: items.length,
itemBuilder: (BuildContext context, int index) {
final item = items[index];
return ListTile(
title: Text(item.name),
subtitle: Text(item.decsription),
leading: Icon(item.icons),
onTap: () {
Navigator.restorablePushNamed(
context,
SampleItemDetailsView.routeName,
);
});
},
),
);
}
Flutter newbie here!
Currently, my Scaffold has 2 listview builders and the bottom one is giving me the unbounded height (!constraints.hasBoundedHeight error) issue.
I have tried using shrinkWrap on all 3 list views, as suggested in similar questions but I get the same error.
The only thing that works is wrapping the FutureBuilder in a SizedBox. But that seems unintuitive to me, as I would want it to ideally expand as needed and be scrollable.
My rough solution is to maybe dynamically calculate the height based on the number of items the FutureBuilder needs, but again, I feel there should be a better solution.
My code snippet is attached below:
return Scaffold(
appBar: AppBar(),
body: ListView(
children: [
ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 2,
itemBuilder: (context, index) {
return const SuggestCard(
indexKey: 'takt',
);
}),
FutureBuilder<AnimeDetails>(
future: _animeDetail,
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: 2, //Number of anime from list
itemBuilder: (context, index) {
var anime = snapshot.data; //Get the data from the index
return AnimeCard(
anime: anime,
);
});
} else {
return const Center(child: CircularProgressIndicator());
}
},
),
],
),
);
As per your comment I think below link will helpful to you.
Lists
The parent ListView handling scroll event for body and while second ListView will have fixed height, you can do it like this
return Scaffold(
body: LayoutBuilder(
builder: (context, constraints) => ListView(
children: [
SizedBox(
height: constraints.maxHeight * .3,
child: ListView.builder(
itemCount: 122,
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemBuilder: (context, index) => Text("H $index"),
),
),
ListView.builder(
shrinkWrap: true,
physics:
const NeverScrollableScrollPhysics(), // parent controll the scroll event
itemCount: 44,
itemBuilder: (context, index) => Text("$index"),
),
],
),
));
I just added the below lines to your code. You can try the below code.
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
return Scaffold(
appBar: AppBar(),
body: ListView(
children: [
ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 2,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (context, index) {
return const SuggestCard(
indexKey: 'takt',
);
}),
FutureBuilder<AnimeDetails>(
future: _animeDetail,
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: 2, //Number of anime from list
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (context, index) {
var anime = snapshot.data; //Get the data from the index
return AnimeCard(
anime: anime,
);
});
} else {
return const Center(child: CircularProgressIndicator());
}
},
),
],
),
);
I'm trying to make my listview always focus on the last element in a chat, but I don't know how to do it, I appreciate if someone can help me
Widget ChatMessageList(){
return StreamBuilder(
stream: chatMessageStream,
builder: (context, snapshot){
return snapshot.hasData ? ListView.builder(
controller: _scrollController,
itemCount: snapshot.data.documents.length,
itemBuilder: (context, index){
return MessageTile(snapshot.data.documents[index].data()['message'],
snapshot.data.documents[index].data()['sendBy'] == userSnapshop.uid);
}
) : Container();
},
);
}
List view can be reverse by wrapping another scrollable widget.
so you just need to wrap your ListView by SingleChildScrollView and change the reading direction by revers property.
SingleChildScrollView(
reverse: true,
child: ListView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: 100,
itemBuilder: (context, index) => Text(
index.toString(),
),
),
)
_animateToLast() {
debugPrint('scroll down');
_scrollController.animateTo(
_scrollController.position.maxScrollExtent,
curve: Curves.easeOut,
duration: const Duration(milliseconds: 500),
);
}
I have a ScrollController in my page to work with infinite scroll but when the list builder is not in a Container the ScrollController listeners does not work.
Works
Container(
height: 400,
child: Observer(
builder: (_) {
return ListView.builder(
shrinkWrap: true,
controller: _scrollController,
itemCount: passeiosController.passeios.length,
itemBuilder: (_, index) => PasseioCard(
passeioModel: passeiosController.passeios[index],
),
);
},
),
)
Not working
Observer(
builder: (_) {
return ListView.builder(
shrinkWrap: true,
controller: _scrollController,
itemCount: passeiosController.passeios.length,
itemBuilder: (_, index) => PasseioCard(
passeioModel: passeiosController.passeios[index],
),
);
},
)
It worked. I had a list view builder inside a listview. Putting the controller in the parent listview worked correctly.
I am trying to create a home page that has 3 tabs: Friends, Groups and Events.
After finally managing to load events for the current user only, I realised ill have a hard time loading different data for each tab - as the StreamBuilder stream: will always be the same for all the tabs.
I need help finding a way to have a different StreamBuilder for each of my tabs.
Code below:
StreamBuilder(
stream: _streamer(),//Firestore.instance.collection("Events").snapshots(),
builder: (BuildContext context, AsyncSnapshot<List<dynamic>> snapshot) {
if (!snapshot.hasData) return const Text("Loading...");
return new SizedBox(
height: MediaQuery.of(context).size.height - 42 - MediaQuery.of(context).padding.bottom -AppBar().preferredSize.height - kToolbarHeight,
child: Column(
children: <Widget>[
Expanded(
child: TabBarView(
controller: _tabController,
children: <Widget>[
Container(
child: ListView.separated(
itemCount: snapshot.data.length,
itemBuilder: (context, index) =>
_buildListItem(context,
snapshot.data[index]),
separatorBuilder: (context, index) {
return Divider();
},
shrinkWrap: true,
),
),
Container(
child: ListView.separated(
itemCount: snapshot.data.length,
itemBuilder: (context, index) =>
_buildListItem(context,
snapshot.data[index]),
separatorBuilder: (context, index) {
return Divider();
},
shrinkWrap: true,
),
),
Container(
child: ListView.separated(
itemCount: snapshot.data.length,
itemBuilder: (context, index) =>
_buildListItem(context,
snapshot.data[index]),
separatorBuilder: (context, index) {
return Divider();
},
shrinkWrap: true,
),
),
],
),
)
],
));
},
)
This is how the home page looks
I assume you're loading all data required for all your tabs using that stream. What you could do is have distinct pairs of stream/StreamBuilder for each tab:
... // widgets leading up to the TabBarView
TabBarView(
controller: _controller,
children: <Widget>[
StreamBuilder(
stream: friendsStream,
builder: (BuildContext context, AsyncSnapshot<SomeData> snapshot) {
return FriendsWidget();
}
),
StreamBuilder(
stream: groupsStream,
builder: (BuildContext context, AsyncSnapshot<SomeData> snapshot) {
return GroupsWidget();
}
),
//... etc
]
)
You could also wrap ONLY the widgets that should be rebuilt with a StreamBuilder instead of wrapping the whole parent widget:
... // widgets leading up to the TabBarView
TabBarView(
controller: _controller,
children: <Widget>[
Column(
children: <Widget>[
SomeWidget(),
AnotherWidget(),
StreamBuilder(
stream: friendsStream,
builder: (BuildContext context, AsyncSnapshot<SomeData> snapshot) {
return FriendsWidget();
}
)
]
),
// ... etc
]
)
If you are compelled to load all your data from the database at once, you could use a Repository class to load and store all your data, and then, depending on your architecture, have streams built from that class.
As a side note, I highly recommend using a Bloc with BlocBuilder. Blocs are just far superior to other designs (in most cases). flutter_bloc is my favorite.