Skip to content

Instantly share code, notes, and snippets.

@dipendra-sharma
Created April 1, 2026 12:24
Show Gist options
  • Select an option

  • Save dipendra-sharma/e351fe8735cfc58a4857aa90e83ca5b8 to your computer and use it in GitHub Desktop.

Select an option

Save dipendra-sharma/e351fe8735cfc58a4857aa90e83ca5b8 to your computer and use it in GitHub Desktop.
Flutter AppScaffold — transparent status bar + nav bar with correct icon brightness on iOS and all Android navigation modes
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
/// Drop-in replacement for [Scaffold] that enforces:
/// - Transparent status bar (never takes AppBar background color)
/// - Transparent system navigation bar on Android with correct icon brightness
/// - Correct status bar icon brightness on both iOS and Android
/// - Body extends behind bottom navigation bar (use [EdgePaddedListView]
/// inside body to ensure list content is not hidden)
class AppScaffold extends StatelessWidget {
const AppScaffold({
super.key,
this.appBar,
required this.body,
this.bottomNavigationBar,
this.floatingActionButton,
this.floatingActionButtonLocation,
this.backgroundColor,
this.resizeToAvoidBottomInset = true,
this.extendBodyBehindAppBar,
});
final PreferredSizeWidget? appBar;
final Widget body;
final Widget? bottomNavigationBar;
final Widget? floatingActionButton;
final FloatingActionButtonLocation? floatingActionButtonLocation;
final Color? backgroundColor;
final bool resizeToAvoidBottomInset;
/// Override for [Scaffold.extendBodyBehindAppBar].
///
/// Defaults to `true` when [appBar] is null (body fills the whole screen),
/// and `false` when [appBar] is provided. Set this explicitly when you need
/// a transparent/blurred AppBar with the body drawn behind it.
final bool? extendBodyBehindAppBar;
/// Builds a [SystemUiOverlayStyle] that keeps both status bar and navigation
/// bar transparent with icon brightness matching [themeBrightness].
///
/// iOS and Android have opposite brightness conventions:
/// - [statusBarBrightness] (iOS only): Brightness.light → dark icons on light bg
/// - [statusBarIconBrightness] (Android): Brightness.dark → dark icons on light bg
static SystemUiOverlayStyle _overlayStyle(Brightness themeBrightness) {
final iconBrightness = themeBrightness == Brightness.light
? Brightness.dark
: Brightness.light;
return SystemUiOverlayStyle(
statusBarColor: Colors.transparent,
statusBarBrightness: themeBrightness, // iOS only — NOT inverted
statusBarIconBrightness: iconBrightness, // Android — inverted
systemNavigationBarColor: Colors.transparent,
systemNavigationBarDividerColor: Colors.transparent,
systemNavigationBarIconBrightness: iconBrightness,
systemNavigationBarContrastEnforced: false, // disable auto-scrim Android 10+
);
}
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final overlayStyle = _overlayStyle(theme.brightness);
// Patch AppBarTheme so any AppBar passed to this scaffold uses our overlay
// style instead of its default (which sets statusBarColor = AppBar bg color).
final patchedTheme = theme.copyWith(
appBarTheme: theme.appBarTheme.copyWith(
systemOverlayStyle: overlayStyle,
),
);
return AnnotatedRegion<SystemUiOverlayStyle>(
value: overlayStyle,
child: Theme(
data: patchedTheme,
child: Scaffold(
extendBodyBehindAppBar: extendBodyBehindAppBar ?? (appBar == null),
extendBody: true,
appBar: appBar,
body: body,
bottomNavigationBar: bottomNavigationBar,
floatingActionButton: floatingActionButton,
floatingActionButtonLocation: floatingActionButtonLocation,
backgroundColor: backgroundColor,
resizeToAvoidBottomInset: resizeToAvoidBottomInset,
),
),
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment