问题描述
我在一个 SliverAppBar
中有多个 CustomScrollView
,屏幕主体在 SliverFillRemaining
内。
顶部 SliverAppBar 已固定
中间的 SliverAppBar 是一个图像,会随着用户滚动而折叠
底部 SliverAppBar 是一个 TabBar,它是固定的,在图像完全折叠后会留在第一个 SliverAppBar 下
目前的体验是,当你最初滚动时,body 滚动到最低的 SliverAppBar 下方。我已经尝试过使用 SliverOverlapAbsorber/Injector,但这只是在主体顶部添加了一个空间,以便空间重叠而不是主体重叠,但这不是我想要的。
我希望正文和 SliverAppBars 一起滚动,直到中间的 SliverAppBar 完全折叠,然后我希望正文滚动。
我已经研究了好几个小时了,你如何阻止身体在滚动时重叠?
解决方法
要实现这种滚动行为,使用 NestedScrollView
会更容易,请注意主应用栏不再位于条带中
import 'package:flutter/material.dart';
final Color darkBlue = Color.fromARGB(255,18,32,47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),debugShowCheckedModeBanner: false,home: Scaffold(
body: Center(
child: MyWidget(),),);
}
}
class MyWidget extends StatefulWidget {
@override
MyWidgetState createState() => MyWidgetState();
}
class MyWidgetState extends State<MyWidget>
with SingleTickerProviderStateMixin {
TabController _tabController;
@override
void initState() {
super.initState();
_tabController = TabController(vsync: this,length: 2);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('title'),elevation: 0,leading: IconButton(
icon: const Icon(Icons.arrow_back),onPressed: () {},body: NestedScrollView(
floatHeaderSlivers: true,physics: const BouncingScrollPhysics(),body: TabBarView(
controller: _tabController,physics: const NeverScrollableScrollPhysics(),children: [
SingleChildScrollView(
physics: const NeverScrollableScrollPhysics(),child: Column(
children: List.generate(
1000,(index) => Text('Tab One: $index'),SingleChildScrollView(
physics: const NeverScrollableScrollPhysics(),child: Column(
children: List.generate(
1000,(index) => Text('Tab Two: $index'),)),)
],headerSliverBuilder: (context,innerBoxIsScrolled) {
return <Widget>[
SliverAppBar(
pinned: true,floating: false,toolbarHeight: 0,collapsedHeight: null,automaticallyImplyLeading: false,expandedHeight: MediaQuery.of(context).size.height * .4,flexibleSpace: const FlexibleSpaceBar(
collapseMode: CollapseMode.parallax,background: Placeholder()),titleSpacing: 0,primary: false,SliverAppBar(
pinned: true,forceElevated: true,expandedHeight: 50,toolbarHeight: 50,title: Align(
alignment: Alignment.topCenter,child: TabBar(
controller: _tabController,isScrollable: true,tabs: [
const Text('Tab One'),const Text('Tab Two'),]),];
},);
}
}