赞
踩
什么是滚动组件?
滚动组件指可以通过滚动(滑动)手势控制可见区域的组件,在Flutter中可以分为盒子布局(RenderBox)和滚动布局(RenderSliver),我们本次讨论的就是构建滚动布局的组件
滚动组件有哪些
按照类型可以分为完整滚动组件和Sliver类型组件,常见的完整滚动组件有:ListView、GridView、PageView等,常见的Sliver类型组件有SliverList,SliverGrid、SliverFixedExtentList等
什么是Sliver类型组件?为什么需要使用Sliver类型的滚动组件?
Sliver类型组件也是滚动组件,只是它们并非是完整的,即无法单独的存在,完整的滚动组件包含Scrollable、Viewport和Sliver,但是完整的滚动组件也只能在页面中存在一个,如果我们需要在页面中构建多个可滚动组件,那么我们就需要使用Sliver组件进行构建,可以认为Sliver组件是功能组件的多滚动环境替代品
Sliver组件一般以Sliver开头或结尾,从名字大抵就可以判断它的替代对象是谁,比如SliverList与ListView,SliverGrid与GridView
如何使用Sliver组件?
Sliver组件可以通过CustomScrollView组件来构建,CustomScrollView允许定义多个Sliver类型组件,我们可以基于以上,构建一个比较完整的页面结构
import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatefulWidget { const MyApp({super.key}); @override MyAppState createState() => MyAppState(); } class MyAppState extends State<MyApp> with SingleTickerProviderStateMixin { late TabController _controller; @override void initState() { super.initState(); _controller = TabController(length: 2, vsync: this); _controller.addListener(() { if (kDebugMode) { print(_controller.index); } }); } _mySliverChildBuilderDelegate() { return SliverChildBuilderDelegate( (BuildContext context, int index) { return Container( height: 30, color: Colors.primaries[index % 8], ); }, childCount: 20, ); } _mySliverGridDelegateWithFixedCrossAxisCount() { return const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 5, mainAxisSpacing: 10, crossAxisSpacing: 5, childAspectRatio: 1, ); } @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar( title: const Text('Sliver Demo'), bottom: TabBar( controller: _controller, tabs: const <Widget>[ Tab(text: 'Tab1'), Tab(text: 'Tab2'), ], ), ), body: TabBarView( controller: _controller, children: <Widget>[ CustomScrollView( slivers: [ SliverGrid( delegate: _mySliverChildBuilderDelegate(), gridDelegate: _mySliverGridDelegateWithFixedCrossAxisCount(), ), SliverList(delegate: _mySliverChildBuilderDelegate()) ], ), const Text('Tab2 content'), ], ))); } }
上述结构中使用了Scaffold脚手架定义了固定的AppBar,但是如果想要将AppBar替换为动态的SliverAppBar(一般是下拉缩小或隐藏),那么继续使用CustomScrollView来构建就会麻烦许多了,特别与TarBarView的融合,这时我们可以使用NestedScrollView组件来构建
NestedScrollView提供了一个包含header、body两段结构的框架,header中允许定义多个Sliver类型的组件,body中允许定义一个完整滚动组件,当然,我们也可以定义为CustomScrollView类型,实现如下:
import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatefulWidget { const MyApp({super.key}); @override MyAppState createState() => MyAppState(); } class MyAppState extends State<MyApp> with SingleTickerProviderStateMixin { late TabController _controller; @override void initState() { super.initState(); _controller = TabController(length: 2, vsync: this); _controller.addListener(() { if (kDebugMode) { print(_controller.index); } }); } _mySliverChildBuilderDelegate() { return SliverChildBuilderDelegate( (BuildContext context, int index) { return Container( height: 30, color: Colors.primaries[index % 8], ); }, childCount: 20, ); } _mySliverGridDelegateWithFixedCrossAxisCount() { return const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 5, mainAxisSpacing: 10, crossAxisSpacing: 5, childAspectRatio: 1, ); } @override Widget build(BuildContext context) { return MaterialApp( home: NestedScrollView( headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) { return <Widget>[ SliverAppBar( title: const Text('Sliver Demo'), pinned: true, expandedHeight: 100, forceElevated: innerBoxIsScrolled, bottom: TabBar( controller: _controller, tabs: const <Widget>[ Tab(text: 'Tab1'), Tab(text: 'Tab2'), ], ), )]; }, body: TabBarView( controller: _controller, children: <Widget>[ CustomScrollView( slivers: [ SliverGrid( delegate: _mySliverChildBuilderDelegate(), gridDelegate: _mySliverGridDelegateWithFixedCrossAxisCount(), ), SliverList(delegate: _mySliverChildBuilderDelegate()) ], ), const Text('Tab2 content'), ], ))); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。