Flutter实现列表滚动覆盖头部至AppBar底部的问题求助
需求描述
我想要实现这样的效果:列表的白色区域可以滚动覆盖蓝色头部区域,直到到达AppBar底部,效果参考以下截图:

初始尝试代码(TestScreen)
class TestScreen extends StatelessWidget { const TestScreen({Key? key}) : super(key: key); @override Widget build(BuildContext context) { double height = MediaQuery.of(context).size.height; AppController appController = Provider.of<AppController>(context); HomeController homeController = Provider.of<HomeController>(context); String selectedCategory = homeController.selectedCategory; return SafeArea( child: Container( //height: 450, width: double.infinity, decoration: const BoxDecoration( image: DecorationImage( image: AssetImage('assets/images/home_header.png'), alignment: Alignment.topCenter, repeat: ImageRepeat.repeatY, )), child: Scaffold( appBar: AppBar( backgroundColor: Colors.transparent, elevation: 0, flexibleSpace: Padding( padding: const EdgeInsets.only(left: 20, right: 20), child: ChiscoAppbar( icon: MENU, iconAlignment: Alignment.centerLeft, title: 'خانه', onClick: () { Navigator.pushNamed(context, '/account'); }, ), ), ), backgroundColor: Colors.transparent, body: Stack( children: [ Positioned( child: Container( color: Colors.transparent, height: 200, child: Column( mainAxisSize: MainAxisSize.min, children: [ const Expanded( flex: 3, child: Align( alignment: Alignment.center, child: ChiscoText( text: 'دستگاههای هوشمند چیسکو', fontWeight: FontWeight.w500, textColor: Colors.white, fontSize: 16, )), ), Expanded( flex: 1, child: Padding( padding: EdgeInsets.only(left: 20, right: 20), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: const [ HeaderItem( titleText: 'کنترلر', icon: COOLER, counterText: '2', ), HeaderItem( titleText: 'سه راهی', icon: SOCKET, counterText: '2', ) ], ), )), ], ), ), ), Positioned( top: homeController.customPixel+20 , bottom: 0, child: Container( color: Styles.backGroundColor, height: MediaQuery.of(context).size.height, width: MediaQuery.of(context).size.width, )), NotificationListener<ScrollNotification>( onNotification: homeController.scrollNotification, child: CustomScrollView( slivers: [ SliverToBoxAdapter( child: Container( height: 200, color: Colors.transparent, )), SliverPersistentHeader( delegate: OnTapHeader(), floating: false, pinned: true, ), SliverToBoxAdapter( child: Container( margin: const EdgeInsets.fromLTRB(20, 8, 20, 10), height: 30, child: ListView.builder( physics: const BouncingScrollPhysics(), itemCount: appController.listOfDevicesCategory.length, scrollDirection: Axis.horizontal, primary: true, addSemanticIndexes: false, itemBuilder: (context, index) { String category = appController.listOfDevicesCategory[index]; return CategoryListItem( isSelected: selectedCategory == category, category: category, ); }), )), DeviceGridList() ], ), ), ], ), floatingActionButton:Container( margin: const EdgeInsets.only(bottom: 16), child: const ChiscoSpeedDial()), floatingActionButtonLocation: FloatingActionButtonLocation.startDocked, ), ), ); } }
使用Sliver组件时,白色区域会折叠蓝色头部区域,无法达到预期效果;且正常状态下白色区域需位于蓝色区域上方,请问如何实现该需求?
更新尝试(使用DraggableScrollableSheet)
我尝试使用DraggableScrollableSheet来实现列表,但内部嵌套Column后效果异常,效果如下:
对应的HomeScreen代码:
class HomeScreen extends StatelessWidget { const HomeScreen({Key? key}) : super(key: key); @override Widget build(BuildContext context) { double height = MediaQuery.of(context).size.height; AppController appController = Provider.of<AppController>(context); HomeController homeController = Provider.of<HomeController>(context); String selectedCategory = homeController.selectedCategory; return SafeArea( child: Container( //height: 450, width: double.infinity, decoration: const BoxDecoration( image: DecorationImage( image: AssetImage('assets/images/home_header.png'), alignment: Alignment.topCenter, )), child: Scaffold( appBar: AppBar( backgroundColor: Colors.transparent, elevation: 0, flexibleSpace: Padding( padding: const EdgeInsets.only(left: 20, right: 20), child: ChiscoAppbar( icon: MENU, iconAlignment: Alignment.centerLeft, title: 'خانه', onClick: () { Navigator.pushNamed(context, '/account'); }, ), ), ), backgroundColor: Colors.transparent, body: Stack( children: [ Positioned( child: Container( color: Colors.transparent, height: 200, child: Column( mainAxisSize: MainAxisSize.min, children: [ const Expanded( flex: 3, child: Align( alignment: Alignment.center, child: ChiscoText( text: 'دستگاههای هوشمند چیسکو', fontWeight: FontWeight.w500, textColor: Colors.white, fontSize: 16, )), ), Expanded( flex: 1, child: Padding( padding: EdgeInsets.only(left: 20, right: 20), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: const [ HeaderItem( titleText: 'کنترلر', icon: COOLER, counterText: '2', ), HeaderItem( titleText: 'سه راهی', icon: SOCKET, counterText: '2', ) ], ), )), ], ), ), ), Positioned( child: DraggableScrollableSheet( expand: true, minChildSize: 0.70, maxChildSize: 0.95, initialChildSize: 0.70, builder: (context, scrollController) { return Container( decoration: BoxDecoration( color: Colors.blue[100], borderRadius: const BorderRadius.only( topLeft: Radius.circular(25), topRight: Radius.circular(25))), child: SingleChildScrollView( controller: scrollController, child: Column( mainAxisSize: MainAxisSize.min, children: [ ListHandlerView(), Container( margin: const EdgeInsets.fromLTRB(20, 8, 20, 10), height: 30, child: ListView.builder( shrinkWrap: true, physics: const BouncingouncingScrollPhysics(), itemCount: appController.listOfDevicesCategory.length, scrollDirection: Axis.horizontal, primary: true, addSemanticIndexes: false, itemBuilder: (context, index) { String category = appController .listOfDevicesCategory[index]; return CategoryListItem( isSelected: selectedCategory == category, category: category, ); }), ), Container( decoration: BoxDecoration( color: Colors.blue[100], borderRadius: const BorderRadius.only( topLeft: Radius.circular(25), topRight: Radius.circular(25))), child: ListView.builder( shrinkWrap: true, itemCount: 25, controller: scrollController, itemBuilder: (BuildContext context, int index) { return ListTile(title: Text('Item $index')); }, ), ), ], ), ), ); }, ), ) ], ), floatingActionButton: Container( margin: const EdgeInsets.only(bottom: 16), child: const ChiscoSpeedDial()), floatingActionButtonLocation: FloatingActionButtonLocation.startDocked, ), ), ); } }
内容的提问来源于stack exchange,提问作者MehdiAbolhassani
相关产品推荐
相关产品推荐

