Flutterを学習中です。
NavigationWidgetを用いて画面遷移を実装中にエラーが発生し、詰まった部分があった為
解決策を記載いたします。
####環境
Mac OS
Flutter1.20.4(channel stable)
VS code
####実装したいこと
作った料理のレシピをストックできるアプリを開発したく、
ホーム画面のボタンをクリックすると、レシピ追加画面に移行するように
画面遷移を実装したい。
####エラー文
大量のエラー・・・
I/flutter (23646): ══╡ EXCEPTION CAUGHT BY GESTURE ╞═══════════════════════════════════════════════════════════════════
I/flutter (23646): The following assertion was thrown while handling a gesture:
I/flutter (23646): Navigator operation requested with a context that does not include a Navigator.
I/flutter (23646): The context used to push or pop routes from the Navigator must be that of a widget that is a
I/flutter (23646): descendant of a Navigator widget.
I/flutter (23646):
I/flutter (23646): When the exception was thrown, this was the stack:
I/flutter (23646): #0 Navigator.of.<anonymous closure> (package:flutter/src/widgets/navigator.dart:2190:9)
I/flutter (23646): #1 Navigator.of (package:flutter/src/widgets/navigator.dart:2197:6)
I/flutter (23646): #2 Navigator.push (package:flutter/src/widgets/navigator.dart:1801:22)
I/flutter (23646): #3 CookApp.build.<anonymous closure> (package:mytodoapp/main.dart:27:29)
I/flutter (23646): #4 _InkResponseState._handleTap (package:flutter/src/material/ink_well.dart:992:19)
I/flutter (23646): #5 _InkResponseState.build.<anonymous closure> (package:flutter/src/material/ink_well.dart:1098:38)
I/flutter (23646): #6 GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:184:24)
I/flutter (23646): #7 TapGestureRecognizer.handleTapUp (package:flutter/src/gestures/tap.dart:524:11)
I/flutter (23646): #8 BaseTapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:284:5)
I/flutter (23646): #9 BaseTapGestureRecognizer.handlePrimaryPointer (package:flutter/src/gestures/tap.dart:219:7)
I/flutter (23646): #10 PrimaryPointerGestureRecognizer.handleEvent (package:flutter/src/gestures/recognizer.dart:477:9)
I/flutter (23646): #11 PointerRouter._dispatch (package:flutter/src/gestures/pointer_router.dart:78:12)
I/flutter (23646): #12 PointerRouter._dispatchEventToRoutes.<anonymous closure> (package:flutter/src/gestures/pointer_router.dart:124:9)
I/flutter (23646): #13 _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:377:8)
I/flutter (23646): #14 PointerRouter._dispatchEventToRoutes (package:flutter/src/gestures/pointer_router.dart:122:18)
I/flutter (23646): #15 PointerRouter.route (package:flutter/src/gestures/pointer_router.dart:108:7)
I/flutter (23646): #16 GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:220:19)
I/flutter (23646): #17 GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:200:22)
I/flutter (23646): #18 GestureBinding._handlePointerEvent (package:flutter/src/gestures/binding.dart:158:7)
I/flutter (23646): #19 GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:104:7)
I/flutter (23646): #20 GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:88:7)
I/flutter (23646): #24 _invoke1 (dart:ui/hooks.dart:267:10)
I/flutter (23646): #25 _dispatchPointerDataPacket (dart:ui/hooks.dart:176:5)
I/flutter (23646): (elided 3 frames from dart:async)
I/flutter (23646):
I/flutter (23646): Handler: "onTap"
I/flutter (23646): Recognizer:
I/flutter (23646): TapGestureRecognizer#aaa22
I/flutter (23646): ════════════════════════════════════════════════════════════════════════════════════════════════════
I/flutter (23646): Another exception was thrown: Navigator operation requested with a context that does not include a Navigator.
I/flutter (23646): Another exception was thrown: Navigator operation requested with a context that does not include a Navigator.
####エラーが発生した際のコード文
main.dart(遷移元)
import 'package:flutter/material.dart';
import 'package:mytodoapp/add_recipe_page.dart';
void main() => runApp(CookApp());
class CookApp extends StatelessWidget {
var titleText = 'cookapp';
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
leading: Icon(Icons.menu),
title: Text('レシピ一覧'),
),
body: Container(
child: Center(
child: Column(children: <Widget>[
Text(titleText),
RaisedButton(
child: Text("Button"),
color: Colors.orange,
textColor: Colors.white,
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => AddRecipe()),
);
},
),
]),
),
),
),
);
}
}
add_recipe.dart(遷移先)
import 'package:flutter/material.dart';
void main() => runApp(AddRecipe());
class AddRecipe extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('レシピ追加画面'),
leading: Icon(Icons.add_alert),
),
body: Container(
child: Center(
child: Text('レシピ追加'),
),
),
),
);
}
}
####エラーの原因
エラーで画面遷移ができなかった理由としては、
【MaterialAppWidgetの理解】にありました。
上記コードではMaterialAppを遷移元のページと遷移先のページの2箇所に記載していますが、
アプリ内で一箇所のみに記載すべきとのことです。
また、MaterialAppはNavigatorとの間にはワンクッション空けて記載する方が好ましい様です。
(return MaterialAppのかっこの中にはNavigatorを書かない)
以上のことを踏まえて、コードを修正しました。
main.dart(遷移元)
//MaterialAppを返すクラスを別途追加
class CookApp extends StatelessWidget {
var titleText = 'cookapp';
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Home(titleText: titleText),
);
}
}
class Home extends StatelessWidget {
final String titleText;
const Home({this.titleText});
@override
Widget build(BuildContext context) {
//Scaffoldm内に Navigatorを配置
return Scaffold(
appBar: AppBar(
leading: Icon(Icons.menu),
title: Text('レシピ一覧'),
),
body: Container(
child: Center(
child: Column(children: <Widget>[
Text(titleText),
RaisedButton(
child: Text("Button"),
color: Colors.orange,
textColor: Colors.white,
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => AddRecipe()),
);
},
),
]),
),
),
);
}
}
無事に画面遷移が成功することが確認できました!