Flutter Widgets 完全指南引言Widgets 是 Flutter 的核心构建块。本文将深入探讨各种常用 Widget 的用法和高级技巧。基础概念回顾Widget 类型StatelessWidget: 无状态组件StatefulWidget: 有状态组件InheritedWidget: 数据共享组件RenderObjectWidget: 渲染组件Widget 树MaterialApp( home: Scaffold( appBar: AppBar(title: Text(Hello)), body: Center(child: Text(World)), ), )高级技巧一布局 WidgetContainerContainer( width: 200, height: 200, padding: const EdgeInsets.all(16), margin: const EdgeInsets.all(8), decoration: BoxDecoration( color: Colors.blue, borderRadius: BorderRadius.circular(12), boxShadow: const [BoxShadow(color: Colors.black12, blurRadius: 4)], ), child: const Text(Container), )Row 和 ColumnRow( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: const [ Text(Item 1), SizedBox(width: 16), Text(Item 2), SizedBox(width: 16), Text(Item 3), ], ) Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: const [ Text(Top), Text(Middle), Text(Bottom), ], )StackStack( alignment: Alignment.center, children: [ Container(width: 200, height: 200, color: Colors.blue), const Positioned( top: 10, left: 10, child: Text(Top Left), ), const Positioned( bottom: 10, right: 10, child: Text(Bottom Right), ), ], )高级技巧二滚动 WidgetListViewListView( padding: const EdgeInsets.all(16), children: const [ ListTile(title: Text(Item 1)), ListTile(title: Text(Item 2)), ListTile(title: Text(Item 3)), ], ) ListView.builder( itemCount: 100, itemBuilder: (context, index) { return ListTile(title: Text(Item $index)); }, )GridViewGridView.count( crossAxisCount: 3, crossAxisSpacing: 8, mainAxisSpacing: 8, children: List.generate(9, (index) { return Container(color: Colors.blue, child: Center(child: Text($index))); }), ) GridView.builder( gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, ), itemCount: 20, itemBuilder: (context, index) { return Card(child: Center(child: Text(Card $index))); }, )CustomScrollViewCustomScrollView( slivers: [ const SliverAppBar( title: Text(Sliver App Bar), floating: true, expandedHeight: 200, flexibleSpace: FlexibleSpaceBar( background: Image.network(https://picsum.photos/200), ), ), SliverList( delegate: SliverChildBuilderDelegate( (context, index) ListTile(title: Text(Item $index)), childCount: 50, ), ), ], )高级技巧三交互 WidgetGestureDetectorGestureDetector( onTap: () print(Tapped), onDoubleTap: () print(Double tapped), onLongPress: () print(Long pressed), onHorizontalDragEnd: (details) { if (details.primaryVelocity! 0) { print(Swiped right); } else { print(Swiped left); } }, child: Container( width: 200, height: 200, color: Colors.blue, child: const Center(child: Text(Tap me)), ), )InkWellInkWell( onTap: () print(Tapped), splashColor: Colors.red, borderRadius: BorderRadius.circular(8), child: Container( padding: const EdgeInsets.all(16), child: const Text(InkWell), ), )DismissibleDismissible( key: const Key(item), direction: DismissDirection.endToStart, background: Container( color: Colors.red, alignment: Alignment.centerRight, padding: const EdgeInsets.only(right: 16), child: const Icon(Icons.delete), ), onDismissed: (direction) print(Dismissed), child: const ListTile(title: Text(Swipe to delete)), )高级技巧四状态管理 WidgetProviderclass CounterProvider extends ChangeNotifier { int _count 0; int get count _count; void increment() { _count; notifyListeners(); } } void main() { runApp( ChangeNotifierProvider( create: (_) CounterProvider(), child: const MyApp(), ), ); } ConsumerCounterProvider( builder: (context, provider, child) { return Text(Count: ${provider.count}); }, )FutureBuilderFutureBuilderString( future: fetchData(), builder: (context, snapshot) { if (snapshot.connectionState ConnectionState.waiting) { return const CircularProgressIndicator(); } if (snapshot.hasError) { return Text(Error: ${snapshot.error}); } return Text(Data: ${snapshot.data}); }, )StreamBuilderStreamBuilderint( stream: countStream(), initialData: 0, builder: (context, snapshot) { return Text(Count: ${snapshot.data}); }, )实战案例自定义 Widgetclass CustomButton extends StatelessWidget { final String text; final VoidCallback onPressed; final Color color; const CustomButton({ super.key, required this.text, required this.onPressed, this.color Colors.blue, }); override Widget build(BuildContext context) { return ElevatedButton( onPressed: onPressed, style: ElevatedButton.styleFrom( backgroundColor: color, padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ), ), child: Text(text, style: const TextStyle(fontSize: 16)), ); } } // 使用 const CustomButton( text: Click me, onPressed: _handleClick, color: Colors.green, )实战案例可折叠面板class ExpandablePanel extends StatefulWidget { final String title; final Widget content; const ExpandablePanel({ super.key, required this.title, required this.content, }); override StateExpandablePanel createState() _ExpandablePanelState(); } class _ExpandablePanelState extends StateExpandablePanel { bool _isExpanded false; override Widget build(BuildContext context) { return Column( children: [ ListTile( title: Text(widget.title), trailing: Icon( _isExpanded ? Icons.expand_less : Icons.expand_more, ), onTap: () setState(() _isExpanded !_isExpanded), ), AnimatedSize( duration: const Duration(milliseconds: 300), child: _isExpanded ? widget.content : const SizedBox.shrink(), ), ], ); } }实战案例搜索框class SearchBox extends StatefulWidget { const SearchBox({super.key}); override StateSearchBox createState() _SearchBoxState(); } class _SearchBoxState extends StateSearchBox { final TextEditingController _controller TextEditingController(); bool _isFocused false; override void dispose() { _controller.dispose(); super.dispose(); } override Widget build(BuildContext context) { return Container( decoration: BoxDecoration( color: Colors.grey[100], borderRadius: BorderRadius.circular(24), border: Border.all( color: _isFocused ? Colors.blue : Colors.transparent, width: 2, ), ), child: TextField( controller: _controller, decoration: InputDecoration( hintText: Search..., prefixIcon: const Icon(Icons.search), suffixIcon: IconButton( icon: const Icon(Icons.clear), onPressed: _controller.clear, ), border: InputBorder.none, contentPadding: const EdgeInsets.all(12), ), onChanged: (value) print(Search: $value), onTap: () setState(() _isFocused true), onEditingComplete: () setState(() _isFocused false), ), ); } }常见问题与解决方案Q1Widget 不更新A确保使用 StatefulWidget 和 setStateclass MyWidget extends StatefulWidget { override StateMyWidget createState() _MyWidgetState(); } class _MyWidgetState extends StateMyWidget { int _count 0; void _increment() { setState(() _count); } }Q2布局溢出A使用 Expanded 或 FlexibleRow( children: [ Expanded(child: Text(Long text that should wrap)), ], )Q3性能问题A使用 const 构造函数和 keysconst Text(Static text);最佳实践1. 使用 const 构造函数const Text(Hello); const SizedBox(width: 16);2. 提取 WidgetWidget _buildHeader() { return const AppBar(title: Text(Header)); }3. 使用 keysListView.builder( itemBuilder: (context, index) { return ListTile(key: Key(item-$index), title: Text(Item $index)); }, )总结Flutter Widgets 是构建应用的基础。通过本文的学习你应该能够使用布局 Widget使用滚动 Widget使用交互 Widget使用状态管理 Widget创建自定义 Widget实现可折叠面板掌握这些技巧能够帮助你构建更加美观和功能丰富的应用。
Flutter Widgets 完全指南
发布时间:2026/5/17 10:49:19
Flutter Widgets 完全指南引言Widgets 是 Flutter 的核心构建块。本文将深入探讨各种常用 Widget 的用法和高级技巧。基础概念回顾Widget 类型StatelessWidget: 无状态组件StatefulWidget: 有状态组件InheritedWidget: 数据共享组件RenderObjectWidget: 渲染组件Widget 树MaterialApp( home: Scaffold( appBar: AppBar(title: Text(Hello)), body: Center(child: Text(World)), ), )高级技巧一布局 WidgetContainerContainer( width: 200, height: 200, padding: const EdgeInsets.all(16), margin: const EdgeInsets.all(8), decoration: BoxDecoration( color: Colors.blue, borderRadius: BorderRadius.circular(12), boxShadow: const [BoxShadow(color: Colors.black12, blurRadius: 4)], ), child: const Text(Container), )Row 和 ColumnRow( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: const [ Text(Item 1), SizedBox(width: 16), Text(Item 2), SizedBox(width: 16), Text(Item 3), ], ) Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: const [ Text(Top), Text(Middle), Text(Bottom), ], )StackStack( alignment: Alignment.center, children: [ Container(width: 200, height: 200, color: Colors.blue), const Positioned( top: 10, left: 10, child: Text(Top Left), ), const Positioned( bottom: 10, right: 10, child: Text(Bottom Right), ), ], )高级技巧二滚动 WidgetListViewListView( padding: const EdgeInsets.all(16), children: const [ ListTile(title: Text(Item 1)), ListTile(title: Text(Item 2)), ListTile(title: Text(Item 3)), ], ) ListView.builder( itemCount: 100, itemBuilder: (context, index) { return ListTile(title: Text(Item $index)); }, )GridViewGridView.count( crossAxisCount: 3, crossAxisSpacing: 8, mainAxisSpacing: 8, children: List.generate(9, (index) { return Container(color: Colors.blue, child: Center(child: Text($index))); }), ) GridView.builder( gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, ), itemCount: 20, itemBuilder: (context, index) { return Card(child: Center(child: Text(Card $index))); }, )CustomScrollViewCustomScrollView( slivers: [ const SliverAppBar( title: Text(Sliver App Bar), floating: true, expandedHeight: 200, flexibleSpace: FlexibleSpaceBar( background: Image.network(https://picsum.photos/200), ), ), SliverList( delegate: SliverChildBuilderDelegate( (context, index) ListTile(title: Text(Item $index)), childCount: 50, ), ), ], )高级技巧三交互 WidgetGestureDetectorGestureDetector( onTap: () print(Tapped), onDoubleTap: () print(Double tapped), onLongPress: () print(Long pressed), onHorizontalDragEnd: (details) { if (details.primaryVelocity! 0) { print(Swiped right); } else { print(Swiped left); } }, child: Container( width: 200, height: 200, color: Colors.blue, child: const Center(child: Text(Tap me)), ), )InkWellInkWell( onTap: () print(Tapped), splashColor: Colors.red, borderRadius: BorderRadius.circular(8), child: Container( padding: const EdgeInsets.all(16), child: const Text(InkWell), ), )DismissibleDismissible( key: const Key(item), direction: DismissDirection.endToStart, background: Container( color: Colors.red, alignment: Alignment.centerRight, padding: const EdgeInsets.only(right: 16), child: const Icon(Icons.delete), ), onDismissed: (direction) print(Dismissed), child: const ListTile(title: Text(Swipe to delete)), )高级技巧四状态管理 WidgetProviderclass CounterProvider extends ChangeNotifier { int _count 0; int get count _count; void increment() { _count; notifyListeners(); } } void main() { runApp( ChangeNotifierProvider( create: (_) CounterProvider(), child: const MyApp(), ), ); } ConsumerCounterProvider( builder: (context, provider, child) { return Text(Count: ${provider.count}); }, )FutureBuilderFutureBuilderString( future: fetchData(), builder: (context, snapshot) { if (snapshot.connectionState ConnectionState.waiting) { return const CircularProgressIndicator(); } if (snapshot.hasError) { return Text(Error: ${snapshot.error}); } return Text(Data: ${snapshot.data}); }, )StreamBuilderStreamBuilderint( stream: countStream(), initialData: 0, builder: (context, snapshot) { return Text(Count: ${snapshot.data}); }, )实战案例自定义 Widgetclass CustomButton extends StatelessWidget { final String text; final VoidCallback onPressed; final Color color; const CustomButton({ super.key, required this.text, required this.onPressed, this.color Colors.blue, }); override Widget build(BuildContext context) { return ElevatedButton( onPressed: onPressed, style: ElevatedButton.styleFrom( backgroundColor: color, padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ), ), child: Text(text, style: const TextStyle(fontSize: 16)), ); } } // 使用 const CustomButton( text: Click me, onPressed: _handleClick, color: Colors.green, )实战案例可折叠面板class ExpandablePanel extends StatefulWidget { final String title; final Widget content; const ExpandablePanel({ super.key, required this.title, required this.content, }); override StateExpandablePanel createState() _ExpandablePanelState(); } class _ExpandablePanelState extends StateExpandablePanel { bool _isExpanded false; override Widget build(BuildContext context) { return Column( children: [ ListTile( title: Text(widget.title), trailing: Icon( _isExpanded ? Icons.expand_less : Icons.expand_more, ), onTap: () setState(() _isExpanded !_isExpanded), ), AnimatedSize( duration: const Duration(milliseconds: 300), child: _isExpanded ? widget.content : const SizedBox.shrink(), ), ], ); } }实战案例搜索框class SearchBox extends StatefulWidget { const SearchBox({super.key}); override StateSearchBox createState() _SearchBoxState(); } class _SearchBoxState extends StateSearchBox { final TextEditingController _controller TextEditingController(); bool _isFocused false; override void dispose() { _controller.dispose(); super.dispose(); } override Widget build(BuildContext context) { return Container( decoration: BoxDecoration( color: Colors.grey[100], borderRadius: BorderRadius.circular(24), border: Border.all( color: _isFocused ? Colors.blue : Colors.transparent, width: 2, ), ), child: TextField( controller: _controller, decoration: InputDecoration( hintText: Search..., prefixIcon: const Icon(Icons.search), suffixIcon: IconButton( icon: const Icon(Icons.clear), onPressed: _controller.clear, ), border: InputBorder.none, contentPadding: const EdgeInsets.all(12), ), onChanged: (value) print(Search: $value), onTap: () setState(() _isFocused true), onEditingComplete: () setState(() _isFocused false), ), ); } }常见问题与解决方案Q1Widget 不更新A确保使用 StatefulWidget 和 setStateclass MyWidget extends StatefulWidget { override StateMyWidget createState() _MyWidgetState(); } class _MyWidgetState extends StateMyWidget { int _count 0; void _increment() { setState(() _count); } }Q2布局溢出A使用 Expanded 或 FlexibleRow( children: [ Expanded(child: Text(Long text that should wrap)), ], )Q3性能问题A使用 const 构造函数和 keysconst Text(Static text);最佳实践1. 使用 const 构造函数const Text(Hello); const SizedBox(width: 16);2. 提取 WidgetWidget _buildHeader() { return const AppBar(title: Text(Header)); }3. 使用 keysListView.builder( itemBuilder: (context, index) { return ListTile(key: Key(item-$index), title: Text(Item $index)); }, )总结Flutter Widgets 是构建应用的基础。通过本文的学习你应该能够使用布局 Widget使用滚动 Widget使用交互 Widget使用状态管理 Widget创建自定义 Widget实现可折叠面板掌握这些技巧能够帮助你构建更加美观和功能丰富的应用。