Flutter实现搜索框跨AppBar与Body区域显示的方案
解决AppBar与Body间悬浮搜索框的显示问题
我在Flutter应用中实现了带渐变背景的AppBar,Body部分用Expanded包裹了列表组件。想要在AppBar和Body之间放置一个悬浮的搜索框,但使用Stack布局时,超出AppBar或Body范围的部分无法显示出来。
以下是我的原始代码:
appBar: PreferredSize( preferredSize: const Size.fromHeight(100), child: Stack( children: [ AppBar( backgroundColor: Colors.transparent, flexibleSpace: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(25), gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ Theme.of(context).colorScheme.secondary, Theme.of(context).colorScheme.primary, ], stops: const [ 0.0, 0.69, ], ), ), ), title: Text( title, style: TextStyle( shadows: [ Shadow( color: tonsDeAzul[12], offset: const Offset(0, -8), ), ], color: Colors.transparent, decoration: TextDecoration.underline, decorationColor: tonsDeAzul[12], decorationThickness: 3, ), ), centerTitle: false, automaticallyImplyLeading: false, actions: [ Padding( padding: const EdgeInsets.only(right: 5.0), child: TextButton( child: Icon( Icons.comment_outlined, color: tonsDeAzul[12], ), onPressed: () { print("Open messages"); }, ), ) ], ), Positioned( bottom: -25, left: 20, right: 20, child: StandardSearch( textController: _searchController, label: "Pesquisar por palavra ou código", onSubmit: () {}, )) ], ), ), body: Container( color: Theme.of(context).colorScheme.surfaceVariant, child: clients != null ? Column( children: [ Padding( padding: const EdgeInsets.symmetric( vertical: 24, horizontal: 16, ), child: StandardSearch( textController: _searchController, label: "Pesquisar por palavra ou código", onSubmit: () {}, ), ), Expanded( child: ListView.builder( itemCount: clients.length, itemBuilder: (context, index) { final item = clients[index]; return Padding( padding: const EdgeInsets.only(bottom: 8), child: InkWell( onTap: () { openPedidoDialog(item, cubit); }, child: Column( children: [ clientCard(item, context), const Divider(), ], ), ), ); }, ), ), ], ) : const Text("Não foi possível encontrar clientes"))

解决方法
问题出在两个地方:一是AppBar的PreferredSize高度限制了布局范围,超出部分被裁剪;二是Body的顶部没有留出搜索框的空间,导致内容被遮挡。按以下步骤修改:
调整AppBar的PreferredSize高度
把原来的Size.fromHeight(100)改为Size.fromHeight(125),预留出搜索框向下偏移的25像素高度,确保搜索框超出AppBar的部分不会被裁剪。给Body顶部添加间距
在Body的Column开头添加一个SizedBox(height: 25),避免列表内容被悬浮的搜索框挡住。同时删除Body里原来的StandardSearch组件,避免重复显示。
修改后的完整代码
appBar: PreferredSize( preferredSize: const Size.fromHeight(125), // 调整高度容纳搜索框 child: Stack( children: [ AppBar( backgroundColor: Colors.transparent, flexibleSpace: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(25), gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ Theme.of(context).colorScheme.secondary, Theme.of(context).colorScheme.primary, ], stops: const [ 0.0, 0.69, ], ), ), ), title: Text( title, style: TextStyle( shadows: [ Shadow( color: tonsDeAzul[12], offset: const Offset(0, -8), ), ], color: Colors.transparent, decoration: TextDecoration.underline, decorationColor: tonsDeAzul[12], decorationThickness: 3, ), ), centerTitle: false, automaticallyImplyLeading: false, actions: [ Padding( padding: const EdgeInsets.only(right: 5.0), child: TextButton( child: Icon( Icons.comment_outlined, color: tonsDeAzul[12], ), onPressed: () { print("Open messages"); }, ), ) ], ), Positioned( bottom: -25, left: 20, right: 20, child: StandardSearch( textController: _searchController, label: "Pesquisar por palavra ou código", onSubmit: () {}, )) ], ), ), body: Container( color: Theme.of(context).colorScheme.surfaceVariant, child: clients != null ? Column( children: [ SizedBox(height: 25), // 给搜索框留出空间 Expanded( child: ListView.builder( itemCount: clients.length, itemBuilder: (context, index) { final item = clients[index]; return Padding( padding: const EdgeInsets.only(bottom: 8), child: InkWell( onTap: () { openPedidoDialog(item, cubit); }, child: Column( children: [ clientCard(item, context), const Divider(), ], ), ), ); }, ), ), ], ) : const Text("Não foi possível encontrar clientes"))
内容的提问来源于stack exchange,提问作者Gustavo F.
相关产品推荐
相关产品推荐

