Touch
Touch

Reputation: 1491

Popup menu in reorderable list is out of position

Does anyone know why the PopupMenuButton renders at the wrong place when used in a ReorderableListView? It seems to render correctly when used inside a normal ListView.

Here is an example screenshot:

Example of problem

For those that want example code:

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()),
        ),
      ),
    );
  }
}

Could it be that I'm using the PopupMenuButton the wrong way or is this Widget buggy?

I'd like my list to be sortable but the PopupMenuButton appearing at the wrong place is a problem.

Upvotes: 5

Views: 2878

Answers (2)

Spatz
Spatz

Reputation: 20158

It seems that the problem should be in the ReorderableListView widget's code, but in fact it's hidden in PopupMenu. To calculate popup position this code evaluates overlay's rendering box:

final RenderBox overlay = Overlay.of(context).context.findRenderObject() as RenderBox;

Because, by default, the Overlay.of method searches hierarchy for the nearest overlay, in case of ReorderableListView it returns internal overlay (one created to restrict dragging gesture) but for ListView it returns root overlay. Since the root navigator used to show popup menu, a shift appears in the former case.

Calling Overlay.of method with rootOverlay: true fixes the bug:

final RenderBox overlay = Overlay.of(context, rootOverlay: true).context.findRenderObject() as RenderBox;

Patching Flutter SDK is the most appropriate solution.

Upvotes: 5

LonelyWolf
LonelyWolf

Reputation: 4402

I think this is as best as you can get it without tapping into the widget

enter image description here

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

Upvotes: 3

Related Questions