需要同时滚动ListView和GridView时可以使用SliverList和SliverGrid。
CustomScrollView( slivers: [ SliverList( delegate: SliverChildBuilderDelegate( (context, index) { return Container( height: 50, color: Colors.primaries[index % Colors.primaries.length], ); }, childCount: 5, ), ), SliverGrid( gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 3, crossAxisSpacing: 5, mainAxisSpacing: 5, ), delegate: SliverChildBuilderDelegate( (BuildContext context, int index) { return Container( color: Colors.primaries[index % Colors.primaries.length], ); }, childCount: 20, ), ), ], )
pinned:是否固定在屏幕顶部。
expandedHeight:展开区域的高度。
flexibleSpace:展开取消显示内容。
CustomScrollView( slivers: [ SliverAppBar( pinned: true, expandedHeight: 200, flexibleSpace: FlexibleSpaceBar( title: const Text("SliverAppBar"), background: Image.asset("images/avatar.jpg", fit: BoxFit.cover), ), ), SliverFixedExtentList( delegate: SliverChildBuilderDelegate( (BuildContext context, int index) { return Container( alignment: Alignment.center, color: Colors.primaries[index % Colors.primaries.length], child: Text("$index"), ); }, ), itemExtent: 50.0, ), ], )
SliverPersistentHeader组件可以控制滚动的最大高度和最小高度,类似SliverAppBar效果。
build:显示内容。
maxExtent & minExtent:滚动的高度范围。
shouldRebuild:是否需要更新。
CustomScrollView( slivers: [ SliverPersistentHeader( pinned: true, delegate: MySliverPersistentHeaderDelegate(), ), SliverGrid( gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 3, crossAxisSpacing: 5, mainAxisSpacing: 5, ), delegate: SliverChildBuilderDelegate( (BuildContext context, int index) { return Container( color: Colors.primaries[index % Colors.primaries.length], ); }, ), ), ], )
class MySliverPersistentHeaderDelegate extends SliverPersistentHeaderDelegate { @override Widget build( BuildContext context, double shrinkOffset, bool overlapsContent) { return Container( color: Colors.blue, alignment: Alignment.center, child: Text( "hello world", style: TextStyle(color: Colors.white), ), ); } @override double get maxExtent => 200; @override double get minExtent => 50; @override bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) { return false; } }
CustomScrollView只能包含Sliver组件,如果需要使用普通组件可以使用SliverToBoxAdapter。
CustomScrollView( slivers: [ SliverToBoxAdapter( child: Container( height: 200, color: Colors.black26, alignment: Alignment.center, child: Text("hello world"), ), ), SliverList( delegate: SliverChildBuilderDelegate( (BuildContext context, int index) { return Container( height: 60, color: Colors.primaries[index % Colors.primaries.length], ); }, childCount: 50, ), ), ], )
CustomScrollView组件可以将多个组件组合在一起,具有统一的滚动效果,但是CustomScrollView只能嵌套Sliver系列的组件,如SliverList、SliverGrid、SliverPadding、SliverAppBar等。
NestedScrollView可以协调两个滚动组件滑动。NestedScrollView在逻辑上将可滚动组件分为header和body两部分,heade部分只能接收Sliver类型的组件,而body部分可以接收任意类型的组件。
NestedScrollView( //Sliver组件 headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) { return [ SliverAppBar( title: const Text("嵌套ListView"), pinned: true, //固定AppBar forceElevated: true, ), SliverFixedExtentList( itemExtent: 50, delegate: SliverChildBuilderDelegate( (BuildContext context, int index) { return ListTile(title: Text("$index")); }, childCount: 5, ), ), ]; }, //滚动组件 body: ListView.builder( padding: const EdgeInsets.all(8), physics: const ClampingScrollPhysics(), //需要 itemCount: 30, itemBuilder: (BuildContext context, int index) { return SizedBox( height: 50, child: Center(child: Text("item $index")), ); }, ), )
NestedScrollView( headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) { return [ SliverAppBar( floating: true, snap: true, expandedHeight: 200, forceElevated: innerBoxIsScrolled, flexibleSpace: FlexibleSpaceBar( background: Image.asset( "images/logo.png", fit: BoxFit.cover, ), ), ), ]; }, body: CustomScrollView( slivers: [buildSliverList(50)], ), )
SliverAppBar+CustomScrollView组合,当反向滑动时,SliverAppBar就会整体回到屏幕顶部,出现遮挡问题,为了解决该问题,可以用在header里用SliverOverlapAbsorber组件包裹SliverAppBar,body里Sliver列表最前面添加一个SliverOverlapInjector。
NestedScrollView( headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) { return [ SliverOverlapAbsorber( handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), sliver: SliverAppBar( floating: true, snap: true, expandedHeight: 200, forceElevated: innerBoxIsScrolled, flexibleSpace: FlexibleSpaceBar( background: Image.asset( "images/logo.png", fit: BoxFit.cover, ), ), ), ), ]; }, body: Builder( builder: (BuildContext context) { return CustomScrollView( slivers: [ SliverOverlapInjector( handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), ), buildSliverList(50), ], ); }, ), )
class MyPageView extends StatefulWidget { late Listtabs; MyPageView({Key? key, required this.tabs}) : super(key: key); @override State createState() { return _MyPageViewState(); } } class _MyPageViewState extends State with SingleTickerProviderStateMixin { late TabController _controller; @override void initState() { super.initState(); _cOntroller= TabController(length: widget.tabs.length, vsync: this); } @override void dispose() { super.dispose(); _controller.dispose(); } @override Widget build(BuildContext context) { return NestedScrollView( headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) { return [ SliverOverlapAbsorber( handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), sliver: SliverAppBar( title: const Text("hi Flutter"), floating: true, snap: true, forceElevated: innerBoxIsScrolled, bottom: TabBar( controller: _controller, tabs: widget.tabs.map((e) => Tab(text: e)).toList(), ), ), ), ]; }, body: TabBarView( controller: _controller, children: widget.tabs.map((e) { return Builder(builder: (BuildContext context) { return CustomScrollView( key: PageStorageKey(e), slivers: [ SliverOverlapInjector( handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), ), SliverPadding( padding: const EdgeInsets.all(9), sliver: buildSliverList(50), ), ], ); }); }).toList(), ), ); } }
到此这篇关于Flutter Sliver滚动组件的文章就介绍到这了,更多相关Flutter 滚动组件内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!