Flutter滚动ListView时实现透明AppBar 列表项显示在其下层
问题根源
你当前代码无法实现预期效果,核心是两个Flutter默认布局机制没做适配:
- Scaffold的
body默认会从AppBar下边缘开始布局,就算AppBar设为透明,列表内容也不会延伸到AppBar所在区域,自然做不到内容在透明AppBar下层显示的效果 - AppBar默认自带4个单位的elevation阴影,透明状态下阴影会非常突兀,破坏视觉效果
修复方案
按以下几点调整代码即可:
- 给Scaffold添加
extendBodyBehindAppBar: true属性,允许body内容延伸布局到AppBar的后方区域 - 给AppBar添加
elevation: 0属性,移除默认阴影 - 给ListView设置顶部内边距,值为状态栏高度+AppBar默认高度,避免初始非透明状态下顶部列表项被AppBar遮挡
- 保留你原有的滚动监听逻辑,根据滚动偏移切换AppBar背景色即可
修复后可运行代码
import 'package:flutter/material.dart'; class HomeScreen extends StatefulWidget { @override State<HomeScreen> createState() => _HomeScreenState(); } class _HomeScreenState extends State<HomeScreen> { int _selectIndex = 0; bool isAppbarCollapsing = false; final ScrollController _homeController = ScrollController(); List<String> notelist = [ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K','L','M','N','O','P','Q','R','S','T','U','V' ]; @override void initState() { super.initState(); _initializeController(); } @override void dispose() { _homeController.dispose(); super.dispose(); } void _initializeController(){ _homeController.addListener(() { if(_homeController.offset == 0.0 && !_homeController.position.outOfRange){ if(!mounted) return; setState(() => isAppbarCollapsing = false); } if(_homeController.offset >= 9.0 && !_homeController.position.outOfRange){ if(!mounted) return; setState(() => isAppbarCollapsing = true); } }); } @override Widget build(BuildContext context) { return Scaffold( // 允许body内容延伸到AppBar后方 extendBodyBehindAppBar: true, appBar: AppBar( title: const Text('Transparent Demo'), backgroundColor: isAppbarCollapsing ? Colors.transparent : Colors.blue, // 移除默认阴影 elevation: 0, ), body: MyBody(), ); } Widget MyBody() { return Center( child: Padding( padding: const EdgeInsets.all(20.0), child: Column( children: [ Expanded( child: ListView.builder( controller: _homeController, shrinkWrap: true, // 增加顶部padding避免初始状态内容被AppBar遮挡 padding: EdgeInsets.only(top: MediaQuery.of(context).padding.top + kToolbarHeight), itemCount: notelist.length, itemBuilder: (context, index) { return Card( color: Colors.orange, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(20.0)), child: ListTile( onTap: (){ }, title: Text(notelist[index]), leading: CircleAvatar( radius: 30.0, child: Text(notelist[index][0],style: const TextStyle( color: Colors.white, ),), ), trailing: const Icon(Icons.delete), ), ); }), ), ], ), ), ); } }
效果说明
滚动偏移小于9px时AppBar显示为不透明蓝色,滚动超过9px后AppBar变为全透明,列表项会从AppBar下方滑过,实现穿透显示效果。如果需要平滑的渐变透明过渡,可以将布尔状态替换为0-1区间的透明度数值,根据滚动偏移实时计算值赋值给AppBar背景色即可。
内容的提问来源于stack exchange,提问作者Irfan Ganatra
相关产品推荐
相关产品推荐

