Flutter自定义Drawer用Expanded/Flexible构建失败求助
Flutter Drawer自适应布局问题解决
问题场景
自定义Flutter Drawer时,尝试用Expanded/Flexible包裹Text或CircleAvatar会导致布局构建失败。需要在Web端调整屏幕尺寸时,让文本和CircleAvatar自动适配大小,之前用LayoutBuilder没解决问题。
问题原因
- Expanded必须在有明确主轴约束的父组件中使用,而你的Column嵌套在Row里,Row垂直方向没有固定高度,Expanded无法获取有效约束,导致布局报错。
- CircleAvatar用固定radius值,无法随屏幕尺寸变化自适应缩放。
修复步骤
- 移除文本外层的Expanded:文本组件本身不需要Expanded分配垂直空间,直接保留Text,通过
FittedBox实现文本自适应缩放,避免溢出。 - 动态计算CircleAvatar的半径:根据Drawer的宽度按比例设置radius,确保头像随Drawer大小缩放。
- 用Flexible包裹右侧文本列:让文本区域在Row中占据剩余可用空间,避免水平方向溢出。
修改后的关键代码片段
自适应CircleAvatar部分
Padding( padding: const EdgeInsets.all(8.0), child: CircleAvatar( // 根据Drawer宽度的1/8动态计算半径 radius: MediaQuery.of(context).size.width * 0.6 / 8, backgroundColor: const Color(0xffF1C452), child: CircleAvatar( radius: MediaQuery.of(context).size.width * 0.6 / 8 - 4, child: Image.asset("assets/images/userImage.png"), ), ), )
修复后的文本列部分
Flexible( child: Padding( padding: const EdgeInsets.all(16.0), child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start, children: [ // 用FittedBox让文本自适应宽度,避免溢出 FittedBox( fit: BoxFit.scaleDown, alignment: Alignment.centerLeft, child: Text( "Zee Lounge", style: TextStyle( color: const Color(0xffF1C452), fontSize: 28, ), ), ), const SizedBox(height: 8), FittedBox( fit: BoxFit.scaleDown, alignment: Alignment.centerLeft, child: Text( " 0300 000 0000", style: TextStyle( color: const Color(0xffFFFFFF), fontSize: 16, ), ), ), const SizedBox(height: 8), Row( children: [ const Icon( Icons.star, color: Color(0xff8EA659), ), const SizedBox(width: 4), FittedBox( fit: BoxFit.scaleDown, child: Text( "4.5(5 Reviews)", style: TextStyle( color: const Color(0xff8EA659), fontSize: 16, ), ), ) ], ), ], ), ), )
完整修复代码
import 'package:flutter/material.dart'; class BistroCustomDrawer extends StatelessWidget { const BistroCustomDrawer({super.key}); @override Widget build(BuildContext context) { final drawerWidth = MediaQuery.of(context).size.width * 0.6; return Drawer( width: drawerWidth, child: Container( color: Colors.black, child: SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.end, children: [ Padding( padding: const EdgeInsets.all(16.0), child: InkWell( onTap: () => Navigator.of(context).pop(), child: const Icon(Icons.close, color: Color(0xffF1C452)), ), ) ], ), Padding( padding: const EdgeInsets.all(16.0), child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ Padding( padding: const EdgeInsets.all(8.0), child: CircleAvatar( radius: drawerWidth / 8, backgroundColor: const Color(0xffF1C452), child: CircleAvatar( radius: drawerWidth / 8 - 4, child: Image.asset("assets/images/userImage.png"), ), ), ), Flexible( child: Padding( padding: const EdgeInsets.all(16.0), child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start, children: [ FittedBox( fit: BoxFit.scaleDown, alignment: Alignment.centerLeft, child: Text( "Zee Lounge", style: TextStyle( color: const Color(0xffF1C452), fontSize: 28, ), ), ), const SizedBox(height: 8), FittedBox( fit: BoxFit.scaleDown, alignment: Alignment.centerLeft, child: Text( " 0300 000 0000", style: TextStyle( color: const Color(0xffFFFFFF), fontSize: 16, ), ), ), const SizedBox(height: 8), Row( children: [ const Icon( Icons.star, color: Color(0xff8EA659), ), const SizedBox(width: 4), FittedBox( fit: BoxFit.scaleDown, child: Text( "4.5(5 Reviews)", style: TextStyle( color: const Color(0xff8EA659), fontSize: 16, ), ), ) ], ), ], ), ), ) ], ), ), Container( width: double.infinity, color: const Color(0xff212129), padding: const EdgeInsets.only(left: 16, top: 6, bottom: 6), child: const Text( "Profile Details", style: TextStyle( color: Color(0xffF1C452), fontSize: 24, fontWeight: FontWeight.bold, ), ), ), const Padding( padding: EdgeInsets.only(left: 16, top: 6, bottom: 0), child: Text( "What inspired me to become a host?", style: TextStyle( color: Color(0xffFEE4A4), fontSize: 18, fontWeight: FontWeight.bold, ), ), ), const Padding( padding: EdgeInsets.only(left: 16, top: 0, bottom: 6), child: Text( "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod temp", style: TextStyle( color: Color(0xff909094), fontSize: 16, ), ), ), const Padding( padding: EdgeInsets.only(left: 16, top: 6, bottom: 0), child: Text( "My Culnary journey", style: TextStyle( color: Color(0xffFEE4A4), fontSize: 18, fontWeight: FontWeight.bold, ), ), ), const Padding( padding: EdgeInsets.only(left: 16, top: 0, bottom: 6), child: Text( "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod temp", style: TextStyle( color: Color(0xff909094), fontSize: 16, ), ), ), const Padding( padding: EdgeInsets.only(left: 16, top: 6, bottom: 0), child: Text( "My Interests", style: TextStyle( color: Color(0xffFEE4A4), fontSize: 18, fontWeight: FontWeight.bold, ), ), ), const Padding( padding: EdgeInsets.only(left: 16, top: 0, bottom: 6), child: Text( "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod temp", style: TextStyle( color: Color(0xff909094), fontSize: 16, ), ), ), const Padding( padding: EdgeInsets.only(left: 16, top: 6, bottom: 0), child: Text( "Social Media Handles", style: TextStyle( color: Color(0xffFEE4A4), fontSize: 18, fontWeight: FontWeight.bold, ), ), ), const Padding( padding: EdgeInsets.only(left: 16, top: 0, bottom: 6), child: Text( "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod temp", style: TextStyle( color: Color(0xff909094), fontSize: 16, ), ), ), ], ), ), ), ); } }
内容的提问来源于stack exchange,提问作者farhan khan
相关产品推荐
相关产品推荐

