import 'dart:ui'; import 'package:flutter/cupertino.dart'; import 'package:flutter/services.dart'; import 'package:get/get.dart'; /// Standard iOS navigation bar height without the status bar. /// /// This height is constant and independent of accessibility as it is in iOS. const double _kNavBarPersistentHeight = kMinInteractiveDimensionCupertino; const Color _kDefaultNavBarBorderColor = Color(0x4D000000); const Border _kDefaultNavBarBorder = Border( top: BorderSide( color: _kDefaultNavBarBorderColor, width: 0.0, // 0.0 means one physical pixel ), ); /// Returns `child` wrapped with background and a bottom border if background color /// is opaque. Otherwise, also blur with [BackdropFilter]. /// /// When `updateSystemUiOverlay` is true, the nav bar will update the OS /// status bar's color theme based on the background color of the nav bar. Widget _wrapWithBackground({ Border? border, required Color backgroundColor, Brightness? brightness, required Widget child, bool updateSystemUiOverlay = true, }) { Widget result = child; if (updateSystemUiOverlay) { final bool isDark = backgroundColor.computeLuminance() < 0.179; final Brightness newBrightness = brightness ?? (isDark ? Brightness.dark : Brightness.light); final SystemUiOverlayStyle overlayStyle; switch (newBrightness) { case Brightness.dark: overlayStyle = SystemUiOverlayStyle.light; break; case Brightness.light: overlayStyle = SystemUiOverlayStyle.dark; break; } /*result = AnnotatedRegion( value: overlayStyle, child: result, );*/ } final DecoratedBox childWithBackground = DecoratedBox( decoration: BoxDecoration( border: border, color: backgroundColor, ), child: result, ); if (backgroundColor.alpha == 0xFF) { return childWithBackground; } return ClipRect( child: BackdropFilter( filter: ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0), child: childWithBackground, ), ); } class BottomNavigationBar extends StatefulWidget implements ObstructingPreferredSizeWidget { final Widget child; final Color? backgroundColor; final Brightness? brightness; final Border? border; const BottomNavigationBar({ super.key, required this.child, this.backgroundColor, this.brightness, this.border = _kDefaultNavBarBorder, }); @override bool shouldFullyObstruct(BuildContext context) { final Color backgroundColor = CupertinoDynamicColor.maybeResolve(this.backgroundColor, context) ?? CupertinoTheme.of(context).barBackgroundColor; return backgroundColor.alpha == 0xFF; } @override Size get preferredSize { double scaleFactor = MediaQuery.of(Get.context!).textScaleFactor; return Size.fromHeight(_kNavBarPersistentHeight * scaleFactor); } @override State createState() => _BottomNavigationBarState(); } class _BottomNavigationBarState extends State { @override Widget build(BuildContext context) { final Color backgroundColor = CupertinoDynamicColor.maybeResolve(widget.backgroundColor, context) ?? CupertinoTheme.of(context).barBackgroundColor; final scaleFactor = MediaQuery.of(context).textScaleFactor; return _wrapWithBackground( border: widget.border, backgroundColor: backgroundColor, brightness: widget.brightness, child: DefaultTextStyle( style: CupertinoTheme.of(context).textTheme.textStyle, child: SizedBox( height: (_kNavBarPersistentHeight * scaleFactor) + MediaQuery.of(context).padding.bottom, child: SafeArea( top: false, child: widget.child, ), ), ), ); } }