On this page · 15 sections
- What is new in Flutter 3.44
- The Widget Previewer, explained
- Enabling the Previewer
- Your first preview
- Customising previews
- Design systems and @MultiPreview
- The web caveat and the rules
- Create with AI and the MCP server
- Android screen-share protection
- A worked example: every state of one input
- A faster 2026 UI workflow
- India-specific considerations
- FAQ
- How eCorpIT can help
- References
Summary. Flutter 3.44, released alongside Dart 3.12 at Google I/O 2026 in May, pushes three things into the everyday workflow: the Widget Previewer, a Create with AI guide, and Android screen-share protection. The Widget Previewer renders a widget in Chrome, isolated from the full app, using a @Preview annotation. It first appeared experimentally in Flutter 3.35 and gained the IDE integration that made it useful in 3.38, so 3.44 is where it becomes routine. Create with AI documents how Gemini Code Assist and the Gemini CLI connect through the Dart and Flutter MCP server to read your widget tree and fix errors. And a new SensitiveContent widget blacks out sensitive screens during media projection on Android API 35 and above. This guide covers each, with the code to use them.
For years the Flutter UI loop was compile, navigate, observe, repeat. You changed a widget, hot-reloaded, then tapped through several screens to reach the state you wanted to check. Hot reload made the change fast; it did nothing about the navigation. Flutter 3.44 is the release where the alternative, previewing a single widget in isolation, becomes the default way to build UI. As Majid Hajian, a Developer Advocate at DCM, puts it: "Widget Previewer completes the picture. It makes development focused." If you also want the language changes from the same cycle, read our guide to Dart 3.12.
What is new in Flutter 3.44
Three items in the Flutter 3.44 what's-new matter most for day-to-day work.
| Feature | What it does | Where it runs |
|---|---|---|
| Widget Previewer | Renders isolated widgets in real time with @Preview |
Chrome, or the IDE sidebar |
| Create with AI | Guidance for Gemini Code Assist and the Gemini CLI | Your IDE and terminal |
| SensitiveContent widget | Obscures sensitive screens during screen sharing | Android API 35 and above |
| Dart and Flutter MCP server | Connects AI assistants to your project | Local dev environment |
| Impeller and web updates | Rendering and platform refinements | Android, iOS, web |
The Widget Previewer is the headline, so start there.
The Widget Previewer, explained
The Widget Previewer isolates a Flutter widget and renders it in real time as you code, decoupled from your main app. If you have used SwiftUI's canvas or Jetpack Compose previews, the idea is familiar, and if you have used Storybook on the web, the goal is the same: components as living, interactive documentation. It was introduced as an experimental feature in Flutter 3.35, and the IDE integration that makes it practical arrived in 3.38.
Why it matters is the navigation tax. Verifying a widget across screen sizes, text scales, light and dark themes, and locales used to mean rebuilding and re-navigating for each case. The Previewer shows those variations side by side, without restarting the app. This complements, rather than replaces, hot reload: hot reload speeds up the code change, the Previewer removes the trip through your app to see the result.
Enabling the Previewer
Use Flutter 3.38 or later; 3.44 is current. There are two ways in. In VS Code, Android Studio, or IntelliJ, look for the "Flutter Widget Preview" tab in the sidebar, usually on the right, and click it to spin up the environment. From the command line, launching the previewer starts a local server and opens the preview in Chrome, which auto-refreshes when you save. The IDE path is the one most teams use, because it keeps the preview beside your code.
Your first preview
Import the previews package and annotate a widget-producing function with @Preview:
import 'package:flutter/material.dart';
import 'package:flutter/widget_previews.dart';
@Preview(name: 'My Sample Text')
Widget mySampleText() {
return const Text('Hello, World!');
}
Save the file, and the Previewer detects the annotation and renders a card labelled "My Sample Text." You can annotate three kinds of target: a top-level function that returns a Widget or WidgetBuilder, a static method that returns a Widget, or a public Widget constructor or factory that has no required arguments. Each preview card gives you zoom in and out, reset zoom, a light and dark toggle, and a hot restart for that single preview.
Customising previews
The @Preview annotation takes parameters that let one widget be checked under many conditions. These are the ones you will use most, documented on the Widget Previewer page.
| Parameter | What it controls | Example |
|---|---|---|
name |
The label above the preview | @Preview(name: 'Error state') |
size |
A fixed canvas size | size: Size(375, 812) |
brightness |
Initial light or dark theme | brightness: Brightness.dark |
theme |
Full Material or Cupertino theme data | theme: myPreviewTheme |
textScaleFactor |
Simulated font scaling | textScaleFactor: 2.0 |
wrapper |
Wraps the widget in context | wrapper: appWrapper |
group |
Groups related previews | group: 'Input states' |
Two rules matter because of how Dart handles annotations. Annotation arguments must be compile-time constants, so a theme or wrapper has to be a public top-level function or a static method, not an inline closure. The wrapper is the one to learn first, because most real widgets need a Scaffold, theme, or provider above them:
@Preview(name: 'Input in context', wrapper: appWrapper)
Widget inputPreview() => const MyTextField();
Widget appWrapper(Widget child) {
return Scaffold(
body: Padding(padding: const EdgeInsets.all(16), child: child),
);
}
Design systems and @MultiPreview
For a design system, writing a light and a dark preview for every component by hand gets old fast. Flutter 3.38 made the Preview class extendable, so you can define a custom annotation once and reuse it. A MultiPreview subclass generates several Preview instances from a single annotation, which keeps a component's states in sync as the design changes:
final class BrightnessPreview extends MultiPreview {
const BrightnessPreview({required this.name});
final String name;
@override
List<Preview> get previews => const [
Preview(brightness: Brightness.light, group: 'Theme'),
Preview(brightness: Brightness.dark, group: 'Theme'),
];
}
@BrightnessPreview(name: 'Input field')
Widget inputFieldPreview() => const MyDesignSystemInput(label: 'Enter text');
Now every component that uses @BrightnessPreview renders in both themes with no repeated boilerplate. For a team maintaining a component library, this is the difference between a design system that stays in sync and one that drifts. This pairs naturally with the code-conciseness gains in Dart 3.12's primary constructors, which shorten the widget classes themselves.
The web caveat and the rules
The Previewer renders with Flutter Web through the Dart Development Compiler, which compiles to JavaScript. That has consequences. Widgets that invoke dart:io or dart:ffi APIs, or plugins without web support, will show an error rather than render. A few practical rules follow: preview widgets that take no required constructor arguments, use the wrapper to inject any context a widget needs, keep wrapper and theme callbacks public or static, use group to organise a growing library, and avoid relative asset paths in favour of package-based paths like packages/my_package/assets/image.png. Widgets tied to the camera, sensors, or file system will not render in the web environment.
Create with AI and the MCP server
The second pillar of 3.44 is the Create with AI guide. It documents how to build with AI coding tools, and the engine underneath is the Dart and Flutter MCP server. The server connects an AI assistant directly to your development environment, so the assistant works from real project state rather than guesses. It can analyse and fix errors, resolve symbols, introspect and interact with a running app, search pub.dev for packages, manage dependencies, run tests, and format code.
Gemini Code Assist's agent mode integrates the Gemini CLI, and you point it at the MCP server by following the CLI configuration steps, then confirm it with /mcp in the agent chat. The Flutter extension for the Gemini CLI adds a default set of Flutter and Dart rules plus commands like /create-app and /modify for structured changes. This is the same MCP direction we covered in Flutter's AI features with Gemini and the Dart MCP server, now documented as a first-class workflow. If your AI features go beyond scaffolding into full flows, pair it with Genkit Dart.
Android screen-share protection
The third addition is a privacy control. Flutter 3.44 adds a SensitiveContent widget that prevents screens holding sensitive data, such as passwords or account details, from appearing when a user shares or records their screen. You set a child's content sensitivity to one of three ContentSensitivity values, notSensitive, sensitive, or autoSensitive, and if any SensitiveContent widget on the screen is marked sensitive, the whole screen is obscured during media projection.
SensitiveContent(
sensitivity: ContentSensitivity.sensitive,
child: PasswordField(),
);
The feature works on Android API 35 and above. On Android API 34 and below, or on other platforms, it has no effect and the screen is not obscured, so treat it as a defence-in-depth measure rather than a guarantee across every device.
A worked example: every state of one input
The payoff is clearest on a component with many states. Take a design-system text input that has to be verified empty, filled, in error, and disabled, each in light and dark. Without the Previewer, that is eight manual runs. With it, you declare the states once and read them side by side. A single preview function cannot return different widgets per preview, so group several functions under one group:
@Preview(name: 'Empty', group: 'Input states', wrapper: inputWrapper)
Widget inputEmpty() => const TextField(
decoration: InputDecoration(border: OutlineInputBorder(), labelText: 'Username'),
);
@Preview(name: 'Error', group: 'Input states', wrapper: inputWrapper)
Widget inputError() => const TextField(
decoration: InputDecoration(
border: OutlineInputBorder(), labelText: 'Username', errorText: 'Required',
),
);
@Preview(name: 'Disabled', group: 'Input states', wrapper: inputWrapper)
Widget inputDisabled() => const TextField(
enabled: false,
decoration: InputDecoration(border: OutlineInputBorder(), labelText: 'Username'),
);
Widget inputWrapper(Widget child) => Center(
child: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 320),
child: Padding(padding: const EdgeInsets.all(16), child: child),
),
);
All three cards render together under an "Input states" heading, and adding a dark variant is one more annotation. When you later change the component's border or padding, every state updates at once, which is exactly how edge cases that manual navigation would miss become visible. This is the pattern that turns a scattered component folder into documentation the whole team can read.
A faster 2026 UI workflow
Put together, the three additions change the shape of a Flutter session. You build a component in isolation in the Previewer, seeing every state and theme at once. You lean on the Gemini CLI and the MCP server to scaffold, refactor, and fix against real project context. And you mark the screens that hold private data so a screen recording does not leak them. None of these replaces sound engineering, but each removes a specific friction that used to slow UI work down. For the full set of announcements from the same event, see everything Flutter shipped at Google I/O 2026.
India-specific considerations
For Indian product teams and consultancies, two of these land with extra force. The Widget Previewer suits agencies that maintain design systems across several client apps, because a shared component library becomes visible documentation that new team members can read at a glance, cutting onboarding time. The SensitiveContent widget matters for fintech and health apps under the DPDP Act, where a screen recording that captures a customer's account number is a real disclosure risk; marking those screens sensitive is a low-cost control. Because the feature needs Android API 35, confirm your user base's device mix before relying on it, and keep server-side safeguards for older devices.
FAQ
How eCorpIT can help
eCorpIT builds and maintains production Flutter apps for clients in India and abroad, and we adopt each release deliberately rather than chasing the changelog. If your team wants help standing up a Widget Previewer workflow for a design system, wiring the Dart and Flutter MCP server into your AI tooling, or adding screen-share protection to a fintech or health app, our senior engineering team can help. Reach us through the contact page.
References
- Flutter documentation, Flutter Widget Previewer, docs.flutter.dev.
- Majid Hajian, Flutter Hot Reload Isn't Enough (And Why Flutter Developers Need Widget Previews), DCM, December 2025.
- Flutter documentation, What's new in the docs, docs.flutter.dev.
- Flutter documentation, Flutter 3.44.0 release notes, docs.flutter.dev.
- Flutter documentation, Create with AI, docs.flutter.dev.
- Flutter documentation, Dart and Flutter MCP server, docs.flutter.dev.
- Flutter documentation, Protect your app's sensitive content, docs.flutter.dev.
- Flutter team, What's new in Flutter 3.44, Flutter blog, May 2026.
- Flutter API, widget_previews library, api.flutter.dev.
- Flutter, flutter-add-widget-preview skill, GitHub.
- Yawar Othman, Flutter 3.44 and Dart 3.12: Everything That Changed at Google I/O 2026, Medium, May 2026.
_Last updated: July 7, 2026._