Skip to content

MenuAnchor does not update menuChildren position after being repositioned. #169457

@kmrosiek

Description

@kmrosiek

Steps to reproduce

  1. Flutter (Channel stable, 3.29.2)
  2. Copy and run attached code
  3. Click Select color so that MenuAnchor gets opened.
  4. Wait up to 5 sec for the animation to happen (list item gets removed/inserted)
  5. Notice menuChildren are not aligned.

Expected results

menuChildren are aligned when layout changes and position of MenuAnchor is changed.

Actual results

When MenuAnchor is repositioned menuChildren` stay in the old position and become unaligned.

Code sample

Code sample
import 'package:flutter/material.dart';
import 'dart:async';

void main() {
  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Time List Demo',
      theme: ThemeData(colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple)),
      home: const MyHomePage(title: 'Time List Demo'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final List<String> _items = ['Item 1', 'Item 2', 'Item 3', 'Item 4', 'Item 5'];
  Timer? _timer;
  Color _selectedColor = Colors.blue;
  bool _showFirstItem = true;

  @override
  void initState() {
    super.initState();
    _timer = Timer.periodic(const Duration(seconds: 5), (timer) {
      setState(() {
        _showFirstItem = !_showFirstItem;
      });
    });
  }

  @override
  void dispose() {
    _timer?.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(backgroundColor: Theme.of(context).colorScheme.inversePrimary, title: Text(widget.title)),
      body: ListView.builder(
        itemCount: _items.length,
        itemBuilder: (context, index) {
          if (index == 0 && !_showFirstItem) {
            return const SizedBox.shrink();
          }

          return Container(
            margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
            padding: const EdgeInsets.all(16),
            decoration: BoxDecoration(
              color: _selectedColor.withOpacity(0.1),
              borderRadius: BorderRadius.circular(8),
              border: Border.all(color: _selectedColor),
            ),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(_items[index], style: TextStyle(color: _selectedColor)),
                if (index == 3)
                  Padding(
                    padding: const EdgeInsets.only(top: 8.0),
                    child: MenuAnchor(
                      builder: (context, controller, child) {
                        return ElevatedButton(
                          onPressed: () {
                            if (controller.isOpen) {
                              controller.close();
                            } else {
                              controller.open();
                            }
                          },
                          child: Row(
                            mainAxisSize: MainAxisSize.min,
                            children: [
                              Container(
                                width: 20,
                                height: 20,
                                decoration: BoxDecoration(color: _selectedColor, shape: BoxShape.circle),
                              ),
                              const SizedBox(width: 8),
                              const Text('Select Color'),
                            ],
                          ),
                        );
                      },
                      menuChildren: [
                        MenuItemButton(
                          child: const Text('Blue'),
                          onPressed: () {
                            setState(() => _selectedColor = Colors.blue);
                          },
                        ),
                        MenuItemButton(
                          child: const Text('Red'),
                          onPressed: () {
                            setState(() => _selectedColor = Colors.red);
                          },
                        ),
                      ],
                    ),
                  ),
              ],
            ),
          );
        },
      ),
    );
  }
}

Screenshots or Video

Screenshots / Video demonstration
vi_resized.mov

Logs

Logs
[Paste your logs here]

Flutter Doctor output

Doctor output
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.29.2, on macOS 15.5 24F74 darwin-arm64, locale en-PL)
[!] Android toolchain - develop for Android devices (Android SDK version 35.0.0)
    ✗ cmdline-tools component is missing
      Run `path/to/sdkmanager --install "cmdline-tools;latest"`
      See https://developer.android.com/studio/command-line for more details.
    ✗ Android license status unknown.
      Run `flutter doctor --android-licenses` to accept the SDK licenses.
      See https://flutter.dev/to/macos-android-setup for more details.
[✓] Xcode - develop for iOS and macOS (Xcode 16.3)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2024.1)
[✓] VS Code (version 1.100.2)
[✓] Connected device (5 available)
[✓] Network resources

! Doctor found issues in 1 category.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Important issues not at the top of the work lista: qualityA truly polished experiencef: material designflutter/packages/flutter/material repository.found in release: 3.32Found to occur in 3.32found in release: 3.33Found to occur in 3.33frameworkflutter/packages/flutter repository. See also f: labels.has reproducible stepsThe issue has been confirmed reproducible and is ready to work onr: fixedIssue is closed as already fixed in a newer versionteam-designOwned by Design Languages teamtriaged-designTriaged by Design Languages team

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions