一起滚动屏幕和列表视图,而不是单独滚动
Posted
技术标签:
【中文标题】一起滚动屏幕和列表视图,而不是单独滚动【英文标题】:Scroll the screen and listview together, NOT seperately 【发布时间】:2021-10-29 06:08:39 【问题描述】:我已经看过这些答案here,但它们对我不起作用。我希望 LatestNewsList 小部件和整个屏幕一起滚动而不是单独滚动。这是屏幕的代码:
class Search extends StatelessWidget
final tab = new TabBar(tabs: <Tab>[
new Tab(icon: new Icon(Icons.arrow_forward)),
new Tab(icon: new Icon(Icons.arrow_downward)),
new Tab(icon: new Icon(Icons.arrow_back)),
]);
@override
Widget build(BuildContext context)
final bloc = LatestNewsProvider.of(context);
return DefaultTabController(
length: 6,
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
margin: EdgeInsets.only(
// right: 10,
left: 10,
top: 20,
),
child: Row(
children: [
Container(
width: 32,
height: 32,
child: CircleAvatar(
backgroundImage: NetworkImage(
'https://thispersondoesnotexist.com/image'),
),
),
SizedBox(
width: 20,
),
SearchBar(),
],
),
),
Container(
child: TabBar(
isScrollable: true,
unselectedLabelColor: Colors.black,
labelColor: Colors.blue,
tabs: [
Tab(
text: "Latest",
),
Tab(text: "programming"),
Tab(text: "general"),
Tab(text: "sports"),
Tab(text: "academia"),
Tab(text: "politics"),
]),
),
Container(
//Add this to give height
height: MediaQuery.of(context).size.height,
child: TabBarView(children: [
Column(
children: [
StreamBuilder(
stream: bloc.searchedListBuilderStream,
builder: (context, snapshot)
if (snapshot.hasData)
return NewsListBuilder(snapshot);
else if (snapshot.hasError)
return Text('No results found');
bloc.fetchLatestNews();
return Expanded(
child: Column(
children: [
HorizontalSearchList(bloc, bloc.newsStream),
LatestNewsList(bloc, bloc.newsStream, 'Search'),
],
));
,
)
],
),
Column(
children: [
StreamBuilder(
stream: bloc.searchedListBuilderStream,
builder: (context, snapshot)
if (snapshot.hasData)
return NewsListBuilder(snapshot);
else if (snapshot.hasError)
return Text('No results found');
bloc.c1Fetch('programming');
return Expanded(
child: Column(
children: [
HorizontalSearchList(bloc, bloc.c1Stream),
LatestNewsList(bloc, bloc.c1Stream, 'Search'),
],
));
,
)
],
),
Column(
children: [
StreamBuilder(
stream: bloc.searchedListBuilderStream,
builder: (context, snapshot)
if (snapshot.hasData)
return NewsListBuilder(snapshot);
else if (snapshot.hasError)
return Text('No results found');
bloc.c2Fetch('general');
return Expanded(
child: Column(
children: [
HorizontalSearchList(bloc, bloc.c2Stream),
LatestNewsList(bloc, bloc.c2Stream, 'Search'),
],
));
,
)
],
),
Column(
children: [
StreamBuilder(
stream: bloc.searchedListBuilderStream,
builder: (context, snapshot)
if (snapshot.hasData)
return NewsListBuilder(snapshot);
else if (snapshot.hasError)
return Text('No results found');
bloc.c3Fetch('sports');
return Expanded(
child: Column(
children: [
HorizontalSearchList(bloc, bloc.c3Stream),
LatestNewsList(bloc, bloc.c3Stream, 'Search'),
],
));
,
)
],
),
Column(
children: [
StreamBuilder(
stream: bloc.searchedListBuilderStream,
builder: (context, snapshot)
if (snapshot.hasData)
return NewsListBuilder(snapshot);
else if (snapshot.hasError)
return Text('No results found');
bloc.c4Fetch('academia');
return Expanded(
child: Column(
children: [
HorizontalSearchList(bloc, bloc.c4Stream),
LatestNewsList(bloc, bloc.c4Stream, 'Search'),
],
));
,
)
],
),
Column(
children: [
StreamBuilder(
stream: bloc.searchedListBuilderStream,
builder: (context, snapshot)
if (snapshot.hasData)
return NewsListBuilder(snapshot);
else if (snapshot.hasError)
return Text('No results found');
bloc.c5Fetch('politics');
return Expanded(
child: Column(
children: [
HorizontalSearchList(bloc, bloc.c5Stream),
LatestNewsList(bloc, bloc.c5Stream, 'Search'),
],
));
,
)
],
),
]),
),
],
),
));
LatestNewsList 小部件内部有一个小部件,该小部件具有负责构建列表视图的代码:
class NewsListBuilder extends StatelessWidget
final snapshot;
NewsListBuilder(this.snapshot);
@override
Widget build(BuildContext context)
return Expanded(
child: ListView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
scrollDirection: Axis.vertical,
padding: EdgeInsets.all(8),
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index)
return NewsListBuilderItems(snapshot, index);
,
));
我无法继续滚动:
【问题讨论】:
【参考方案1】:对于像您这样的更复杂的滚动页面,您应该使用 slivers。在此处阅读有关它们的更多信息:https://flutter.dev/docs/development/ui/advanced/slivers
我可以为您提供一个简化的示例,说明您想做什么(希望我理解正确):
import 'package:flutter/material.dart';
void main()
runApp(MyApp());
class MyApp extends StatelessWidget
@override
Widget build(BuildContext context)
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Search(),
);
class Search extends StatefulWidget
@override
_SearchState createState() => _SearchState();
class _SearchState extends State<Search> with SingleTickerProviderStateMixin
late final TabController _tabController;
@override
void initState()
// Make sure to set the correct length
_tabController = TabController(length: 5, vsync: this);
super.initState();
@override
Widget build(BuildContext context)
return NestedScrollView(
headerSliverBuilder: (context, innerBoxIsScrolled)
return [
SliverAppBar(
title: Container(height: 40, color: Colors.grey), // this can be the search bar
bottom: TabBar(
indicatorWeight: 3,
indicatorPadding: EdgeInsets.symmetric(horizontal: 10, vertical: 0),
controller: _tabController,
tabs: <Widget>[
Tab(text: "programming"),
Tab(text: "general"),
Tab(text: "sports"),
Tab(text: "academia"),
Tab(text: "politics"),
],
),
),
];
,
body: TabBarView(
controller: _tabController,
children: [
/// here you put all your pages
// Example of one page
// You will need to wrap this in StreamBuilder as you do in the
// original code
CustomScrollView(
slivers: [
SliverList(
delegate: SliverChildBuilderDelegate((context, index)
return Container(
height: 400,
color: Colors.red.shade200,
margin: EdgeInsets.all(4),
);
),
),
],
),
CustomScrollView(
slivers: [
SliverList(
delegate: SliverChildBuilderDelegate((context, index)
return Container(
height: 400,
color: Colors.green,
margin: EdgeInsets.all(4),
);
),
),
],
),
CustomScrollView(
slivers: [
SliverList(
delegate: SliverChildBuilderDelegate((context, index)
return Container(
height: 400,
color: Colors.blue,
margin: EdgeInsets.all(4),
);
),
),
],
),
CustomScrollView(
slivers: [
SliverList(
delegate: SliverChildBuilderDelegate((context, index)
return Container(
height: 400,
color: Colors.blue,
margin: EdgeInsets.all(4),
);
),
),
],
),
CustomScrollView(
slivers: [
SliverList(
delegate: SliverChildBuilderDelegate((context, index)
return Container(
height: 400,
color: Colors.blue,
margin: EdgeInsets.all(4),
);
),
),
],
),
],
),
);
【讨论】:
它以某种方式工作,但并不完全。你在哪里评论 /// 当我这样做时,你把所有的标签放在你的页面上,列表视图消失了 @Benyamin,PageView
在这种情况下与您帖子中的TabBarView
的工作方式类似。您可以横向滑动(或单击选项卡)以在页面之间导航。您需要为每个类别(编程、一般、运动等)添加一个 CustomScrollView 页面。这些页面必须像在原始代码中一样被包裹在 StreamBuilder
s 中。
如何在标签栏顶部添加头像和搜索栏?
@Benyamin,您可以将其与bottom
的 TabBar 放在一列中。我会更新答案
我不知道bottom
参数需要特定的小部件,抱歉。您仍然可以改用title
。当我弄清楚其他问题时,我会更新答案以上是关于一起滚动屏幕和列表视图,而不是单独滚动的主要内容,如果未能解决你的问题,请参考以下文章