build method
Widget
build(
- BuildContext context,
- WidgetRef ref,
- Locale state,
- LanguageSwitcherNotifier notifier,
- List<
LocaleInfo> supportedLocales,
override
Build method that concrete implementations must override.
This method receives all necessary data for building language switcher UI:
context
: The build context for accessing theme and navigationref
: WidgetRef for accessing Riverpod providersstate
: Current locale state from the language switcher providernotifier
: LanguageSwitcherNotifier for changing localessupportedLocales
: List of all supported locales from app configuration
Example implementation:
@override
Widget build(
BuildContext context,
WidgetRef ref,
Locale state,
LanguageSwitcherNotifier notifier,
List<LocaleInfo> supportedLocales,
) {
return Column(
children: supportedLocales.map((localeInfo) {
return RadioListTile<Locale>(
value: localeInfo.locale,
groupValue: state,
title: Text(localeInfo.displayName),
onChanged: (locale) {
if (locale != null) notifier.changeLocale(locale);
},
);
}).toList(),
);
}
Implementation
@override
Widget build(
BuildContext context,
WidgetRef ref,
Locale state,
LanguageSwitcherNotifier notifier,
List<LocaleInfo> supportedLocales,
) {
final currentLocale = state;
return Container(
decoration: const BoxDecoration(
borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
margin: const EdgeInsets.only(top: 12),
width: 40,
height: 4,
decoration: BoxDecoration(
color: Theme.of(context).dividerColor,
borderRadius: BorderRadius.circular(2),
),
),
// Header
Padding(
padding: const EdgeInsets.all(20),
child: Row(
children: [
Icon(
Icons.language,
color: Theme.of(context).colorScheme.primary,
),
const SizedBox(width: 12),
Text(
context.jetI10n.changeLanguage,
style: Theme.of(context).textTheme.titleLarge?.copyWith(
fontWeight: FontWeight.w600,
),
),
const Spacer(),
IconButton(
onPressed: () {
HapticFeedback.lightImpact();
Navigator.of(context).pop();
},
icon: const Icon(Icons.close),
style: IconButton.styleFrom(
backgroundColor: Theme.of(
context,
).colorScheme.surfaceContainerHighest,
),
),
],
),
),
// Locale options
ListView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: supportedLocales.length,
itemBuilder: (context, index) {
final localeInfo = supportedLocales[index];
final isSelected =
currentLocale.languageCode == localeInfo.locale.languageCode;
return ListTile(
contentPadding: const EdgeInsets.symmetric(
horizontal: 20,
vertical: 4,
),
leading: Container(
width: 40,
height: 40,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: isSelected
? Theme.of(context).colorScheme.primary
: Theme.of(context).colorScheme.surfaceContainerHighest,
),
child: Center(
child: Text(
localeInfo.locale.languageCode.toUpperCase(),
style: TextStyle(
color: isSelected
? Theme.of(context).colorScheme.onPrimary
: Theme.of(context).colorScheme.onSurfaceVariant,
fontWeight: FontWeight.bold,
fontSize: 12,
),
),
),
),
title: Text(
localeInfo.displayName,
style: Theme.of(context).textTheme.bodyLarge?.copyWith(
fontWeight: isSelected
? FontWeight.w600
: FontWeight.normal,
),
),
trailing: isSelected
? Icon(
Icons.check_circle,
color: Theme.of(context).colorScheme.primary,
)
: null,
onTap: () async {
if (!isSelected) {
HapticFeedback.lightImpact();
await notifier.changeLocale(localeInfo.locale);
}
if (context.mounted) {
Navigator.of(context).pop();
}
},
);
},
),
// Bottom padding
const SizedBox(height: 20),
],
),
);
}