Flutter中的组件 : OpenContainer
OpenContainer
是 Flutter Material 组件库中一个强大的 容器过渡动画组件,专门用于实现 从一个小容器(如卡片)平滑展开到全屏页面,再收缩返回 的视觉效果。它通过动画将两个不同尺寸的 UI 状态无缝连接,常用于创建符合 Material Design 规范的交互场景(如点击卡片跳转详情页)。
animations包中的组件。
OpenContainer({
Key? key,
Color closedColor = Colors.white,
Color openColor = Colors.white,
Color? middleColor,
double closedElevation = 1.0,
double openElevation = 4.0,
ShapeBorder closedShape = const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(4.0))),
ShapeBorder openShape = const RoundedRectangleBorder(),
void Function(Object?)? onClosed,
required Widget Function(BuildContext, void Function()) closedBuilder,
required Widget Function(BuildContext, void Function({Object? returnValue})) openBuilder,
bool tappable = true,
Duration transitionDuration = const Duration(milliseconds: 300),
ContainerTransitionType transitionType = ContainerTransitionType.fade,
bool useRootNavigator = false,
RouteSettings? routeSettings,
Clip clipBehavior = Clip.antiAlias,
})
| 属性 | 类型 | 默认值 | 作用 |
|---|---|---|---|
closedColor | Color | Colors.white | 闭合状态(小容器)的背景色 |
openColor | Color | Colors.white | 展开状态(全屏)的背景色 |
middleColor | Color? | null | 过渡动画中间的背景色(可选) |
closedShape | ShapeBorder | 圆角矩形 | 闭合时的形状(如圆角卡片) |
openShape | ShapeBorder | 矩形 | 展开时的形状(通常全屏无圆角) |
closedElevation | double | 1.0 | 闭合状态的阴影深度(类似卡片阴影) |
openElevation | double | 4.0 | 展开状态的阴影深度 |
closedBuilder | Widget Function(BuildContext, void Function()) | ✅ | 构建闭合状态的UI,参数含触发展开的回调(如按钮点击调用它) |
openBuilder | Widget Function(BuildContext, void Function({Object? returnValue})) | ✅ | 构建展开全屏的UI,参数含关闭回调(可带返回值) |
tappable | bool | true | 是否允许点击闭合容器触发展开 |
onClosed | Function(Object?) | null | 关闭动画完成后的回调(接收openBuilder返回的值) |
transitionDuration | Duration | 300ms | 动画持续时间 |
transitionType | ContainerTransitionType | fade | 动画类型: • fade(淡入淡出+缩放) • fadeThrough(交叉淡入淡出) |
clipBehavior | Clip | Clip.antiAlias | 内容裁剪方式(抗锯齿) |
useRootNavigator | bool | false | 是否使用根导航器(处理深层导航栈时有用) |
routeSettings | RouteSettings? | null | 自定义路由设置(如命名路由参数) |
实际用法
///绘制tiem
_renderItem(e) {
ReposViewModel reposViewModel = ReposViewModel.fromTrendMap(e);
return OpenContainer(
closedColor: Colors.transparent,
closedElevation: 0,
transitionType: ContainerTransitionType.fade,
openBuilder: (BuildContext context, VoidCallback _) {
// 测试
print("就是这里实现的,啦啦啦");
return NavigatorUtils.pageContainer(
RepositoryDetailPage(
reposViewModel.ownerName!, reposViewModel.repositoryName!),
context);
},
tappable: true,
closedBuilder: (BuildContext _, VoidCallback openContainer) {
return ReposItem(reposViewModel, onPressed: null);
},
);
}
效果
项目应用实例:
OpenContainer(
closedColor: Colors.transparent,
openColor: Colors.transparent,
closedElevation: 0,
closedShape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(0)),
),
openElevation: 0,
transitionDuration: const Duration(milliseconds: 300),
closedBuilder: (context, action) {
return GestureDetector(
onTap: action,
child: Container(
alignment: Alignment.center,
width: ScreenAdapter.width(144),
height: ScreenAdapter.height(35),
decoration: BoxDecoration(
border: Border.all(
color: const Color.fromRGBO(0, 0, 0, 1),
width: ScreenAdapter.width(1),
),
borderRadius: BorderRadius.circular(ScreenAdapter.radius(55)),
color: Colors.transparent,
),
child: Text(
"编辑个人资料",
textAlign: TextAlign.center,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: ScreenAdapter.fontSize(14),
color: const Color.fromRGBO(0, 0, 0, 1),
),
),
),
);
},
openBuilder: (context, action) {
Get.put(EditProfileController());
return EditProfileView();
},
),