Skip to content

Conversation

@bleroux
Copy link
Contributor

@bleroux bleroux commented Oct 24, 2024

Description

This PR fixes DropdownMenu menu vertical position when tight constraints are given to the DropdownMenu.

Before:

image

After:

image

Related Issue

Fixes the minHeight part of DropdownMenu does not correctly handle incoming maxWidth and minHeight constraints.
(The maxWidth part was already fixed in #147233).

Tests

Adds 4 tests.
Refactors many existing tests.

@github-actions github-actions bot added framework flutter/packages/flutter repository. See also f: labels. f: material design flutter/packages/flutter/material repository. labels Oct 24, 2024
@bleroux bleroux force-pushed the fix_DropdownMenu_menu_vertical_position branch from 4fa5fd5 to f41296c Compare October 24, 2024 12:04
@github-actions github-actions bot added d: api docs Issues with https://api.flutter.dev/ d: examples Sample code and demos labels Oct 24, 2024
Copy link
Contributor

@justinmc justinmc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍

child: menuAnchor,
);
// Put the menu anchor into a Column with CrossAxisAlignment.stretch
// to loose just the height constraints. Doing so, the menu anchor
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"loose" => "loosen"

@justinmc justinmc added autosubmit Merge PR when tree becomes green via auto submit App and removed autosubmit Merge PR when tree becomes green via auto submit App labels Oct 30, 2024
);
// Put the menu anchor into a Column with CrossAxisAlignment.stretch
// to loose just the height constraints. Doing so, the menu anchor
// adjusts to the inner text field intrinsic heigth even if it received
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// adjusts to the inner text field intrinsic heigth even if it received
// adjusts to the inner text field intrinsic height even if it received

@justinmc
Copy link
Contributor

It looks like there are several legit Google test failures. I was expecting maybe some visual diff tests where the menu items have moved or changed size, but I don't see any like that. Instead I see stuff like a tap happening on a dropdown item, then a pumpAndSettle, but now the wrong item is selected or the selection didn't change.

Any thoughts on that?? Sorry for the awkward second hand description here.

@QuncCccccc
Copy link
Contributor

Taking a look.

// The first one is the real button item in the menu.
// The second one is not visible, it is part of _DropdownMenuBody
// which is used to compute the dropdown width.
return find.widgetWithText(MenuItemButton, label).first;
Copy link
Contributor

@QuncCccccc QuncCccccc Oct 30, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should not use .first to get the menu item because we layout the items for the first time to get each items' size but we don't paint them. The .last should be the "real" buttons that show in the menu.

Oh sorry, I didn't see the comment above. Why do we change the order? I'm a little confused. Which part of change make the order get changed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The order change is a result of the new tree structure.

Before this PR _DropdownMenuBody was inside the MenuAnchor, with this PR MenuAnchor is inside _DropdownMenuBody.
Having two occurrences of each widget is somewhat confusing, especially for the testing story, whether the real widget is first or second, I don’t know if there is a way to avoid this.

Do you see any reason (other than not breaking existing tests) why the real item should be the second one and not the first one? In both cases, it seems arbitrary to me?
Nonetheless, If it breaks to many existing tests and it is difficult to update them, we can try to tweak the order, not sure if it is possible.

Before going further, I will investigate if the issue can be fix at MenuAnchor level according to #157496 (comment)

@QuncCccccc
Copy link
Contributor

Should we fix this problem in MenuAnchor? I can reproduce this issue in MenuAnchor

import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: Container(
        alignment: Alignment.center,
        color: Colors.amber,
        child: Scaffold(
          body: SizedBox(
            height: 500,
            width: 500,
            child: ColoredBox(
              color: Colors.amber,
              child: MenuAnchor(
                builder: (context, controller, child) {
                  return TextField(
                    decoration: InputDecoration(
                      border: OutlineInputBorder(),
                    ),
                    onTap: () {
                      if (controller.isOpen) {
                        controller.close();
                      } else {
                        controller.open();
                      }
                    }
                  );
                },
                menuChildren: [
                  MenuItemButton(
                    child: Text('This is a very long label',),
                  )
                ],
              ),
              // child: DropdownMenu(
              //   // expandedInsets: EdgeInsets.zero,
              //   dropdownMenuEntries: [
              //     DropdownMenuEntry(
              //       value: '',
              //       label: 'This is a very long label',
              //     ),
              //   ],
              // ),
            ),
          ),
        ),
      ),
    );
  }
}

@bleroux bleroux force-pushed the fix_DropdownMenu_menu_vertical_position branch from 71549db to 0e9cac3 Compare October 31, 2024 06:31
@bleroux
Copy link
Contributor Author

bleroux commented Oct 31, 2024

Should we fix this problem in MenuAnchor? I can reproduce this issue in MenuAnchor

Very good point, I don’t know if this can be fixed at MenuAnchor level but it is really worth investigating. The first question I will try to answer is: can MenuAnchor loose the constraints for the widget it surrounds? (it probably can but will it be possible for all cases as MenuAnchor is versatile?).

@bleroux bleroux marked this pull request as draft October 31, 2024 09:13
auto-submit bot pushed a commit that referenced this pull request Nov 5, 2024
## Description

This PR introduces some utility functions to simplify some DropdownMenu tests.
The main purpose is to centralize and document how tests should find menu items, because it is tricky as there are two occurrences of each widgets and using '.last' is mandatory:

```dart
  Finder findMenuItemButton(String label) {
    // For each menu items there are two MenuItemButton widgets.
    // The last one is the real button item in the menu.
    // The first one is not visible, it is part of _DropdownMenuBody
    // which is used to compute the dropdown width.
    return find.widgetWithText(MenuItemButton, label).last;
  }
```

## Related Issue

This is extracted from #157496.

## Tests

Refactors many existing tests.
@bleroux
Copy link
Contributor Author

bleroux commented Dec 2, 2024

Closing as I will try a simpler approach.

@bleroux bleroux deleted the fix_DropdownMenu_menu_vertical_position branch December 6, 2024 15:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

d: api docs Issues with https://api.flutter.dev/ d: examples Sample code and demos f: material design flutter/packages/flutter/material repository. framework flutter/packages/flutter repository. See also f: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants