Flutter控件归纳总结
Flutter 的控件(Widget)是构建 UI 的基础,分为无状态(StatelessWidget)和有状态(StatefulWidget)两大类。以下是 Flutter 核心控件的系统归纳:
一、基础布局控件
-
Container
- 通用容器:支持装饰(颜色、边框、阴影)、内外边距、尺寸约束。
- 示例:
Container(color: Colors.blue, padding: EdgeInsets.all(16))
-
Row
/Column
- 线性布局:水平(
Row
)或垂直(Column
)排列子控件。 - 关键属性:
mainAxisAlignment
(主轴对齐)、crossAxisAlignment
(交叉轴对齐)。 - 子控件常用:
Expanded
(按比例填充剩余空间)、Flexible
(灵活伸缩)。
- 线性布局:水平(
-
Stack
- 层叠布局:子控件重叠(如文字+图片)。
- 配合
Positioned
定位:Positioned(top: 10, left: 20, child: ...)
-
ListView
- 滚动列表:
ListView(children: [...])
(静态列表)ListView.builder()
(动态懒加载,大数据集首选)
- 滚动列表:
-
GridView
- 网格布局:
GridView.count(crossAxisCount: 2)
(固定列数)GridView.builder()
(动态构建)
- 网格布局:
二、常用功能控件
-
文本显示
Text("Hello", style: TextStyle(fontSize: 20))
RichText
:混合样式文本。
-
图片
Image.asset("assets/logo.png")
(本地资源)Image.network("https://...")
(网络图片)
-
按钮
ElevatedButton
:凸起按钮(主操作)TextButton
:文本按钮(次要操作)IconButton
:图标按钮(工具栏)FloatingActionButton
:悬浮动作按钮(FAB)
-
输入控件
TextField
:文本输入框Checkbox
/Switch
:勾选框/开关Radio
/Slider
:单选按钮/滑块
-
对话框
AlertDialog
:提示对话框showModalBottomSheet
:底部弹窗
三、导航与路由
-
页面导航
Navigator.push(context, MaterialPageRoute(builder: (context) => NextPage())); Navigator.pop(context); // 返回
-
命名路由
// 定义路由表 MaterialApp(routes: {'/home': (context) => HomePage(),'/detail': (context) => DetailPage(),}, ); // 跳转 Navigator.pushNamed(context, '/detail');
四、状态管理控件
-
有状态组件
StatefulWidget
+setState()
:局部状态刷新。- 示例:计数器应用。
-
状态管理方案(进阶)
Provider
:官方推荐,依赖注入。Bloc
/Riverpod
:响应式状态管理。ValueListenableBuilder
:监听值变化局部刷新。
五、Material & Cupertino 风格控件
-
Material Design (Android)
Scaffold
:页面骨架(AppBar、Drawer、BottomNavigationBar)。AppBar
:顶部导航栏。BottomNavigationBar
:底部导航。Card
:卡片容器。
-
Cupertino (iOS)
CupertinoApp
/CupertinoPageScaffold
CupertinoButton
/CupertinoTextField
CupertinoPicker
:iOS风格选择器。
六、动画与高级控件
-
隐式动画
AnimatedContainer
:自动过渡的容器。AnimatedOpacity
:透明度渐变。
-
显式动画
AnimationController
:控制动画周期。Tween
:定义动画值范围。AnimatedBuilder
:自定义动画构建。
-
高级组件
FutureBuilder
:异步数据加载(如API请求)。StreamBuilder
:实时数据流(如WebSocket)。Hero
:页面间共享元素动画。
七、自定义控件
-
组合现有控件
class CustomButton extends StatelessWidget {Widget build(BuildContext context) {return Container(decoration: BoxDecoration(...),child: Text("Click"),);} }
-
自绘控件
- 继承
CustomPainter
,使用Canvas
绘制图形(如自定义图表)。
- 继承
八、性能优化控件
-
const
构造函数- 减少重建:
const Text("Static")
。
- 减少重建:
-
懒加载控件
ListView.builder()
:仅渲染可见区域。FutureBuilder
:按需加载数据。
-
RepaintBoundary
- 隔离重绘区域,提升性能。
完整示例:基础页面结构
class HomePage extends StatelessWidget {Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("首页")),body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: [Text("Hello Flutter!"),ElevatedButton(onPressed: () => Navigator.pushNamed(context, '/detail'),child: Text("跳转详情"),),],),),bottomNavigationBar: BottomNavigationBar(items: [BottomNavigationBarItem(icon: Icon(Icons.home), ...],),);}
}
下面我将为Flutter的核心控件补充完整代码示例,涵盖布局、交互、导航和状态管理等关键场景:
下面我将为Flutter的核心控件补充完整代码示例,涵盖布局、交互、导航和状态管理等关键场景:
1. 基础布局组合示例
class LayoutDemo extends StatelessWidget { Widget build(BuildContext context) {return Scaffold(body: Column(children: [// 顶部导航栏Container(height: 60,color: Colors.blue,child: Row(children: [IconButton(icon: Icon(Icons.menu), onPressed: () {}),Text('布局示例', style: TextStyle(color: Colors.white)),],),),// 内容区域Expanded(child: ListView(children: [// 网格布局GridView.count(shrinkWrap: true,physics: NeverScrollableScrollPhysics(),crossAxisCount: 3,children: List.generate(9, (index) {return Container(margin: EdgeInsets.all(8),color: Colors.amber[100 * (index % 9)],child: Center(child: Text('Item $index')),);}),),// 层叠布局Stack(alignment: Alignment.center,children: [Container(height: 200, color: Colors.green),Positioned(bottom: 20,child: Card(elevation: 8,child: Padding(padding: EdgeInsets.all(16),child: Text('浮动卡片', style: TextStyle(fontSize: 24)),),),)],),// 输入区域Padding(padding: EdgeInsets.all(16),child: TextField(decoration: InputDecoration(border: OutlineInputBorder(),labelText: '输入内容',suffixIcon: Icon(Icons.search),),),)],),)],),);}
}
2. 状态管理完整示例
class CounterApp extends StatefulWidget { _CounterAppState createState() => _CounterAppState();
}class _CounterAppState extends State<CounterApp> {int _counter = 0;bool _isDarkMode = false;void _incrementCounter() {setState(() {_counter++;});}void _toggleTheme() {setState(() {_isDarkMode = !_isDarkMode;});} Widget build(BuildContext context) {return MaterialApp(theme: _isDarkMode ? ThemeData.dark() : ThemeData.light(),home: Scaffold(appBar: AppBar(title: Text('状态管理示例'),actions: [IconButton(icon: Icon(_isDarkMode ? Icons.light_mode : Icons.dark_mode),onPressed: _toggleTheme,)],),body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: [Text('当前计数:', style: TextStyle(fontSize: 24)),Text('$_counter', style: TextStyle(fontSize: 48, fontWeight: FontWeight.bold)),SizedBox(height: 30),Row(mainAxisAlignment: MainAxisAlignment.center,children: [ElevatedButton(onPressed: _incrementCounter,child: Text('增加'),),SizedBox(width: 20),OutlinedButton(onPressed: () {setState(() {_counter = 0;});},child: Text('重置'),),],)],),),floatingActionButton: FloatingActionButton(onPressed: _incrementCounter,tooltip: '增加',child: Icon(Icons.add),),),);}
}
3. 导航与路由完整示例
void main() => runApp(NavigationApp());class NavigationApp extends StatelessWidget { Widget build(BuildContext context) {return MaterialApp(initialRoute: '/',routes: {'/': (context) => HomeScreen(),'/details': (context) => DetailScreen(),'/settings': (context) => SettingsScreen(),},);}
}class HomeScreen extends StatelessWidget { Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text('首页')),body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: [ElevatedButton(onPressed: () {// 基本导航Navigator.push(context,MaterialPageRoute(builder: (context) => DetailScreen(),),);},child: Text('前往详情页'),),SizedBox(height: 20),ElevatedButton(onPressed: () {// 命名路由导航Navigator.pushNamed(context, '/settings');},child: Text('前往设置页'),),SizedBox(height: 20),ElevatedButton(onPressed: () async {// 带返回值的导航final result = await Navigator.push(context,MaterialPageRoute(builder: (context) => SelectionScreen(),),);ScaffoldMessenger.of(context)..removeCurrentSnackBar()..showSnackBar(SnackBar(content: Text('选择了: $result')));},child: Text('选择选项'),),],),),);}
}class DetailScreen extends StatelessWidget { Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text('详情页')),body: Center(child: ElevatedButton(onPressed: () {Navigator.pop(context);},child: Text('返回'),),),);}
}class SettingsScreen extends StatelessWidget { Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text('设置页')),body: Center(child: ElevatedButton(onPressed: () {Navigator.popUntil(context, ModalRoute.withName('/'));},child: Text('返回首页'),),),);}
}class SelectionScreen extends StatelessWidget { Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text('选择选项')),body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: [ChoiceButton(choice: '选项A'),ChoiceButton(choice: '选项B'),ChoiceButton(choice: '选项C'),],),),);}
}class ChoiceButton extends StatelessWidget {final String choice;const ChoiceButton({Key? key, required this.choice}) : super(key: key); Widget build(BuildContext context) {return ElevatedButton(onPressed: () {Navigator.pop(context, choice);},child: Text(choice),style: ElevatedButton.styleFrom(minimumSize: Size(200, 50),margin: EdgeInsets.symmetric(vertical: 10),),);}
}
4. 动画与高级控件示例
class AnimationDemo extends StatefulWidget { _AnimationDemoState createState() => _AnimationDemoState();
}class _AnimationDemoState extends State<AnimationDemo>with SingleTickerProviderStateMixin {late AnimationController _controller;late Animation<double> _sizeAnimation;late Animation<Color?> _colorAnimation;bool _isExpanded = false;bool _isLoading = false;void initState() {super.initState();_controller = AnimationController(vsync: this,duration: Duration(milliseconds: 500),);_sizeAnimation = Tween<double>(begin: 100, end: 200).animate(CurvedAnimation(parent: _controller, curve: Curves.easeInOut),);_colorAnimation = ColorTween(begin: Colors.blue,end: Colors.purple,).animate(_controller);}void _toggleSize() {setState(() {_isExpanded = !_isExpanded;if (_isExpanded) {_controller.forward();} else {_controller.reverse();}});}void _simulateLoad() {setState(() {_isLoading = true;});Future.delayed(Duration(seconds: 2), () {setState(() {_isLoading = false;});});} Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text('动画示例')),body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: [// 隐式动画AnimatedContainer(duration: Duration(milliseconds: 300),width: _isExpanded ? 300 : 150,height: _isExpanded ? 300 : 150,decoration: BoxDecoration(color: Colors.blue,borderRadius: BorderRadius.circular(_isExpanded ? 30 : 10),),child: Icon(Icons.star, color: Colors.white, size: 50),),SizedBox(height: 30),// 显式动画AnimatedBuilder(animation: _controller,builder: (context, child) {return Container(width: _sizeAnimation.value,height: _sizeAnimation.value,color: _colorAnimation.value,child: Icon(Icons.favorite, color: Colors.white, size: 40),);},),SizedBox(height: 30),// 切换按钮ElevatedButton(onPressed: _toggleSize,child: Text(_isExpanded ? '缩小' : '放大'),),SizedBox(height: 50),// 加载状态if (_isLoading)CircularProgressIndicator()elseText('数据加载完成'),ElevatedButton(onPressed: _simulateLoad,child: Text('加载数据'),),SizedBox(height: 30),// Hero动画Hero(tag: 'hero-icon',child: Icon(Icons.rocket, size: 60, color: Colors.red),),ElevatedButton(onPressed: () {Navigator.push(context,MaterialPageRoute(builder: (context) => HeroDetailScreen(),),);},child: Text('查看详情'),),],),),);}void dispose() {_controller.dispose();super.dispose();}
}class HeroDetailScreen extends StatelessWidget { Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text('详情页')),body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: [Hero(tag: 'hero-icon',child: Icon(Icons.rocket, size: 120, color: Colors.red),),SizedBox(height: 30),Text('Hero动画示例', style: TextStyle(fontSize: 24)),],),),);}
}
5. 完整应用结构示例
void main() => runApp(MyApp());class MyApp extends StatelessWidget { Widget build(BuildContext context) {return MaterialApp(title: 'Flutter 综合示例',theme: ThemeData(primarySwatch: Colors.blue,visualDensity: VisualDensity.adaptivePlatformDensity,),home: MainScreen(),debugShowCheckedModeBanner: false,);}
}class MainScreen extends StatefulWidget { _MainScreenState createState() => _MainScreenState();
}class _MainScreenState extends State<MainScreen> {int _currentIndex = 0;final List<Widget> _screens = [HomeTab(),SearchTab(),ProfileTab(),]; Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text('Flutter 控件大全'),actions: [IconButton(icon: Icon(Icons.notifications), onPressed: () {}),IconButton(icon: Icon(Icons.settings), onPressed: () {}),],),drawer: Drawer(child: ListView(children: [DrawerHeader(decoration: BoxDecoration(color: Colors.blue),child: Text('导航菜单', style: TextStyle(color: Colors.white, fontSize: 24)),),ListTile(leading: Icon(Icons.home),title: Text('首页'),onTap: () => _selectTab(0),),ListTile(leading: Icon(Icons.search),title: Text('搜索'),onTap: () => _selectTab(1),),ListTile(leading: Icon(Icons.person),title: Text('个人资料'),onTap: () => _selectTab(2),),],),),body: IndexedStack(index: _currentIndex,children: _screens,),bottomNavigationBar: BottomNavigationBar(currentIndex: _currentIndex,onTap: (index) => _selectTab(index),items: [BottomNavigationBarItem(icon: Icon(Icons.home),label: '首页',),BottomNavigationBarItem(icon: Icon(Icons.search),label: '搜索',),BottomNavigationBarItem(icon: Icon(Icons.person),label: '个人',),],),floatingActionButton: FloatingActionButton(onPressed: () {},child: Icon(Icons.add),tooltip: '添加内容',),);}void _selectTab(int index) {setState(() {_currentIndex = index;});Navigator.pop(context); // 关闭抽屉}
}class HomeTab extends StatelessWidget { Widget build(BuildContext context) {return ListView(children: [_buildCard('布局控件', Icons.grid_on),_buildCard('交互控件', Icons.touch_app),_buildCard('动画示例', Icons.animation),_buildCard('导航路由', Icons.navigation),_buildCard('状态管理', Icons.storage),],);}Widget _buildCard(String title, IconData icon) {return Card(margin: EdgeInsets.all(12),elevation: 4,child: ListTile(leading: Icon(icon, size: 40, color: Colors.blue),title: Text(title, style: TextStyle(fontSize: 20)),trailing: Icon(Icons.arrow_forward),onTap: () {},),);}
}// 其他Tab的实现类似,省略...
这些完整示例展示了:
- 各种布局控件的组合使用
- 状态管理的完整流程
- 多种导航方式的实现
- 显式/隐式动画的应用
- 实际应用的标准结构
- 复杂交互的实现方法
建议从基础示例开始,逐步组合和扩展功能。实际开发中,可以根据需求将这些示例拆分为多个小部件,并使用状态管理方案(如Provider)来管理跨组件的状态。
学习资源
- Flutter Widget 目录(官方文档)
- Flutter Gallery(示例集合)
- pub.dev(第三方控件库)
掌握这些控件后,可组合出 99% 的常见 UI 效果。建议从基础布局入手,逐步实践状态管理和动画,再深入自定义绘制。