Flutter的Widget世界

Flutter 常用 Widget 分类速查表

按图中脉络,将核心组件分为 6 大类,并补充每类典型用途与要点。

分类 常见 Widget 典型作用 / 备注
布局 Widget (Layout) 单子元素布局 ContainerCenterAlignFractionallySizedBoxSizedBoxFittedBoxConstrainedBoxOverflowBoxAspectRatioOffstage 控制 单个子组件 的尺寸、位置或可见性。 Container = 装饰 + 约束 + 边距的一站式方案;Offstage 用于临时隐藏但保留状态。
多子元素布局 RowColumnStackIndexedStackFlowTableWrapListBody 负责 多个子组件 排版。 Row/Column 线性排列;Stack 层叠定位;Wrap/Flow 流式换行;Table 网格;IndexedStack 仅显示指定索引子项。
可滚动 Widget ListView, GridView, NestedScrollView, CustomScrollView 内建滚动能力。NestedScrollView 适合协同滚动 AppBar;CustomScrollView 能组合多个 Sliver 实现复杂滚动效果。
绘制 & 效果 Widget Opacity, Transform, DecoratedBox, FractionalTranslation, RotatedBox, ClipOval, ClipPath, ClipRect, CustomPaint, BackdropFilter 图形变换、裁剪、透明度、装饰与自绘。CustomPaint 可绘制任意图形;BackdropFilter 做毛玻璃等高斯模糊。
图片与资源 Widget Image, Icon, RawImage, (资源加载辅助:AssetBundle) 加载位图或矢量资源。RawImage 直接显示 ui.ImageAssetBundle 为多平台统一的资源检索接口。
文本 Widget Text, RichText 渲染普通文本或富文本;RichText 支持多样式 TextSpan 嵌套。
样式 Widget Padding, Theme, MediaQuery 提供边距、全局主题与环境信息(屏幕尺寸、文字缩放、暗色模式)。
  1. 尺寸与约束不满足时,优先考虑 SizedBox / ConstrainedBox
  2. 复杂滚动场景优先研究 Sliver 系列CustomScrollView
  3. 动态裁剪或特效可组合 ClipPath + BackdropFilter
  4. 跨页面共享配色/字体,统一写在 ThemeData,并用 Theme.of(context) 读取。

StatelessWidget与StatefulWidget

StatelessWidget 与 StatefulWidget 全面对比

维度 StatelessWidget StatefulWidget
核心定义 无可变状态 。构建后只能依赖 build() 里传入的 外部参数 (构造函数、InheritedWidgetProvider 等)来决定外观。 拥有可变状态 。通过内部 State 对象保存数据,调用 setState() 后可触发重新构建自身及其子树。
典型场景 - 纯展示组件 - Button、Icon、Logo 等简单静态 UI - 只依赖父级传值、不需自行更新 - 表单输入、计时器、动画、Tab 切换 - 网络请求完成后刷新页面 - 需要局部记忆 / 交互的组件
生命周期 ```dart
Widget build(BuildContext context)
``` 只有一次 build,依赖更新 ⇒ 整棵 Widget 重新创建。 常用回调: initState()didChangeDependencies()build()setState()dispose()
更新机制 父级的 setState()InheritedWidget 改变后,Flutter 框架会销毁旧实例,创建新实例执行 build() 调用自身 setState(fn) ⇒ 仅当前 StatefulWidget 重新 build(),子树中未变化的内容利用 Element 树 Diff 被高效复用。
性能 占用内存少、构建开销低;如果 UI 真正静态,更利于框架优化。 略高,但局部刷新的粒度更细,避免整页重绘。正确拆分可获得更佳整体性能。
转换 业务增长需本地状态 → 可 快捷替换 : 1. 用 IDE 将类继承改为 StatefulWidget 2. 自动生成 State,再挪动原 build() 状态已不再需要 ⇒ 把业务状态上提或放入 Provider/Riverpod/BLoC,然后改为 StatelessWidget,使组件更轻量。
易错点 - 不支持 setState();如直接调用会报错。 - 忘记 dispose() 释放资源(AnimationControllerStreamTimer)。 - 在 build() 里创建 Future/Stream 导致反复执行;应缓存。

1. 快速示例对比

StatelessWidget

dart 复制代码
class HelloText extends StatelessWidget {
  final String name;
  const HelloText({required this.name, super.key});

  @override
  Widget build(BuildContext context) {
    return Text('Hello, $name');
  }
}

StatefulWidget

dart 复制代码
class CounterBtn extends StatefulWidget {
  const CounterBtn({super.key});

  @override
  State<CounterBtn> createState() => _CounterBtnState();
}

class _CounterBtnState extends State<CounterBtn> {
  int _count = 0;

  void _inc() => setState(() => _count++);

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: _inc,
      child: Text('Clicked $_count'),
    );
  }
}

2. 何时选谁?

  • 完全静态或仅依赖外部数据Stateless

  • 需在组件内用 setState() 更新Stateful

  • 状态要跨组件 / 全局共享 → 把状态上提或使用状态管理,再让 UI 尽量保持 Stateless


3. 状态拆分的小技巧

  1. 最小重绘原则
    把仅因点击计数变化的部分包成 StatefulWidget,周围稳定区域仍用 StatelessWidget,减少重建。
  2. AutomaticKeepAliveClientMixin
    滑动页签 PageView/TabBarView 中要保持页面状态,可在 State 里混入并重写 wantKeepAlive => true;
  3. Keys
    当控件类型相同但需要唯一身份(动画切换、列表重排)时,使用 ValueKey/ObjectKey/UniqueKey 保持状态不丢失。

4. 小结

  • StatelessWidget:纯展示、所有数据都从外部流入。
  • StatefulWidget :自己的状态自己管,setState() 后局部刷新。
  • 合理拆分与状态上提可以兼顾 可维护性性能
  • 如果组件既要管理内部细节,又要暴露事件给外部,推荐"内部 Stateful + 对外 Stateless API"的封装方式,提高复用度。

Android开发者如何快速上手Flutter布局开发

1. LinearLayout 在 Flutter 中等价于什么?

Android Flutter 说明
LinearLayout (horizontal / vertical) Row (横向) Column(纵向) Row / Column 只负责子组件线性排列 ,额外尺寸/权重需要 ExpandedFlexibleSpacer 等配合。
dart 复制代码
Column(
  mainAxisAlignment: MainAxisAlignment.center,
  children: [
    Text('A'),
    Text('B'),
  ],
)

2. RelativeLayout 在 Flutter 中等价于什么?

Android Flutter 用途
RelativeLayout Stack + Positioned / Align Stack 允许子组件"层叠"摆放;通过 Positioned(绝对偏移)或 Align(相对父尺寸)来模拟 RelativeLayout 效果。
dart 复制代码
Stack(
  children: [
    Container(color: Colors.blue),              // 底层
    Positioned(top: 8, right: 8, child: Icon(Icons.close)),
  ],
)

3. 如何使用 Widget 定义布局属性?

在 Flutter 中,"布局 + 样式"都是由 一层层 Widget 组合实现,而非 XML。常见属性对应的 Widget/参数:

功能 Widget / 参数示例
边距、内边距 Padding(padding: EdgeInsets.all(8))
大小约束 SizedBox(width: 100, height: 50) / ConstrainedBox
对齐 Align(alignment: Alignment.centerRight)
权重(填充剩余) Expanded(child: ...)Flexible(flex: 2, child: ...)
背景装饰 Container(decoration: BoxDecoration(color: Colors.red))

4. 如何分层布局?

  • 透明层叠Stack
  • 滚动内部再分层CustomScrollView + 各种 Sliver
  • 浮动/悬浮元素Stack + Positioned 放在屏幕顶层,或使用 ScaffoldfloatingActionButtonDrawerBottomSheet 等 slot。

5. 如何设置布局样式?

  • 颜色 / 圆角 / 阴影Container → BoxDecoration
  • 字体 / 主题ThemeData + TextStyle
  • 动画样式AnimatedContainer, AnimatedPositioned, Hero
  • 适配暗黑模式 → 读取 Theme.of(context).brightnessMediaQuery.platformBrightnessOf(context)
dart 复制代码
Container(
  padding: const EdgeInsets.all(12),
  decoration: BoxDecoration(
    color: Colors.white,
    borderRadius: BorderRadius.circular(16),
    boxShadow: [BoxShadow(blurRadius: 4, color: Colors.black26)],
  ),
  child: const Text('样式示例'),
)

6. ScrollView 在 Flutter 中等价于什么?

Android Flutter 备注
ScrollView / NestedScrollView SingleChildScrollView (单子组件) CustomScrollView(多 Sliver 组合滚动) 若仅需包一段静态内容,用 SingleChildScrollView;复杂协同滚动(如 AppBar 吸顶)用 NestedScrollViewCustomScrollView + Slivers。

7. 谁是 Flutter 的列表组件?

  • ListView:最常用

    • ListView(children: [...]) 静态少量
    • ListView.builder(itemCount: n, itemBuilder: ...) 懒加载
    • ListView.separated(...) 带分割线
  • GridView:网格

  • ListView.custom / SliverList:高度自定义

  • ReorderableListView:可拖拽排序

  • AnimatedList:插入/删除动画


8. 如何知道点击了列表中哪个 item?

dart 复制代码
ListView.builder(
  itemCount: items.length,
  itemBuilder: (context, index) {
    return ListTile(
      title: Text(items[index]),
      onTap: () {
        print('点击了第 $index 个:${items[index]}');
      },
    );
  },
)
  • 可替换 ListTileGestureDetector, InkWell 等,自由处理 onTap

9. 如何动态更新 ListView?

  1. StatefulWidget + setState

    dart 复制代码
    setState(() {
      items.add('新元素');
    });
  2. 更平滑的插入/删除动画 → 用 AnimatedList

  3. 大规模异步数据 → 结合 StreamBuilder / FutureBuilder 或状态管理(Provider、Riverpod、Bloc 等)

  4. 局部刷新 → 使用 ValueNotifier<List<T>> + ValueListenableBuilder 或者 ListView.builder 本身的懒加载特性。


🌟 小结

  • 线性布局Row / Column
  • 相对 / 层叠布局Stack + Positioned | Align
  • 滚动SingleChildScrollViewListViewCustomScrollView
  • 列表ListView.builder 最普遍;AnimatedListReorderableListView 提供更高阶交互
  • 点击 & 动态更新InkWell/GestureDetector + setState(),或选择更合适的状态管理/动画组件
Android 组件 / 布局 Flutter 对应 Widget 备注与补充
LinearLayout (vertical / horizontal) Column / Row 线性排列;用 Expanded / Flexible 实现权重,Spacer 占位
RelativeLayout / FrameLayout Stack + Positioned / Align 层叠摆放、支持绝对或相对父布局定位
ConstraintLayout Stack + 约束插件(flutter_layout_grid / flutter_constraintlayout) 或直接拆分为多层 Row / Column / Expanded 官方无完全等价物,复杂场景可引入第三方
ScrollView SingleChildScrollView 仅能包裹单个子组件(可再套 Column 等)
NestedScrollView NestedScrollView(Flutter 同名) 或 CustomScrollView + SliverAppBar/SliverList 协同滚动吸顶效果
ListView (Adapter) ListView.builder 懒加载;itemBuilder 相当于 Adapter
RecyclerView + DiffUtil ListView.builder + AnimatedList / 第三方 flutter_staggered_grid_view 默认已复用 item,无需 ViewHolder;动画用 AnimatedList
GridView GridView.count / GridView.builder crossAxisCountSliverGridDelegate 控制列数与间距
ViewPager / ViewPager2 PageView 支持横纵向、无限轮播(配合 PageController)
TabLayout + ViewPager TabBar + TabBarView TabController 关联
DrawerLayout Scaffold.drawer / Scaffold.endDrawer 自动处理滑动抽屉
Toolbar / AppBar AppBarScaffold.appBar 内建返回按钮、菜单
FloatingActionButton FloatingActionButton(同名) 放在 Scaffold.floatingActionButton
CardView Card 带圆角与阴影
Snackbar SnackBar ScaffoldMessenger.of(context).showSnackBar()
AlertDialog AlertDialog showDialog(context: ...)
Switch (SwitchCompat) Switch / SwitchListTile
CheckBox / RadioButton Checkbox / Radio (RadioListTile)
EditText TextField / TextFormField 输入装饰用 InputDecoration
ProgressBar CircularProgressIndicator / LinearProgressIndicator
相关推荐
一斤代码5 小时前
vue3 下载图片(标签内容可转图)
前端·javascript·vue
中微子5 小时前
React Router 源码深度剖析解决面试中的深层次问题
前端·react.js
光影少年5 小时前
从前端转go开发的学习路线
前端·学习·golang
中微子6 小时前
React Router 面试指南:从基础到实战
前端·react.js·前端框架
3Katrina6 小时前
深入理解 useLayoutEffect:解决 UI "闪烁"问题的利器
前端·javascript·面试
前端_学习之路7 小时前
React--Fiber 架构
前端·react.js·架构
伍哥的传说7 小时前
React 实现五子棋人机对战小游戏
前端·javascript·react.js·前端框架·node.js·ecmascript·js
qq_424409197 小时前
uniapp的app项目,某个页面长时间无操作,返回首页
前端·vue.js·uni-app
我在北京coding7 小时前
element el-table渲染二维对象数组
前端·javascript·vue.js
布兰妮甜7 小时前
Vue+ElementUI聊天室开发指南
前端·javascript·vue.js·elementui