Flutter带BottomNavigationBar页面无法在模拟器运行:类型不匹配错误问题
解决Flutter路由中
_MainPage无法赋值给Widget的问题 嘿,这个问题其实是个常见的新手小坑——你搞混了StatefulWidget本身和它对应的State子类啦!
错误原因分析
你定义的_MainPage是MyApp这个StatefulWidget对应的State子类,它的类型是State<MyApp>,并不是Widget类型。而Flutter路由的builder函数要求返回一个Widget对象,所以直接在路由里写_MainPage()就会触发类型不匹配的错误:
Error: A value of type '_MainPage' can't be assigned to a variable of type 'Widget'
快速修复方案
你只需要把路由配置里的_MainPage()换成MyApp()就可以了,因为MyApp才是真正的StatefulWidget(属于Widget类型):
routes: { '/LogIn': (BuildContext context) => LogInPage(), '/QRScan': (BuildContext context) => QRCodePage(), '/LogIn/Registr': (BuildContext context) => RegistrPage(), '/Main': (BuildContext context) => MyApp(), // 这里改成MyApp() },
更规范的代码优化(推荐)
不过从命名规范来说,MyApp这个名字不太合适,因为它其实是你的主页面,不是整个App的根组件。建议你调整命名,让代码更清晰:
- 把
MyApp改名为MainPage(作为主页面的StatefulWidget) - 把
_MainPage改名为_MainPageState(符合Flutter State类的命名习惯:Widget名+State)
调整后的完整代码如下:
import 'package:flutter/material.dart'; class LogInPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text("Log In")), body: Center( child: Row( mainAxisAlignment: MainAxisAlignment.center, // 让按钮居中显示 children: <Widget>[ RaisedButton( onPressed: () { Navigator.pushNamed(context, '/Main'); }, child: Text("Log In")), SizedBox(width: 16), // 按钮之间增加间距 RaisedButton( onPressed: () { Navigator.pushNamed(context, '/LogIn/Registr'); }, child: Text("Registration")), ], )), ); } } class QRCodePage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text("QR Scan")), body: Center( child: RaisedButton( onPressed: () { Navigator.pushNamed(context, '/Main'); }, child: Text("Scan")), )); } } class RegistrPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text("Registration")), body: Center( child: RaisedButton( onPressed: () { Navigator.pushNamed(context, '/Main'); }, child: Text("Log In")), )); } } // 调整命名,符合Flutter代码规范 class MainPage extends StatefulWidget { @override _MainPageState createState() => _MainPageState(); } class _MainPageState extends State<MainPage> { int _currentIndex = 0; @override Widget build(BuildContext context) { return new Scaffold( appBar: AppBar(title: Text("Main")), body: Container(), bottomNavigationBar: BottomNavigationBar( items: [ BottomNavigationBarItem( icon: Icon(Icons.home), backgroundColor: Colors.blue), BottomNavigationBarItem( icon: Icon(Icons.qr_code), backgroundColor: Colors.blue), BottomNavigationBarItem( icon: Icon(Icons.restaurant_menu), backgroundColor: Colors.blue), BottomNavigationBarItem( icon: Icon(Icons.shopping_basket), backgroundColor: Colors.blue), ], onTap: (index){ setState(() { _currentIndex = index; }); }, ), ); } } void main() { runApp(MaterialApp( initialRoute: '/LogIn', routes: { '/LogIn': (BuildContext context) => LogInPage(), '/QRScan': (BuildContext context) => QRCodePage(), '/LogIn/Registr': (BuildContext context) => RegistrPage(), '/Main': (BuildContext context) => MainPage(), // 使用调整后的MainPage }, )); }
另外我还顺手加了两个小优化:给LogInPage的Row加了mainAxisAlignment: MainAxisAlignment.center让按钮居中,加了SizedBox(width: 16)让两个按钮之间有间距,视觉体验更好~
内容的提问来源于stack exchange,提问作者Максим Мазепа
相关产品推荐
相关产品推荐

