showBottomModal static method
Future<void>
showBottomModal(
- BuildContext context, {
- double? height,
- Color? backgroundColor,
- Color? handleColor,
- Color? selectedColor,
- TextStyle? titleStyle,
- TextStyle? languageTextStyle,
- BorderRadius? borderRadius,
Show a bottom modal to switch languages
Implementation
static Future<void> showBottomModal(
BuildContext context, {
double? height,
Color? backgroundColor,
Color? handleColor,
Color? selectedColor,
TextStyle? titleStyle,
TextStyle? languageTextStyle,
BorderRadius? borderRadius,
}) async {
// Capture navigator state before async operations
final navigator = Navigator.of(context);
List<Map<String, String>> list = await getLanguageList();
Map<String, dynamic>? currentLang = await currentLanguage();
if (!context.mounted) return;
final isDark = Theme.of(context).brightness == Brightness.dark;
final screenHeight = MediaQuery.of(context).size.height;
showModalBottomSheet(
context: context,
isScrollControlled: true,
backgroundColor: Colors.transparent,
builder: (BuildContext modalContext) {
final effectiveBackgroundColor =
backgroundColor ??
(isDark ? const Color(0xFF1C1C1E) : Colors.white);
final effectiveHandleColor =
handleColor ??
(isDark ? Colors.grey.shade600 : Colors.grey.shade300);
final effectiveSelectedColor =
selectedColor ??
(isDark ? const Color(0xFF2C2C2E) : const Color(0xFFF2F2F7));
final effectiveBorderRadius =
borderRadius ??
const BorderRadius.vertical(top: Radius.circular(20));
return Container(
constraints: BoxConstraints(maxHeight: height ?? screenHeight * 0.6),
decoration: BoxDecoration(
color: effectiveBackgroundColor,
borderRadius: effectiveBorderRadius,
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.15),
blurRadius: 20,
offset: const Offset(0, -5),
),
],
),
child: SafeArea(
top: false,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
// Drag handle
Padding(
padding: const EdgeInsets.only(top: 12, bottom: 8),
child: Container(
width: 36,
height: 5,
decoration: BoxDecoration(
color: effectiveHandleColor,
borderRadius: BorderRadius.circular(2.5),
),
),
),
// Title
Padding(
padding: const EdgeInsets.fromLTRB(24, 8, 24, 16),
child: Text(
"nylo.language_switcher.title".tr(),
style:
titleStyle ??
TextStyle(
fontSize: 20,
fontWeight: FontWeight.w600,
color: isDark ? Colors.white : Colors.black,
letterSpacing: -0.5,
),
),
),
// Divider
Divider(
height: 1,
thickness: 0.5,
color: isDark ? Colors.grey.shade800 : Colors.grey.shade200,
),
// Language list
Flexible(
child: ListView.builder(
padding: const EdgeInsets.symmetric(vertical: 8),
shrinkWrap: true,
itemCount: list.length,
itemBuilder: (context, index) {
final meta = list[index];
final data = meta.entries.firstOrNull;
if (data == null) return const SizedBox.shrink();
final isSelected =
currentLang != null &&
currentLang.entries.isNotEmpty &&
data.key == currentLang.entries.first.key;
final flagEmoji = getFlagEmoji(data.key);
return _LanguageListItem(
languageName: data.value,
localeCode: data.key,
flagEmoji: flagEmoji,
isSelected: isSelected,
selectedColor: effectiveSelectedColor,
textStyle: languageTextStyle,
isDark: isDark,
onTap: () async {
await NyLocalization.instance.setLanguage(
modalContext,
language: data.key,
);
// store the language
await storeLanguage(object: {data.key: data.value});
updateState(
state,
data: {"action": "refresh-page", "data": {}},
);
navigator.pop();
},
);
},
),
),
],
),
),
);
},
);
}