Contents
やりたいことと課題
ScreenUtilInit
の導入をするために、main()
にコードを追記したい。
導入前の時点のmain()
とMyApp
(一部割愛)。なお、MyText
、MyTheme
、MySize
はスタイルをまとめて定義し呼び出しているものです。
Dart
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';
import 'package:electricorange/domein/00_user/state/initial_route_provider.dart';
import 'package:electricorange/infrastructure/remote_config/remote_config.dart';
import 'package:electricorange/presentation/router/main_router/router.dart';
import 'package:electricorange/presentation/router/main_router/routes.dart';
import 'package:electricorange/presentation/styles/sizes.dart';
import 'package:electricorange/presentation/styles/texts.dart';
import 'package:electricorange/presentation/styles/theme.dart';
import 'package:electricorange/firebase_options.dart';
void main() async {
runZonedGuarded<Future<void>>(
() async {
// Firebaseの初期化
WidgetsFlutterBinding.ensureInitialized();
await MobileAds.instance.initialize();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
await RemoteConfigService().setRemoteConfig();
// 画面の向き
await SystemChrome.setPreferredOrientations([
// 縦向き
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,
]);
// Flutterフレームワーク内でスローされたすべてのエラーを自動的にキャッチ
FlutterError.onError =
FirebaseCrashlytics.instance.recordFlutterFatalError;
runApp(const ProviderScope(child: MyApp()));
},
// Flutterフレームワーク内でキャッチされないエラー
(error, stack) async => await FirebaseCrashlytics.instance.recordError(
error,
stack,
fatal: true,
),
);
}
class MyApp extends ConsumerWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
// 割愛 initialLocation(ユーザーのログイン状態や初回起動かによって起動画面を出しわけ)
// 割愛 router(Providerで受け取る形にして別の場所で定義)
final app = MaterialApp.router(
routeInformationProvider: router.routeInformationProvider,
routeInformationParser: router.routeInformationParser,
routerDelegate: router.routerDelegate,
localizationsDelegates: const [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
theme: ThemeData(
useMaterial3: true,
fontFamily: 'MPLUS1p',
colorSchemeSeed: MyTheme.green,
scaffoldBackgroundColor: MyTheme.background,
navigationBarTheme: NavigationBarThemeData(
backgroundColor: MyTheme.onGreen,
indicatorColor: MyTheme.green,
surfaceTintColor: MyTheme.grey,
height: MySize.navigationBarHeight,
iconTheme: WidgetStateProperty.resolveWith((states) {
return IconThemeData(size: MySize.navigationIconSize);
}),
labelTextStyle: WidgetStateProperty.resolveWith((states) {
return MyText.navi;
}),
),
pageTransitionsTheme: const PageTransitionsTheme(
builders: <TargetPlatform, PageTransitionsBuilder>{
TargetPlatform.android: CupertinoPageTransitionsBuilder(), // iOS風
TargetPlatform.iOS: CupertinoPageTransitionsBuilder(),
},
),
),
supportedLocales: const [
// Locale("en"),
Locale("ja"),
],
debugShowCheckedModeBanner: false, // タグ非表示
);
return MediaQuery(
data: MediaQuery.of(context).copyWith(
textScaler: TextScaler.linear(1),
boldText: false,
), // 文字サイズを固定
child: app,
);
}
}
すでにmain()
とMyApp
では以下を実行している中、てんこ盛り状態のどこに導入すれば良いのかの備忘です。
- Firebaseを初期化して
- RemoteConfigを初期化して
- Crashlyticsを設定して
- 画面の向きを固定して
- 文字サイズを指定して
- ProviderScopeで囲んで
- ・・・

サンプルコードでの実装記事が多かったため、実際のコードではどこに入れれば良いかわからなかったので、順番に挿入してみたよ
まずは結論。これで解決
Dart
// 追加
import 'package:flutter_screenutil/flutter_screenutil.dart';
void main() async {
// 変更なし
}
class MyApp extends ConsumerWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
return ScreenUtilInit(
designSize: const Size(411, 890), // 基準サイズ
minTextAdapt: true, // テキストサイズの適応を有効化
splitScreenMode: true, // マルチウィンドウ対応
builder: (context, child) {
return MaterialApp.router(
// 割愛
builder: (context, child) => MediaQuery(
data: MediaQuery.of(context).copyWith(
textScaler: TextScaler.linear(1),
boldText: false,
), // 文字サイズを固定
child: child!,
),
);
},
);
}
}
以下別パターン
原因がよくわかっていなくて申し訳ないのですが、変更した瞬間はどれも動いたためそのうちの一つでしばらくUIテストをしていたのですが、突然キーボードがクラッシュする不具合に悩まされ、結果的にはScreenUtilInit
が原因でした。
詳細はこちら→https://hami030.com/devlog/flutter-error-textfield/
以下のいずれも一時的には動きますが、遅れて不具合が起こる可能性はなきにしもあらず。

よくわかっていないのでとっても怖い。
1. とりあえずrunApp
に書いてみる
とりあえずrunApp
に書いている記事が多いので記載。動く。
Dart
runApp(
ScreenUtilInit(
designSize: Size(411, 890),
builder: (BuildContext context, Widget? widget) => const ProviderScope(child: MyApp()),
),
);
次にこれ。一旦は動いたのでしばらくこの実装にしていたのだが、少しして発生したキーボードクラッシュエラーの原因がこれでした。ので結果的にはこれはNG。
Dart
runApp(
ProviderScope(
child: ScreenUtilInit(
designSize: Size(411, 890),
builder: (context, child) {
return child!;
},
child: MyApp(),
),
),
);
2. MyApp
に書いてみる
runApp
は戻して・・・
Dart
runApp(const ProviderScope(child: MyApp()));
MyApp
で呼び出してみます。どっちでも動く。
Dart
return ScreenUtilInit(
designSize: Size(411, 890),
builder: (context, child) {
return MediaQuery(
data: MediaQuery.of(context).copyWith(
textScaler: TextScaler.linear(1),
boldText: false,
), // 文字サイズを固定
child: app,
);
},
);
Dart
return MediaQuery(
data: MediaQuery.of(context).copyWith(
textScaler: TextScaler.linear(1),
boldText: false,
), // 文字サイズを固定
child: ScreenUtilInit(
designSize: Size(411, 890),
builder: (context, child) => app,
),
);
コメント