-
Major new features and breaking changes
-
Code examples & migration tips
- Why it matters for businesses & clients
- Sparkle Web take: How we leverage these changes
1. Stateful Hot Reload on Web is Enabled by Default
What changed:
Code / Usage Example:
# Before (older versions)
flutter run -d chrome --web-experimental-hot_reload
# In 3.35
flutter run -d chrome
# Now you get stateful hot reload by default for web
// A simple counter example to test
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) => MaterialApp(home: CounterScreen());
}
class CounterScreen extends StatefulWidget {
@override
_CounterScreenState createState() => _CounterScreenState();
}
class _CounterScreenState extends State<CounterScreen> {
int count = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Web Hot Reload Demo")),
body: Center(child: Text('Count: $count', style: TextStyle(fontSize: 30))),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () => setState(() => count++),
),
);
}
}
2. WebAssembly (WASM) Dry Runs During JavaScript Builds
What changed:
-
Every JS build now performs a "dry run" compilation to WebAssembly (WASM) to check compatibility. You’ll get console warnings about potential issues.
-
Controlled with flags --wasm-dry-run or disable via --no-wasm-dry-run.
Why this matters:
-
Prepares web apps for future performance gains from WASM
-
Let's help you catch unsupported APIs early
- Helps reduce surprises when switching to WASM builds
Example:
flutter build web --wasm-dry-run
You might see warnings like:
WARNING: Some APIs used may not be supported in WASM target:
- dart:io
- certain plugins
Then you can revise code (replace unsupported APIs, use conditional imports, etc.).
3. Widget Previews (Experimental)
What changed:
-
A new workflow to preview individual widgets in isolation without running the full app. Useful to test themes, locale, font scaling, and UI states.
-
Properties like theme, brightness, and pub workspaces are supported in Preview.
Usage Example:
import 'package:flutter/material.dart';
// Assuming a preview widget is available
import 'package:flutter_widget_previewer/flutter_widget_previewer.dart';
@Preview(
name: 'ProfileCard Light Mode',
brightness: Brightness.light,
theme: ThemeData.light(),
locale: Locale('en'),
)
Widget buildProfileCardLight() => ProfileCard(userName: 'Alice');
@Preview(
name: 'ProfileCard Dark Mode',
brightness: Brightness.dark,
theme: ThemeData.dark(),
locale: Locale('en'),
)
Widget buildProfileCardDark() => ProfileCard(userName: 'Alice');
This allows design/QA teams to inspect layouts rapidly. Helps catch UI issues early.
4. Accessibility Improvements & Semantics Enhancements
What changed:
-
New widgets & helpers: SemanticsLabelBuilder, SliverEnsureSemantics to improve how UI elements are exposed to screen readers and assistive tech.
-
Better text scaling, RTL (right-to-left) support, and proper alignment of text selection toolbars. On iOS: CupertinoSliverNavigationBar respects accessibility scaling. Android TalkBack improved with platform views.
Code Example:
import 'package:flutter/material.dart';
class AccessibleList extends StatelessWidget {
@override
Widget build(BuildContext context) {
return CustomScrollView(
slivers: [
SliverEnsureSemantics(
sliver: SliverList(
delegate: SliverChildBuilderDelegate(
(ctx, idx) => Semantics(
label: 'Item number ${idx + 1}',
child: ListTile(title: Text('Item ${idx + 1}')),
),
childCount: 20,
),
),
),
],
);
}
}
Or using SemanticsLabelBuilder
:
SemanticsLabelBuilder(
label: (context, value) => 'Selected ${value.title}, $value.status',
child: SomeWidget(),
);
5. Material & Cupertino Widget Polishing / Additions
What changed:
-
DropdownMenuFormField for Material 3 forms.
-
Scrollable NavigationRail (useful when many destinations).
- NavigationDrawer now supports header and footer elements.
- Cupertino polish: shapes (e.g., RSuperellipse), haptics for Picker/Slider, always-visible slider value indicator.
Code Example:
// NavigationDrawer with header and footer
NavigationDrawer(
header: DrawerHeader(child: Text('Welcome')),
footer: Container(
padding: EdgeInsets.all(16),
child: Text('Version 1.0.0'),
),
children: [
NavigationDrawerDestination(
icon: Icon(Icons.home),
label: Text('Home'),
),
NavigationDrawerDestination(
icon: Icon(Icons.settings),
label: Text('Settings'),
),
],
);
6. Breaking Change: Form Widget & Slivers
What changed:
- In previous versions, you might have placed Form directly inside a list of slivers (in CustomScrollView). In 3.35, this is no longer allowed. You must wrap Form in a SliverToBoxAdapter.
Example of migration:
Before:
CustomScrollView(
slivers: [
Form(
child: SliverList(
delegate: SliverChildBuilderDelegate(
(ctx, idx) => Text('Form item $idx'),
childCount: 5,
),
),
),
],
);
After:
CustomScrollView(
slivers: [
SliverToBoxAdapter(
child: Form(
child: Column(
children: List.generate(5, (idx) => Text('Form item $idx')),
),
),
),
// Other slivers...
],
);
This change is essential to avoid runtime layout errors and to align with semantics.
7. Platform Minimum Version Bumps & Compatibility Changes
What changed:
-
Android minimum SDK version: SDK 24 (Nougat) or higher.
-
iOS minimum version bumped to iOS 13. macOS minimum version 10.15.
Why this matters:
-
Helps drop support for older, less secure / less capable platforms
-
Reduces testing surface for very old devices
- Allows Flutter to use newer platform APIs safely
Migration Tip:
-
Update android/app/build.gradle and ios/Runner.xcodeproj deployment target / Info.plist accordingly
-
If you had code branches or feature flags for old versions (< SDK 24 or < iOS 13), either drop those or maintain backwards compatibility separately
8. SensitiveContent Widget / Privacy & Security Features
What changed:
- New SensitiveContent widget (Android API 35+) allows portions of the UI to block screenshots or screen recordings, useful for sensitive data screens (financial, healthcare, etc.)
Usage Example:
import 'package:flutter/widgets.dart';
import 'package:flutter/services.dart';
class SecureScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return SensitiveContent(
child: Scaffold(
appBar: AppBar(title: Text('Secure Info')),
body: Center(child: Text('Data you can’t screen-capture!')),
),
);
}
}
This prevents recording or screenshotting when the widget is in view (depending on platform support).
9. Frame / Impeller & Rendering Fixes
What changed:
-
Multiple rendering fixes (tree sliver offsets, correct fade/animate insets, clip bottom widgets in navbar transitions, etc.) to smooth out visual glitches.
-
Impeller goldens re-enabled.
Why this matters:
-
UI is more polished, with fewer janky animations or glitches
-
Important for brands where UI/UX is a selling point (Healthcare apps, Fintech dashboards, etc.)
10. Developer Tooling & “Create with AI” / MCP Server Support
What changed:
-
Flutter documents now include a “Create with AI” guide showing how to integrate AI-powered tools such as Gemini Code Assist, Dart & Flutter MCP Server.
-
These tools provide better context for code completion, error detection, and boilerplate generation.
Example use (pseudo-code / config):
# To enable widget previews (if not enabled by default):
flutter config --enable-widget-previews
# To run build with wasm dry run:
flutter build web --wasm-dry-run
Why These Changes Matter: Business & Client Impact
-
Faster Iteration Cycles: With hot reload working smoothly on the web, UI/UX fixes, client feedback loops, and design tweaks happen much quicker. Sparkle Web can deliver feature demos faster and improve UI alignment with client expectations.
-
Future-Readiness: WASM readiness ensures that if/when web builds shift more to WASM, you’re not caught off guard. It helps with bundle size, startup speed.
- Inclusive Apps: Accessibility improvements reduce support burden, improve compliance (e.g., for accessibility laws), and open up to broader audiences. For healthcare, government, and fintech apps, this is crucial.
- Polished UI / Native Feel: Material 3 + Cupertino polish means clients get modern, native-feeling apps without needing heavy custom UI work.
-
Security & Data Privacy: The SensitiveContent widget helps with privacy compliance and trust, especially for sectors where screen sharing / privacy matters.
-
Platform Maintenance Simplified: Bumping minimum versions means less legacy code to support, fewer platform-specific bugs.
Sparkle Web Perspective: How We Use Flutter 3.35 in Projects
-
Immediately upgrade new projects to SDK 3.35 to benefit from the latest hot reload, widget previews, and Impeller improvements.
-
Audit existing projects to adjust breaking changes (Form inside sliver, minimum OS version).
- Use the new widgets (DropdownMenuFormField, Scrollable NavigationRail, etc.) in UI redesigns to match modern design systems.
- Use SensitiveContent in apps handling private data (healthcare records, payments).
-
Ensure accessibility is baked in: use SemanticsLabelBuilder & SliverEnsureSemantics, test with VoiceOver/TalkBack.
Migration Tips & Checklist

Before & After Upgrade Flow
Before (pre-3.35):
-
Web app with hot reload, but losing state frequently with complex widget trees
-
The developer manually toggles flags for web hot reload
- Form placed directly in the silver list, causing layout quirks
- UI uses older form controls; custom dropdowns rather than Material3 updated ones
-
Sensitive screens are not protected
After (with 3.35):
-
Web development feels much smoother; state preserved, quicker iterations
-
Remove flag overhead
- Refactored Form placement for stable sliver behavior
- Use DropdownMenuFormField, scrollable NavigationRail, and NavigationDrawer with header/footer
-
Use SensitiveContent to guard privacy screens
Mohit Kokane
A highly skilled Flutter Developer. Committed to delivering efficient, high-quality solutions by simplifying complex projects with technical expertise and innovative thinking.
Reply