Following the tutorials at 1 and 2 I am trying to set up localization for my flutter app. That works fine and I can use I18n.of(context).trans(<key>) to access translated strings in my widgets.
However I don't know how to access the translations in the MaterialApp top widget:
import 'package:flutter/material.dart';
import 'package:flutter_app/i18n/i18n.dart';
import 'package:flutter_app/views/menu.dart';
import 'package:flutter\_localizations/flutter\_localizations.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
supportedLocales: [
const Locale('en', 'US'),
const Locale('de', 'DE'),
],
localizationsDelegates: [
const I18nDelegate(),
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate
],
title: I18n.of(context).trans('title'), //FIXME doesn't work
home: new Menu(),
);
}
}
For above code I get an exception because I18n.of(context) returns null. What am I missing?
You should use onGenerateTitle instead of title field :
MaterialApp(
...
onGenerateTitle: (context) => I18n.of(context).trans('title'),
)
Related
I spent so much time for this. I am using navigator key for routing. In android I have no problem but in IOS navigator key is coming null in runtime. I have no idea what is the problem. In Android there is no problem. Working very well. Any idea why is it happening?
main.dart
void main() async {
// sets up the global service locator
setupServices();
CompanyErrorHandler(
child: EasyLocalization(
supportedLocales: const [
Locale('en', 'US'),
],
path: 'assets/translations',
child: const GlobalProvider(child: Company()),
));
}
Company.dart
class Company extends StatelessWidget {
const Company({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
final themeBloc = context.watch<ThemeBloc>();
final systemBrightness = context.watch<Brightness>();
return MaterialApp(
title: 'company',
debugShowCheckedModeBanner: false,
theme: themeBloc.state.lightCompanyTheme.themeData,
darkTheme: themeBloc.state.darkCompanyTheme.themeData,
themeMode: systemBrightness == Brightness.light
? ThemeMode.light
: ThemeMode.dark,
color: Colors.black,
localizationsDelegates: context.localizationDelegates,
locale: context.locale,
supportedLocales: context.supportedLocales,
navigatorKey: app<CompanyNavigator>().key,
onGenerateRoute: onGenerateRoute,
navigatorObservers: [
companyRouteObserver,
],
home: const SplashScreen(),
builder: (_, child) => _ContentBuilder(child: child),
);
}
}
Company Navigator class
final companyRouteObserver = RouteObserver<ModalRoute<dynamic>>();
class CompanyNavigator {
final GlobalKey<NavigatorState> key = GlobalKey<NavigatorState>();
NavigatorState get state => key.currentState!;
}
CurrentState coming null for IOS in here.
I'm receiving this error when running my flutter web, unexpected null value and when I look at my terminal it directs me to my main.dart where I'm being told that the error is coming from my Material widget.
Whereas I'm not understanding what's causing the error.
The following TypeErrorImpl was thrown building Builder:
Unexpected null value.
The relevant error-causing widget was:
Material Material
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:bwamnewsappadmin/pages/home.dart';
import 'package:bwamnewsappadmin/pages/sign_in.dart';
import 'package:provider/provider.dart';
import 'blocs/admin_bloc.dart';
import 'blocs/notification_bloc.dart';
import 'blocs/comment_bloc.dart';
void main(){
runApp(MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MultiProvider(providers: [
ChangeNotifierProvider<AdminBloc>(create: (context) => AdminBloc()),
ChangeNotifierProvider<CommentBloc>(create: (context) => CommentBloc()),
ChangeNotifierProvider<NotificationBloc>(create: (context) => NotificationBloc())
],
child: MaterialApp(
debugShowCheckedModeBanner: false,
scrollBehavior: TouchAndMouseScrollBehavior(),
theme: ThemeData(
scaffoldBackgroundColor: Colors.white,
textTheme: GoogleFonts.poppinsTextTheme(),
appBarTheme: AppBarTheme(
color: Colors.white,
titleTextStyle: GoogleFonts.poppins(
color: Colors.grey[900],fontWeight: FontWeight.w600, fontSize: 18
),
elevation: 0,
actionsIconTheme: IconThemeData(
color: Colors.grey[900],
),
iconTheme: IconThemeData(
color: Colors.grey[900]
)
),
),
home: MyApp1(),
),
);
}
}
class MyApp1 extends StatelessWidget {
const MyApp1({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
final ab = context.watch<AdminBloc>();
return ab.isSignedIn == false ? SignInPage() : HomePage();
}
}
class TouchAndMouseScrollBehavior extends MaterialScrollBehavior {
// Override behavior methods and getters like dragDevices
#override
Set<PointerDeviceKind> get dragDevices => {
PointerDeviceKind.touch,
PointerDeviceKind.mouse,
// etc.
};
}
I am creating an app using Flutter.
On iOS however (you can also test it on Android), dark theme is not applied.
Using Android widgets, it is working fine tho.
How can I make the Cupertino widgets using the dark theme? Especially for the popups.
I am using Flutter 1.9.1+hotfix6
E.g. the Cupertino "ActionSheet":
import 'package:flutter/material.dart';
import 'home.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData.dark(),
darkTheme: ThemeData.dark(),
home: Home(),
);
}
}
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class Home extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Center(
child: RaisedButton(
child: Text('test'),
onPressed: () {
Widget secondaryButton, confirmButton, popup;
secondaryButton = CupertinoActionSheetAction(
child: Text('secundary'),
onPressed: () {},
);
confirmButton = CupertinoActionSheetAction(
child: Text('test'),
onPressed: () {},
);
popup = CupertinoActionSheet(
title: Text('Title'),
message: Text('Content'),
cancelButton: secondaryButton,
actions: [confirmButton],
);
showCupertinoModalPopup(
context: context, builder: (context) => popup);
},
),
);
}
}
Screenshot:
Check this repo, you can create platform specific layouts only using a single widget that does all the platform specific boilerplate for you.
Also have support for dark mode, at least in iOS.
I am building a demo app to test using localization strings.
I get the following error:
I/flutter (21588): The following NoSuchMethodError was thrown building MainApp(dirty):
I/flutter (21588): The getter 'title' was called on null.
I/flutter (21588): Receiver: null
I/flutter (21588): Tried calling: title
I am not sure why I am getting this error. I have followed the indications on flutter documentation.
I have following Localization Class:
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'dart:async';
import 'package:bet_master/l10n/messages_all.dart';
class AppLocalizations {
static Future<AppLocalizations> load(Locale locale) {
final String name =
locale.countryCode.isEmpty ? locale.languageCode : locale.toString();
final localeName = Intl.canonicalizedLocale(name);
return initializeMessages(localeName).then((bool _) {
Intl.defaultLocale = localeName;
return AppLocalizations();
});
}
static AppLocalizations of(BuildContext context) {
return Localizations.of<AppLocalizations>(context, AppLocalizations);
}
String get title {
return Intl.message(
'Bet Master',
name: 'title',
desc: 'App Title'
);
}
String get search {
return Intl.message(
'Search',
name: 'search',
desc : ''
);
}
}
class AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> {
const AppLocalizationsDelegate();
#override
bool isSupported(Locale locale) {
return ['en', 'es', 'fr'].contains(locale.languageCode);
}
#override
Future<AppLocalizations> load(Locale locale) {
return AppLocalizations.load(locale);
}
#override
bool shouldReload(AppLocalizationsDelegate old) {
return false;
}
}
For the Home Widget I am only setting the title
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:bet_master/localization/localizations.dart';
void main() {
runApp(MainApp());
}
class MainApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
// TODO: implement build
return MaterialApp(
localizationsDelegates: [
const AppLocalizationsDelegate(),
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate
],
supportedLocales: [
const Locale('en', ''),
const Locale('es', ''),
const Locale('fr', ''),
],
home: Scaffold(
appBar: AppBar(
title: Text(AppLocalizations.of(context).title),
),
),
);
}
}
At the end the issue seems related to Localization not being available, I moved the "home" code to another widget and solved the issue.
Widget build(BuildContext context) {
return new MaterialApp(
localizationsDelegates: [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
_appLocalizationsDelegate,
],
supportedLocales: [
Locale('en'),
Locale('es'),
],
locale: _appLocalizationsDelegate.overridenLocale,
onGenerateTitle: (BuildContext context) => AppLocalizations.of(context).title,
home: Home()
);
}
}
class Home extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: AppBar(
title: Text(AppLocalizations.of(context).title),
),
body: Column(children: <Widget>[
Text('hola'),
],)
);
}
}
I need to research still why is this needed, but at least it works now.
I had the same error, but my problem was that I was using two nested
MaterialApp() widgets.
It was causing that this line retuns null:
return Localizations.of<AppLocalizations>(context, AppLocalizations);
I replaced the nested MarerialApp(The child) widget with a Scaffold and It worked.
Hope It helps someone!
I want to use a Row to display some Text then the LinearProgressIndicator in a row, using this code:
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget { #override Widget build(BuildContext context) {
return MaterialApp(
title: 'MaterialApp',
home: Scaffold(
body: SafeArea(child: Row(
children: <Widget>[
Text('Start row'),
LinearProgressIndicator(),
],
),)),
); } }
The problem is nothing is displayed when I wrap the Text and the LinearProgressIndicator in a Row.
I can only get the Row to display the Text when I delete LinearProgressIndicator. And I can only get the LinearProgressIndicator to display when the Row is not used like this:
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'MaterialApp',
home: Scaffold(
body: SafeArea(child: LinearProgressIndicator(),)),
);
}
}
This is what the app looks like without the Row.
You should set a width for LinearProgressIndicator widget when it's inside a row widget. the error in console explained it very clear:
BoxConstraints forces an infinite width.
These invalid constraints were provided to RenderCustomPaint's layout() function by the following
function, which probably computed the invalid constraints in question:
Every unbounded widget should be wrapped inside widgets like Expanded or Flexible:
In this case:
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'MaterialApp',
home: Scaffold(
body: SafeArea(
child: Row(
children: <Widget>[
Center( // this widget is not nessesary
child: Text('Some text'),
),
Expanded(child: LinearProgressIndicator()),
],
),
)),
);
}
}
There is also a discussion here related to this matter.