我尝试创建一个带有动态项目列表的 PopupMenuButton,如下所示:
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:wideview/view_models/task_control_view_model.dart';
import 'package:wideview/widgets/gap.dart';
class TaskPopupMenuView extends ConsumerWidget {
const TaskPopupMenuView({Key? key}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
final taskControlViewModel = ref.watch(taskControlViewModelProvider);
List<Task>? tasks = taskControlViewModel.tasks;
return PopupMenuButton<Task>(
offset: const Offset(120, 50),
// constraints: const BoxConstraints(
// maxHeight: 500,
// ),
icon: const TaskIcon(),
onSelected: (item) => {
if (item.isSelected)
{
ref.read(taskControlViewModelProvider.notifier).setNoSelectedTask(),
}
else
{
ref
.read(taskControlViewModelProvider.notifier)
.setSelectedTask(item),
}
},
itemBuilder: (context) {
// Build the list of PopupMenuItem dynamically based on tasks
return tasks?.map((Task task) {
return PopupMenuItem<Task>(
value: task,
child: TaskPopupView(task: task),
);
}).toList() ??
[];
},
// itemBuilder: (context) => [
// PopupMenuItem<Task>(
// value: taskControlViewModel.selectedTask,
// child: TaskPopupView(task: taskControlViewModel.selectedTask!)),
// PopupMenuItem<Task>(
// value: taskControlViewModel.selectedTask,
// child: TaskPopupView(task: taskControlViewModel.selectedTask!)),
// PopupMenuItem<Task>(
// value: taskControlViewModel.selectedTask,
// child: TaskPopupView(task: taskControlViewModel.selectedTask!)),
// ],
);
}
}
列表中的每个项目都会显示一个文本,该文本随弹出菜单的打开/关闭动画一起显示。 问题是这个列表很长,因此,为了限制其长度,我添加了注释字段:
// constraints: const BoxConstraints(
// maxHeight: 500,
// ),
这解决了长度问题,但现在当我打开/关闭菜单时,该项目的动画与菜单不同步,文本只是出现并立即消失。 这是为什么?我该如何解决它?
注意:当使用非动态项目列表时,如下所示:
// itemBuilder: (context) => [
// PopupMenuItem<Task>(
// value: taskControlViewModel.selectedTask,
// child: TaskPopupView(task: taskControlViewModel.selectedTask!)),
// PopupMenuItem<Task>(
// value: taskControlViewModel.selectedTask,
// child: TaskPopupView(task: taskControlViewModel.selectedTask!)),
// PopupMenuItem<Task>(
// value: taskControlViewModel.selectedTask,
// child: TaskPopupView(task: taskControlViewModel.selectedTask!)),
// ],
这个动画错误不会出现,并且工作正常。
我尝试创建自定义 PopupMenuButton,最终遇到了相同的错误。
我尝试为列表中的每个项目提供自己的动画(适用于打开菜单,但不适用于关闭菜单)。
我尝试用 ContrainedBox 小部件包装 PopUpMenuButton,如下所示:
ConstrainedBox(
constraints: const BoxConstraints(
maxHeight: 500,
),
child: PopupMenuButton<Task>(
没用。
我发现您与动态项目的出现/消失不同步。您必须在 PopupMenuButton 中使用 ListView 和 ListView.builder 检查下面的代码:
return PopupMenuButton<Task>(
offset: const Offset(120, 50),
icon: const TaskIcon(),
onSelected: (item) => {
if (item.isSelected)
{
ref.read(taskControlViewModelProvider.notifier).setNoSelectedTask(),
}
else
{
ref
.read(taskControlViewModelProvider.notifier)
.setSelectedTask(item),
}
},
itemBuilder: (context) {
// Use ListView.builder to build the list of PopupMenuItem dynamically
return ListView.builder(
itemCount: tasks?.length ?? 0,
itemBuilder: (context, index) {
final task = tasks![index];
return PopupMenuItem<Task>(
value: task,
child: TaskPopupView(task: task),
);
},
);
},
);
当您使用 ListView.builder 时,您可以创建一个动态项目列表,如果超过指定高度(在您的情况下为 500),该列表将滚动,同时保持动画与 PopupMenuButton 的打开和同步关闭。您可以根据需要调整maxHeight。