Flutter中BottomNavigationBar收起键盘时白块闪烁问题排查
Flutter底部自定义导航栏键盘收起时白块闪烁问题
问题描述
自定义底部导航栏(通过Container实现),点击TextField弹出键盘后收起,底部组件区域会出现白块闪烁现象。
复现代码
import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; void main() { runApp(const MyApp()); SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle( statusBarColor: Colors.transparent, systemNavigationBarColor: Colors.transparent, )); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return const MaterialApp( title: 'Flutter Demo', home: MyHomePage(title: 'Flutter Demo Home Page'), ); } } class MyHomePage extends StatefulWidget { const MyHomePage({super.key, required this.title}); final String title; @override State<MyHomePage> createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { int _counter = 0; void _incrementCounter() { setState(() { _counter++; }); } @override Widget build(BuildContext context) { return AnnotatedRegion<SystemUiOverlayStyle>( value: SystemUiOverlayStyle( systemNavigationBarColor: Colors.black.withOpacity(0), ), child: Scaffold( extendBody: true, appBar: AppBar( backgroundColor: Theme.of(context).colorScheme.inversePrimary, title: Text(widget.title), ), bottomNavigationBar: SafeArea( child: Container( decoration: BoxDecoration( color: Theme.of(context).colorScheme.surface, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow(color: Theme.of(context).colorScheme.outlineVariant.withOpacity(0.5), blurRadius: 12), ], ), margin: const EdgeInsets.only(left: 38, right: 38, bottom: 7), padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 4), child: Row( children: [ FilledButton(onPressed: () {}, child: const Text('add')), FilledButton(onPressed: () {}, child: const Text('add')), ], ), ), ), body: CustomScrollView( slivers: [ const SliverToBoxAdapter( child: Column( children: [ ListTile(title: Text('Item 1')), ListTile(title: Text('Item 2')), ListTile(title: Text('Item 3')), ListTile(title: Text('Item 4')), ListTile(title: Text('Item 5')), ListTile(title: Text('Item 6')), ListTile(title: Text('Item 6')), ListTile(title: Text('Item 6')), ListTile(title: Text('Item 7')), ListTile(title: Text('Item 8')), ListTile(title: Text('Item 8')), ], ), ), const SliverToBoxAdapter( child: TextField(), ), SliverList.builder( itemBuilder: (v, a) { return Card( child: ListTile(title: Text('Item $a')), ); }, itemCount: 10), ], ), ), ); } }
问题原因
Scaffold设置了extendBody: true,允许body内容延伸至底部导航栏下方,但键盘收起的布局重绘过程中,底部导航栏区域的背景未被及时填充,露出了默认白色背景。- 全局和
AnnotatedRegion设置了透明系统导航栏,搭配SafeArea使用时,键盘收起的动画过渡阶段会出现短暂布局空白。
解决方案
方案1:给Scaffold设置统一背景色
给Scaffold添加与底部导航栏一致的背景色,确保重绘时底部区域不会露出白色:
Scaffold( extendBody: true, backgroundColor: Theme.of(context).colorScheme.surface, // 添加该行 // 其余代码不变 )
方案2:给底部导航栏外层添加背景容器
若不想修改整个页面背景色,可给bottomNavigationBar的SafeArea外层包裹同色容器填充底部区域:
bottomNavigationBar: Container( color: Theme.of(context).colorScheme.surface, // 填充背景色 child: SafeArea( child: Container( // 原有底部导航栏代码 ), ), )
方案3:调整系统导航栏设置(可选)
若无需透明导航栏,可修改SystemChrome和AnnotatedRegion中的systemNavigationBarColor为非透明色,避免过渡阶段空白:
SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle( statusBarColor: Colors.transparent, systemNavigationBarColor: Colors.white, // 设置为非透明色 )); // 同步修改AnnotatedRegion中的值 AnnotatedRegion<SystemUiOverlayStyle>( value: SystemUiOverlayStyle( systemNavigationBarColor: Colors.white, ), // 其余代码不变 )
内容的提问来源于stack exchange,提问作者laterday
相关产品推荐
相关产品推荐

