You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

132 lines
3.7 KiB
Dart

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<SystemUiOverlayStyle>(
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<StatefulWidget> createState() => _BottomNavigationBarState();
}
class _BottomNavigationBarState extends State<BottomNavigationBar> {
@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,
),
),
),
);
}
}