flutter

Framework

flutter/flutter

Google's UI toolkit for building natively compiled apps for mobile, web, and desktop.

Overview

Flutter is an open-source UI toolkit by Google that enables developers to create beautiful, fast applications from a single codebase for mobile, web, and desktop. It provides a rich set of customizable widgets and hardware-accelerated graphics, ensuring native performance. Flutter also offers a productive development experience with features like hot reload.

README Preview

\n  \n    \n      \n      \n    \n  \n\n\n[](https://flutter-dashboard.appspot.com/#/build?repo=flutter)\n[![Discord badge][]][Discord instructions]\n[![Twitter handle][]][Twitter badge]\n[![BlueSky badge][]][BlueSky handle]\n[](https://codecov.io/gh/flutter/flutter)\n[](https://insights.linuxfoundation.org/project/flutter)\n[](https://bestpractices.coreinfrastructure.org/projects/5631)\n[](https://slsa.dev)\n\nFlutter is Google's SDK for crafting beautiful, fast user experiences for\nmobile, web, and desktop from a single codebase. Flutter works with existing\ncode, is used by developers and organizations around the world, and is free and\nopen source.\n\n## Documentation\n\n* [Install Flutter](https://docs.flutter.dev/get-started)\n* [Flutter documentation](https://docs.flutter.dev)\n* [Development wiki](./docs/README.md)\n* [Contributing to Flutter](https://github.com/flutter/flutter/blob/main/CONTRIBUTING.md)\n\nFor release and other announcements, join the\n[flutter-announce](https://groups.google.com/g/flutter-announce)\nmailing list. Our documentation also tracks [breaking\nchanges](https://docs.flutter.dev/release/breaking-changes) across releases.\n\n## Terms of service\n\nThe Flutter tool may occasionally download resources from Google servers. By\ndownloading or using the Flutter SDK, you agree to the Google Terms of Service:\nhttps://policies.google.com/terms\n\nFor example, when installed from GitHub (as opposed to from a prepackaged\narchive), the Flutter tool will download the Dart SDK from Google servers\nimmediately when first run, as it is used to execute the `flutter` tool itself.\nThis will also occur when Flutter is upgraded (e.g. by running the `flutter\nupgrade` command).\n\n## About Flutter\n\nWe think Flutter will help you create beautiful, fast apps, with a productive,\nextensible and open development model, whether you're targeting iOS or Android,\nweb, Windows, macOS, Linux or embedding it as the UI toolkit for a platform of\nyour choice.

FAQ (5)

Troubleshooting
How to fix "StateError: Bad state: No element" crash in CupertinoPicker tap-to-select when the picker is dismissed during the animation?

This is a Flutter framework race condition (flutter/flutter#192135) in _CupertinoPickerState._handleChildTap: after the 300ms tap-to-select animation (_kCupertinoPickerTapToScrollDuration), the code reads FixedExtentScrollController.selectedItem without checking the widget is still mounted. If the picker is disposed within 300ms of an off-centre tap (e.g. a parent hides it on selection, or a modal with a short exit animation is popped), selectedItem has no attached positions and throws Bad state: No element. It affects Flutter 3.27.0 through at least 3.47.2.

Workarounds until the fix lands (PR flutter/packages#13012):

1. Delay disposal so the picker outlives the animation — wait more than 300ms after the selection change before hiding/popping it:

Timer(const Duration(milliseconds: 350), () {
  if (mounted) Navigator.of(context).pop();
});

Note: tapping the barrier of showCupertinoModalPopup is safe by default because its 335ms exit transition outlives the 300ms animation.

2. Patch the framework locally — guard the post-await code in packages/flutter/lib/src/cupertino/picker.dart (or cupertino_ui in flutter/packages):

await _effectiveController.animateToItem(
  index,
  duration: _kCupertinoPickerTapToScrollDuration,
  curve: _kCupertinoPickerTapToScrollCurve,
);
if (!mounted) return;          // add this guard
_enableHapticFeedback = true;
_lastHapticIndex = _effectiveController.selectedItem;

3. As a last resort, catch the error globally via PlatformDispatcher.instance.onError and ignore StateError from _handleChildTap.

GitHub Issue #192135
Troubleshooting
Why is the Z perspective effect not applied when using Matrix4 with Flutter's Transform widget?

The perspective term gets lost because methods like setRotation() or Matrix4.compose() overwrite the top-left 3x3 of the matrix, wiping the interaction between the perspective entry (row 3, col 2) and the rotation. A flat widget has z=0 everywhere, so if perspective doesn't fold into w, nothing is divided and no depth appears.

**Fix 1 — chain perspective BEFORE rotation** (so rotation folds perspective into w):

Matrix4.identity()
  ..setEntry(3, 2, 0.001) // perspectiveStrength
  ..rotateX(x)
  ..rotateY(y);

**Fix 2 — build the matrix manually** with perspectiveStrength multiplied into the rotation's third column and the z-translation (confirmed working):

return Matrix4(
  r00, r10, r20, perspectiveStrength * r20,
  r01, r11, r21, perspectiveStrength * r21,
  r02, r12, r22, perspectiveStrength * r22,
  xTranslation,
  yTranslation,
  zTranslation,
  perspectiveStrength * zTranslation + 1,
);

Note: applying setEntry(3, 2, p) after translateByDouble()/setRotation() only affects z translation/rotation, not x/y rotations — this is expected matrix math behavior, not a bug in vector_math or Flutter.

GitHub Issue #194632
Troubleshooting
Why does a TextField lose focus on Flutter web when accessibility (semantics) is enabled, and how to fix it?

Cause: If an ancestor Theme rebuilds with a ThemeData that is never equal to the previous one (e.g., you create WidgetStateProperty.resolveWith inline in build — it has no == override), ScrollableState.didChangeDependencies recreates the scroll position. This flips the semantics role between scrollable and generic (because hasImplicitScrolling is only set once position.haveDimensions is true), and the web engine re-appends the DOM elements, moving document.activeElement to <body> so typing no longer lands in the <textarea>. This happens when a TextField sits inside a SingleChildScrollView and any rebuild is triggered (e.g., setState from a focus/text listener).

Workaround: Build your ThemeData once and reuse the same instance every build — store it in a final field, initState, or a top-level/static constant instead of constructing it inside build. Avoid allocating WidgetStateProperty.resolveWith(...) or any property without an == override inline in build. Verified by the reporter: reusing one ThemeData object across builds makes typing land; removing the scroll view also avoids it. Since this is a confirmed Flutter web engine/framework bug (role swap moves the focused node), also upgrade Flutter once the fix lands on stable.

GitHub Issue #192792
Troubleshooting
Why does `flutter test --platform chrome` hang forever at "loading" and how do I fix it?

This is a bug in Flutter's web test server (confirmed on Flutter 3.41.7). The server matches requests with a substring check on host.dart.js, so any library whose filename ends in host.dart (e.g. foo_host.dart, ghost.dart) compiles to foo_host.dart.js, which also matches. The server returns the test host bundle instead of the real module, the module loader throws TypeError: Cannot read properties of undefined, and the runner waits indefinitely with no error, no timeout, and near-zero CPU.

Fixes:
1. Upgrade Flutter: the hang no longer reproduces on Flutter 3.47.4 stable. Run flutter upgrade, then re-run flutter test --platform chrome.
2. Workaround if you cannot upgrade: rename the library file so its basename does not end in host.dart (e.g. foo_host.dart -> foo_host_api.dart) and update all imports. Note that one such suite stalls the entire test run, so check every library file in the project.

Diagnosis tip: open the stalled test page in Chrome DevTools. If a request to /<path>/foo_host.dart.js returns the exact same bytes as /static/host.dart.js (~638 KB dart2js host bundle), you are hitting this bug.

GitHub Issue #192760
Troubleshooting
Why does a long Flutter Semantics label intercept taps on other buttons in Flutter web on iOS Safari?

This is a Flutter web engine bug: an invisible semantics node's long wrapped label overflows far below its element's box and participates in Safari's native hit testing, so tapping a visually lower widget (e.g., a button in a later sliver) targets the upper semantic node and fires its callback instead. The fix is in PR #194011; upgrade to the Flutter release that includes it (check the PR for the milestone, as it was still in review and not yet in a stable release when reported on Flutter 3.47.1). Until then, mitigations observed in the reproduction: keep accessibility labels short on web (labels that don't wrap avoid the overflow), or restructure the layout — replacing separate SliverToBoxAdapters with a Column produced correct stacking (z-index) and hit testing. Disabling semantics also avoids it but removes accessibility, so it is not a viable workaround.

GitHub Issue #192466