I don’t call it directly anymore I just do context.width or what ever thanks to this
// context_plus.dart
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
extension BuildContextX on BuildContext {
// ==== SCREEN & DEVICE INFO ====
double get width => MediaQuery.widthOf(this);
double get height => MediaQuery.heightOf(this);
Size get screenSize => MediaQuery.sizeOf(this);
bool get isLandscape =>
MediaQuery.orientationOf(this) == Orientation.landscape;
bool get isPortrait => !isLandscape;
double get pixelRatio => MediaQuery.devicePixelRatioOf(this);
T customTheme<T>() {
assert(T != dynamic, 'T must be a specific type, not dynamic');
return Theme.of(this).extension<T>()!;
}
// Safe area and insets
EdgeInsets get viewInsets => MediaQuery.viewInsetsOf(this);
EdgeInsets get padding => MediaQuery.paddingOf(this);
EdgeInsets get safeAreaPadding => MediaQuery.paddingOf(this);
EdgeInsets get viewPadding => MediaQuery.viewPaddingOf(this);
TextScaler get textScaler => MediaQuery.textScalerOf(this);
double get topPadding => padding.top;
double get bottomPadding => padding.bottom;
double get leftPadding => padding.left;
double get rightPadding => padding.right;
double get statusBarHeight => padding.top;
double get navigationBarHeight => padding.bottom;
bool get isKeyboardVisible => viewInsets.bottom > 0;
double get keyboardHeight => viewInsets.bottom;
// Screen categories
bool get isSmallScreen => width < 600;
bool get isMediumScreen => width >= 600 && width < 1200;
bool get isLargeScreen => width >= 1200;
bool get isTablet => width > 600;
bool get isDesktop => width > 1200;
bool get isMobile => width <= 600;
// Aspect ratio helpers
double get aspectRatio => width / height;
bool get isSquareScreen => (aspectRatio - 1.0).abs() < 0.1;
bool get isWideScreen => aspectRatio > 1.5;
bool get isTallScreen => aspectRatio < 0.75;
// ==== NAVIGATION ====
NavigatorState get navigator => Navigator.of(this);
Future<T?> push<T>(final Route<T> route) => navigator.push(route);
Future<T?> pushNamed<T>(final String routeName, {final Object? arguments}) =>
navigator.pushNamed<T>(routeName, arguments: arguments);
void pop<T>([final T? result]) => navigator.pop<T>(result);
void popUntil(final bool Function(Route<dynamic>) predicate) =>
navigator.popUntil(predicate);
/// Push and remove everything else.
Future<T?> pushAndRemoveUntil<T>(final Route<T> route) =>
navigator.pushAndRemoveUntil(route, (final _) => false);
/// Push a named route and remove everything else.
Future<T?> pushNamedAndRemoveUntil<T>(
final String routeName, {
final Object? arguments,
}) => navigator.pushNamedAndRemoveUntil<T>(
routeName,
(final _) => false,
arguments: arguments,
);
/// Replace the current route with a new one.
Future<T?> pushReplacement<T>(final Route<T> newRoute) =>
navigator.pushReplacement(newRoute);
/// Push a named route and replace current
Future<T?> pushReplacementNamed<T extends Object?, TO extends Object?>(
final String routeName, {
final TO? result,
final Object? arguments,
}) => navigator.pushReplacementNamed<T, TO>(
routeName,
result: result,
arguments: arguments,
);
/// Pop to root (first route)
void popToRoot() =>
navigator.popUntil((final Route<dynamic> route) => route.isFirst);
/// Explicit return type for linter
bool get canPop => navigator.canPop();
/// Pop with safety check
void safePop<T>([final T? result]) {
if (canPop) navigator.pop<T>(result);
}
// ==== THEME & STYLING ====
ThemeData get theme => Theme.of(this);
TextTheme get textTheme => Theme.of(this).textTheme;
ColorScheme get colorScheme => Theme.of(this).colorScheme;
// Colors
Color get primaryColor => colorScheme.primary;
Color get secondaryColor => colorScheme.secondary;
Color get backgroundColor => colorScheme.surface;
Color get surfaceColor => colorScheme.surface;
Color get errorColor => colorScheme.error;
Color get onPrimaryColor => colorScheme.onPrimary;
Color get onSecondaryColor => colorScheme.onSecondary;
Color get onBackgroundColor => colorScheme.onSurface;
Color get onSurfaceColor => colorScheme.onSurface;
Color get onErrorColor => colorScheme.onError;
// Brightness
bool get isDarkMode => theme.brightness == Brightness.dark;
bool get isLightMode => !isDarkMode;
Brightness get brightness => theme.brightness;
// Text styles
TextStyle? get displayLarge => textTheme.displayLarge;
TextStyle? get displayMedium => textTheme.displayMedium;
TextStyle? get displaySmall => textTheme.displaySmall;
TextStyle? get headlineLarge => textTheme.headlineLarge;
TextStyle? get headlineMedium => textTheme.headlineMedium;
TextStyle? get headlineSmall => textTheme.headlineSmall;
TextStyle? get titleLarge => textTheme.titleLarge;
TextStyle? get titleMedium => textTheme.titleMedium;
TextStyle? get titleSmall => textTheme.titleSmall;
TextStyle? get bodyLarge => textTheme.bodyLarge;
TextStyle? get bodyMedium => textTheme.bodyMedium;
TextStyle? get bodySmall => textTheme.bodySmall;
TextStyle? get labelLarge => textTheme.labelLarge;
TextStyle? get labelMedium => textTheme.labelMedium;
TextStyle? get labelSmall => textTheme.labelSmall;
// ==== FOCUS & KEYBOARD ====
void hideKeyboard() => FocusScope.of(this).unfocus();
void showKeyboard() => FocusScope.of(this).requestFocus();
FocusScopeNode get focusScope => FocusScope.of(this);
bool get hasFocus => focusScope.hasFocus;
bool get hasChildFocus => focusScope.hasPrimaryFocus;
void nextFocus() => focusScope.nextFocus();
void previousFocus() => focusScope.previousFocus();
void unfocus() => focusScope.unfocus();
// ==== SCAFFOLD & MATERIAL ====
ScaffoldState get scaffold => Scaffold.of(this);
ScaffoldMessengerState get scaffoldMessenger => ScaffoldMessenger.of(this);
void openDrawer() => scaffold.openDrawer();
void openEndDrawer() => scaffold.openEndDrawer();
void closeDrawer() => scaffold.closeDrawer();
void closeEndDrawer() => scaffold.closeEndDrawer();
// SnackBar helpers
ScaffoldFeatureController<SnackBar, SnackBarClosedReason> showSnackBar(
final SnackBar snackBar,
) => scaffoldMessenger.showSnackBar(snackBar);
void showTextSnackBar(
final String text, {
final Duration? duration,
final SnackBarAction? action,
}) {
showSnackBar(
SnackBar(
content: Text(text),
duration: duration ?? const Duration(seconds: 4),
action: action,
),
);
}
void showErrorSnackBar(final String message) {
showSnackBar(SnackBar(content: Text(message), backgroundColor: errorColor));
}
void showSuccessSnackBar(final String message) {
showSnackBar(
SnackBar(
content: Text(message),
backgroundColor: Colors.green,
duration: const Duration(seconds: 3),
),
);
}
void hideCurrentSnackBar() => scaffoldMessenger.hideCurrentSnackBar();
void clearSnackBars() => scaffoldMessenger.clearSnackBars();
// ==== DIALOGS & MODALS ====
Future<T?> showCustomDialog<T>({
required final Widget Function(BuildContext) builder,
final bool barrierDismissible = true,
final Color? barrierColor,
final String? barrierLabel,
final bool useSafeArea = true,
}) {
return showDialog<T>(
context: this,
builder: builder,
barrierDismissible: barrierDismissible,
barrierColor: barrierColor,
barrierLabel: barrierLabel,
useSafeArea: useSafeArea,
);
}
Future<T?> showConfirmDialog<T>({
required final String title,
required final String content,
final String confirmText = 'OK',
final String cancelText = 'Cancel',
final bool barrierDismissible = true,
}) {
return showDialog<T>(
context: this,
barrierDismissible: barrierDismissible,
builder: (final BuildContext context) => AlertDialog(
title: Text(title),
content: Text(content),
actions: <Widget>[
TextButton(
onPressed: () => navigator.pop(false),
child: Text(cancelText),
),
TextButton(
onPressed: () => navigator.pop(true),
child: Text(confirmText),
),
],
),
);
}
Future<T?> showBottomSheetModal<T>({
required final Widget Function(BuildContext) builder,
final bool isScrollControlled = false,
final bool useRootNavigator = false,
final bool isDismissible = true,
final bool enableDrag = true,
final Color? backgroundColor,
final double? elevation,
}) {
return showModalBottomSheet<T>(
context: this,
builder: builder,
isScrollControlled: isScrollControlled,
useRootNavigator: useRootNavigator,
isDismissible: isDismissible,
enableDrag: enableDrag,
backgroundColor: backgroundColor,
elevation: elevation,
);
}
// ==== RESPONSIVE HELPERS ====
T responsive<T>({
required final T mobile,
final T? tablet,
final T? desktop,
}) {
if (isDesktop && desktop != null) return desktop;
if (isTablet && tablet != null) return tablet;
return mobile;
}
double responsiveValue({
required final double mobile,
final double? tablet,
final double? desktop,
}) {
if (isDesktop && desktop != null) return desktop;
if (isTablet && tablet != null) return tablet;
return mobile;
}
// Padding helpers
EdgeInsets get defaultPadding => const EdgeInsets.all(16.0);
EdgeInsets get smallPadding => const EdgeInsets.all(8.0);
EdgeInsets get largePadding => const EdgeInsets.all(24.0);
EdgeInsets get horizontalPadding =>
const EdgeInsets.symmetric(horizontal: 16.0);
EdgeInsets get verticalPadding => const EdgeInsets.symmetric(vertical: 16.0);
// ==== SYSTEM INTEGRATION ====
void hideSystemUI() {
SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersive);
}
void showSystemUI() {
SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
}
void setSystemUIOverlay({
final Color? statusBarColor,
final Brightness? statusBarBrightness,
final Brightness? statusBarIconBrightness,
final Color? systemNavigationBarColor,
final Brightness? systemNavigationBarIconBrightness,
}) {
SystemChrome.setSystemUIOverlayStyle(
SystemUiOverlayStyle(
statusBarColor: statusBarColor,
statusBarBrightness: statusBarBrightness,
statusBarIconBrightness: statusBarIconBrightness,
systemNavigationBarColor: systemNavigationBarColor,
systemNavigationBarIconBrightness: systemNavigationBarIconBrightness,
),
);
}
void vibrate() {
HapticFeedback.lightImpact();
}
void vibrateHeavy() {
HapticFeedback.heavyImpact();
}
void vibrateMedium() {
HapticFeedback.mediumImpact();
}
void vibrateSelection() {
HapticFeedback.selectionClick();
}
// ==== UTILITY METHODS ====
/// Get locale information
Locale get locale => Localizations.localeOf(this);
String get languageCode => locale.languageCode;
String? get countryCode => locale.countryCode;
/// Form state helper
FormState? get form => Form.maybeOf(this);
bool get hasForm => form != null;
bool validateForm() => form?.validate() ?? false;
void resetForm() => form?.reset();
void saveForm() => form?.save();
/// Get the nearest widget of type T
T? findAncestor<T extends Widget>() => findAncestorWidgetOfExactType<T>();
/// Check if widget is mounted
bool get isMounted => mounted;
/// Get render object
RenderObject? get renderObject => findRenderObject();
/// Media query shorthand
MediaQueryData get mediaQuery => MediaQuery.of(this);
/// Get text direction
TextDirection get textDirection => Directionality.of(this);
bool get isRTL => textDirection == TextDirection.rtl;
bool get isLTR => !isRTL;
/// Platform helpers
TargetPlatform get platform => theme.platform;
bool get isAndroid => platform == TargetPlatform.android;
bool get isIOS => platform == TargetPlatform.iOS;
bool get isWeb =>
platform == TargetPlatform.linux ||
platform == TargetPlatform.macOS ||
platform == TargetPlatform.windows;
}