我有一个 GridView,它运行得非常流畅。我在无限滚动的上下文中使用网格,只要滚动接近底部,就会通过 REST API 加载更多项目。这里没有问题。
但是我希望能够在网格底部显示加载指示器。该小部件应跨越网格中的所有列,但仍应是可滚动内容的一部分。
我是 Flutter 新手,不知道如何实现这一目标。
我的(工作)GridView 是这样实例化的:
return new GridView.builder(
gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: _COLUMN_COUNT),
controller: widget.scrollController,
itemCount: widget.items.length,
itemBuilder: (BuildContext context, int index) {
return new _ItemView(item: widget.items[index]);
},
);
通过 CustomScrollView 包裹 SliverGrid:
return new CustomScrollView(slivers: <Widget>[
new SliverGrid(
gridDelegate: yourGridDelegate,
delegate: yourBuilderDelegate,
),
new SliverToBoxAdapter(
child: yourFooter,
),
]);
@najeira 提到的是正确的,如果您仍然想保留“controller: widget.scrollController”属性,CustomScrollView 小部件支持它:
CustomScrollView(
controller: widget.scrollController,
slivers: <Widget>[
SliverGrid(
delegate: SliverChildBuilderDelegate( (c,index){return Widget();},
childCount: widget.list.length),
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
)...
我面临着类似的问题,也许更复杂一些。我只需要滚动 GridView,而其他所有内容都应该在布局中保持固定。所以上面的答案帮助我找到了以下解决方案:
class ComplexLayout extends StatelessWidget {
@override
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(
title: Text("Some title"),
),
body: Padding(
padding: kThemeListPadding,
child: Column(
children: [
const _Header(),
const SizedBox(height: 16),
const _AddImagesButton(),
const SizedBox(height: 16),
const _ImagesGridViewLabel(),
const SizedBox(height: 16),
// Here's the trick
const Expanded(
child: CustomScrollView(
slivers: [_ImagesGridView()],
),
),
const SizedBox(height: 16),
_SendImagesButton(),
],
),
),
);
}
Expanded
小部件拉伸 CustomScrollView
填充所有可用空间,但仅限于布局限制。 _ImagesGridView
小部件必须是 SliverGrid
才能适应 CustomScrollView
:
class _ImagesGridView extends StatelessWidget {
const _ImagesGridView();
@override
Widget build(BuildContext context) => SliverGrid(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 8,
mainAxisSpacing: 16,
),
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) => _GridItem(
item: yourGridViewItems.elementAt(index),
),
childCount: yourGridViewItems.length,
),
);
}
我在 Flutter 文档中找到了一个关于
CustomScrollView
的优秀示例,我强烈推荐阅读:
我不确定您以哪种方式构建布局,无论如何,我知道它与您的想法有点不同,但这对我来说听起来像是
CircularProgressIndicator
的一个很好的用例。
请注意,在我的情况下,它会不断加载,因为我的
snapshot.hasData
始终是 false
。每当加载数据时,它都会将 ProgressIndicator
替换为您最初打算注入小部件中的任何数据。
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(title: new Text("GridView Test"),
),
body: new FutureBuilder(future: _getAsyncStuff(),
builder: (BuildContext context,
AsyncSnapshot<DataSnapshot> snapshot) {
return new GridView.builder(
gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3),
itemBuilder: (BuildContext context, int index) {
return new Card(child:
!snapshot.hasData ? new CircularProgressIndicator(
strokeWidth: 0.8,) : new Text("Snapshot data#$index")
);
});
})
);
}
}