Flutter UI 组件完全指南 Flutter UI 组件完全指南引言UI 组件是构建用户界面的基础。本文将深入探讨各种 Flutter UI 组件和最佳实践。基础概念回顾组件类型Material Components: Material Design 组件Cupertino Components: iOS 风格组件Custom Components: 自定义组件核心组件Container: 容器组件Row/Column: 布局组件Text: 文本组件Image: 图片组件Button: 按钮组件高级技巧一自定义按钮class GradientButton extends StatelessWidget { final String text; final VoidCallback onPressed; final double? width; final double? height; const GradientButton({ super.key, required this.text, required this.onPressed, this.width, this.height 50, }); override Widget build(BuildContext context) { return SizedBox( width: width, height: height, child: ElevatedButton( onPressed: onPressed, style: ElevatedButton.styleFrom( padding: EdgeInsets.zero, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ), ), child: Ink( decoration: const BoxDecoration( gradient: LinearGradient( colors: [Color(0xFF667eea), Color(0xFF764ba2)], ), borderRadius: BorderRadius.all(Radius.circular(8)), ), child: Container( alignment: Alignment.center, padding: const EdgeInsets.symmetric(horizontal: 32), child: Text( text, style: const TextStyle( color: Colors.white, fontSize: 16, fontWeight: FontWeight.w600, ), ), ), ), ), ); } }高级技巧二自定义卡片class GradientCard extends StatelessWidget { final Widget child; final double? borderRadius; final ListColor colors; const GradientCard({ super.key, required this.child, this.borderRadius 12, this.colors const [Color(0xFF667eea), Color(0xFF764ba2)], }); override Widget build(BuildContext context) { return Container( decoration: BoxDecoration( gradient: LinearGradient(colors: colors), borderRadius: BorderRadius.circular(borderRadius!), boxShadow: [ BoxShadow( color: colors[0].withOpacity(0.3), blurRadius: 12, offset: const Offset(0, 4), ), ], ), padding: const EdgeInsets.all(24), child: child, ); } }高级技巧三列表项组件class UserListItem extends StatelessWidget { final String avatarUrl; final String name; final String email; final VoidCallback onTap; const UserListItem({ super.key, required this.avatarUrl, required this.name, required this.email, required this.onTap, }); override Widget build(BuildContext context) { return ListTile( onTap: onTap, leading: CircleAvatar( backgroundImage: NetworkImage(avatarUrl), ), title: Text( name, style: const TextStyle( fontWeight: FontWeight.w600, fontSize: 16, ), ), subtitle: Text( email, style: TextStyle( color: Colors.grey[600], fontSize: 14, ), ), trailing: const Icon(Icons.arrow_forward_ios), ); } }实战案例表单组件class CustomTextField extends StatelessWidget { final String label; final String hintText; final TextEditingController controller; final TextInputType keyboardType; final bool obscureText; final String? Function(String?)? validator; const CustomTextField({ super.key, required this.label, required this.hintText, required this.controller, this.keyboardType TextInputType.text, this.obscureText false, this.validator, }); override Widget build(BuildContext context) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( label, style: const TextStyle( fontWeight: FontWeight.w500, fontSize: 14, color: Colors.grey[700], ), ), const SizedBox(height: 8), TextFormField( controller: controller, keyboardType: keyboardType, obscureText: obscureText, decoration: InputDecoration( hintText: hintText, hintStyle: TextStyle(color: Colors.grey[400]), border: OutlineInputBorder( borderRadius: BorderRadius.circular(8), borderSide: const BorderSide(color: Colors.grey), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(8), borderSide: const BorderSide(color: Color(0xFF667eea), width: 2), ), contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), ), validator: validator, ), ], ); } }实战案例加载状态组件class LoadingStateT extends StatelessWidget { final NetworkStateT state; final Widget Function(T) builder; final Widget? loadingWidget; final Widget? errorWidget; final Widget? emptyWidget; const LoadingState({ super.key, required this.state, required this.builder, this.loadingWidget, this.errorWidget, this.emptyWidget, }); override Widget build(BuildContext context) { switch (state.status) { case NetworkStatus.loading: return loadingWidget ?? const Center(child: CircularProgressIndicator()); case NetworkStatus.error: return errorWidget ?? Center(child: Text(state.errorMessage ?? 加载失败)); case NetworkStatus.success: if (state.data null) { return emptyWidget ?? const Center(child: Text(暂无数据)); } return builder(state.data!); case NetworkStatus.initial: return const SizedBox(); } } } // 使用 LoadingStateUser( state: userState, builder: (user) UserProfile(user: user), )实战案例底部导航栏class CustomBottomNav extends StatelessWidget { final int currentIndex; final ValueChangedint onTap; const CustomBottomNav({ super.key, required this.currentIndex, required this.onTap, }); final ListBottomNavigationBarItem items const [ BottomNavigationBarItem( icon: Icon(Icons.home), label: 首页, ), BottomNavigationBarItem( icon: Icon(Icons.search), label: 搜索, ), BottomNavigationBarItem( icon: Icon(Icons.person), label: 我的, ), ]; override Widget build(BuildContext context) { return BottomNavigationBar( currentIndex: currentIndex, onTap: onTap, items: items, selectedItemColor: const Color(0xFF667eea), unselectedItemColor: Colors.grey[500], showSelectedLabels: true, showUnselectedLabels: true, type: BottomNavigationBarType.fixed, ); } }实战案例悬浮按钮class FloatingActionButtonWidget extends StatelessWidget { final VoidCallback onPressed; final IconData icon; final String? tooltip; const FloatingActionButtonWidget({ super.key, required this.onPressed, required this.icon, this.tooltip, }); override Widget build(BuildContext context) { return FloatingActionButton( onPressed: onPressed, tooltip: tooltip, backgroundColor: const Color(0xFF667eea), foregroundColor: Colors.white, elevation: 4, child: Icon(icon), ); } }常见问题与解决方案Q1组件样式不一致A使用 ThemeDataMaterialApp( theme: ThemeData( primaryColor: const Color(0xFF667eea), buttonTheme: const ButtonThemeData( buttonColor: Color(0xFF667eea), ), ), )Q2组件布局问题A使用 LayoutBuilderLayoutBuilder( builder: (context, constraints) { return Container(width: constraints.maxWidth); }, )Q3组件性能问题A使用 const 构造函数const Text(Hello World);最佳实践1. 封装组件class CustomButton extends StatelessWidget { final String text; final VoidCallback onPressed; const CustomButton({super.key, required this.text, required this.onPressed}); override Widget build(BuildContext context) { return ElevatedButton( onPressed: onPressed, child: Text(text), ); } }2. 使用参数化组件class GradientCard extends StatelessWidget { final Widget child; final ListColor colors; const GradientCard({super.key, required this.child, required this.colors}); override Widget build(BuildContext context) { return Container( decoration: BoxDecoration( gradient: LinearGradient(colors: colors), ), child: child, ); } }3. 遵循单一职责// 好的做法每个组件只做一件事 class UserAvatar extends StatelessWidget { final String url; const UserAvatar({super.key, required this.url}); override Widget build(BuildContext context) { return CircleAvatar(backgroundImage: NetworkImage(url)); } }总结Flutter UI 组件是构建用户界面的基础。通过本文的学习你应该能够创建自定义按钮创建自定义卡片创建列表项组件创建表单组件实现加载状态组件创建底部导航栏掌握这些技巧能够帮助你构建更加美观和可维护的界面。