关于 flutter-master-detail-view
用于在 Flutter 应用中并排展示列表及选中内容的组件模式。它会适应可用空间,在较宽屏幕上使用多列布局,在移动设备上切换到详情页。
主要功能
- 01自适应主从布局
- 02列表与详情构建器
- 03嵌套式响应布局
适用场景
- 01在平板或桌面端展示列表和选中项
- 02在移动设备上打开条目详情
- 03为多层数据嵌套列表详情视图
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ rodydavis/ skills --skill flutter-master-detail-view安装后在 Claude Code 中输入/flutter-master-detail-view确认已加载。
详细介绍
Flutter 主从视图
使用 Flutter 构建移动端、桌面端和 Web 应用时,你经常需要考虑如何处理列表及其选中后的内容。根据数据的不同,你可能需要先显示另一个列表,然后才能打开详情视图。在平板电脑或桌面端,可以通过多列布局实现这一点。
在移动端,由于空间有限,你仍然需要跳转到详情屏幕。
如何使用 Flutter 构建主从视图:
import 'package:flutter/material.dart';
class MasterDetail<T> extends StatefulWidget {
const MasterDetail({
Key? key,
required this.listBuilder,
required this.detailBuilder,
required this.onPush,
this.emptyBuilder,
}) : super(key: key);
final Widget Function(BuildContext, ValueChanged<T?>, T?) listBuilder;
final Widget Function(BuildContext, T, bool) detailBuilder;
final void Function(BuildContext, T) onPush;
final WidgetBuilder? emptyBuilder;
@override
State<MasterDetail<T>> createState() => _MasterDetailState<T>();
}
class _MasterDetailState<T> extends State<MasterDetail<T>> {
final selected = ValueNotifier<T?>(null);
double? detailsWidth;
@override
Widget build(BuildContext context) {
return Scaffold(
primary: false,
body: LayoutBuilder(
builder: (context, dimens) {
const double minWidth = 350;
final maxWidth = dimens.maxWidth - minWidth;
if (detailsWidth != null) {
if (detailsWidth! > maxWidth) {
detailsWidth = maxWidth;
}
if (detailsWidth! < minWidth) {
detailsWidth = minWidth;
}
}
return ValueListenableBuilder<T?>(
valueListenable: selected,
builder: (context, item, child) {
final canShowDetails = dimens.maxWidth > 800;
final showDetails = item != null && canShowDetails;
return Row(
children: [
Expanded(
child: widget.listBuilder(context, (item) {
if (canShowDetails) {
selected.value = item;
} else {
selected.value = null;
if (item != null) widget.onPush(context, item);
}
}, selected.value),
),
if (canShowDetails)
MouseRegion(
cursor: SystemMouseCursors.resizeLeftRight,
child: GestureDetector(
behavior: HitTestBehavior.opaque,
onHorizontalDragUpdate: (details) {
if (mounted) {
setState(() {
double w = detailsWidth ?? maxWidth;
w -= details.delta.dx;
// Check for min width
if (w < minWidth) {
w = minWidth;
}
// Check for max width
if (w > maxWidth) {
w = maxWidth;
}
detailsWidth = w;
});
}
},
child: const SizedBox(
width: 5,
height: double.infinity,
child: VerticalDivider(),
),
),
),
if (canShowDetails)
SizedBox(
width: detailsWidth ?? maxWidth,
height: double.infinity,
child: showDetails
? widget.detailBuilder(context, item, false)
: widget.emptyBuilder?.call(context) ??
const Center(
child: Text('Select a item to view details'),
),
),
],
);
},
);
},
),
);
}
}
这个组件会在布局完成后调整自身尺寸,并尽可能缩小列表,将剩余空间留给详情。这一点对于之后嵌套多个此类组件、创建可逐步适配的布局非常重要。
评论
支持 Markdown