可重新排序列表中的弹出菜单位置不正确

Tou*_*uch 5 dart flutter

有谁知道为什么 PopupMenuButton 在 ReorderableListView 中使用时会呈现在错误的位置?当在普通 ListView 中使用时,它似乎可以正确渲染。

这是一个示例屏幕截图:

问题示例

对于那些想要示例代码的人:

import 'package:flutter/material.dart';

void main() {
  runApp(ListApp());
}

class ListApp extends StatefulWidget {
  @override
  _ListAppState createState() => _ListAppState();
}

class _ListAppState extends State<ListApp> {
  List<String> items = [
    "Item 1",
    "Item 2",
    "Item 3",
    "Item 4",
    "Item 5",
    "Item 6",
    "Item 7",
  ];
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Reorder List'),
        ),
        body: Container(
          child: ReorderableListView(
              // child: ListView(

              onReorder: (oldIndex, newIndex) {
                int deleteIndex = oldIndex;
                items.insert(newIndex, items[oldIndex]);

                if (oldIndex > newIndex) {
                  // The old index is now 1 index higher
                  deleteIndex++;
                }
                items.removeAt(deleteIndex);
                setState(() {
                  items = items;
                });
              },

              children: items.map((item) {
                return Card(
                  key: Key(item),
                  child: ListTile(
                    title: Text(item),
                    trailing: PopupMenuButton(
                      itemBuilder: (context) {
                        return [
                          PopupMenuItem(
                            child: Text(item),
                            value: item,
                          )
                        ];
                      },
                    ),
                  ),
                );
              }).toList()),
        ),
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

难道是我使用 PopupMenuButton 的方式错误,还是这个 Widget 有问题?

我希望我的列表可以排序,但 PopupMenuButton 出现在错误的位置是一个问题。

Spa*_*atz 5

看起来问题应该出在ReorderableListView小部件的代码中,但实际上它隐藏在PopupMenu中。为了计算弹出位置,此代码评估覆盖层的渲染框:

final RenderBox overlay = Overlay.of(context).context.findRenderObject() as RenderBox;
Run Code Online (Sandbox Code Playgroud)

因为默认情况下,该Overlay.of方法会在层次结构中搜索最近的覆盖层,因此对于ReorderableListView,它返回内部覆盖层(为限制拖动手势而创建的覆盖层),但对于ListView,它返回根覆盖层。由于根导航器用于显示弹出菜单,因此前一种情况会出现转变。

调用Overlay.of方法 withrootOverlay: true修复了 bug:

final RenderBox overlay = Overlay.of(context, rootOverlay: true).context.findRenderObject() as RenderBox;
Run Code Online (Sandbox Code Playgroud)

修补Flutter SDK是最合适的解决方案。


Lon*_*olf 3

我认为这是最好的,你可以在不点击小部件的情况下获得它

在此输入图像描述

             PopupMenuButton(
                  offset: Offset(0, 50), //add offset to fix it
                  itemBuilder: (context) {
                    return [
                      PopupMenuItem(
                        child: Text(item),
                        value: item,
                      )
Run Code Online (Sandbox Code Playgroud)