【发布时间】:2021-11-11 11:33:30
【问题描述】:
尝试导航到我的应用程序中的receiptDetailScreen 页面时出现错误。 我的应用具有以下结构:
-main (MaterialApp, Provider)
-homeScreen
-receiptListSCreen
-receiptDetailScreen
我可以从主屏幕导航到receiptListScreen。但是当我尝试从那里转到receiptDetailScreen 时,我得到了错误:
在此 ReceiptDetailScreen 小部件上方找不到正确的提供程序
我的 Main.dart 看起来像:
Widget build(BuildContext maincontext) {
return MultiProvider(
providers: [
ChangeNotifierProvider.value(value: GreatPlaces()),
//.....
],
child: MaterialApp(
theme: ThemeData(
canvasColor: Color(0xFF363567),
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: Home(),
routes: {
SettingsScreen.routeName: (ctx) => SettingsScreen(),
ImageInputScreen.routeName: (ctx) => ImageInputScreen(),
AddReceiptScreen.routeName: (ctx) => AddReceiptScreen(),
ReceiptListScreen.routeName: (ctx) => ReceiptListScreen(),
ReceiptDetailScreen.routeName: (ctx) => ReceiptDetailScreen(),
},
),
);
}
我的主页是这样的:
class Home extends StatefulWidget {
@override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color(0xFF363567),
body: Builder(
builder: (BuildContext context) {
return ListView(
children: <Widget>[
Stack(
children: <Widget>[
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
SizedBox(height: 20),
SizedBox(
height: 12,
),
Container(
// height: 300,
height: MediaQuery.of(context).size.height * 0.60,
child: buildGrid(context),
),
SizedBox(
height: 12,
),
],
)
],
)
],
);
}
)
);
}
Widget buildGrid(BuildContext context) {
return GridView.count(
padding: EdgeInsets.fromLTRB(0, 5, 0, 5),
crossAxisCount: 2,
shrinkWrap: true,
childAspectRatio: (MediaQuery.of(context).size.width - 60 / 2) / 300,
children: <Widget>[
buildTile(
context,
0,
"New receipt",
null,
Icons.add,
"1,456 items",
Colors.orange,
Colors.orange[50],
'/add-receipt',
),
buildTile(
context,
1,
"Show list",
null,
Icons.list,
"658 items",
Colors.blue,
Colors.blue[50],
'/receipts-list',
),
buildTile(
context,
2,
"settings",
null,
Icons.settings,
"217 items",
Colors.purple,
Colors.purple[50],
'routename',
),
buildTile(
context,
3,
"About",
null,
Icons.info,
"24 items",
Colors.red,
Colors.red[50],
'routename',
),
],
);
}
int _selectedIndex = -1;
@override
Widget buildTile(
BuildContext context,
int index,
String heading,
Image image,
IconData icon,
String itemCount,
Color color,
Color backgroundColor,
String route) {
return Container(
padding: EdgeInsets.only(
left: index == 0 || index == 2 || index == 4 ? 12 : 5,
top: 0,
right: index == 1 || index == 3 || index == 5 ? 12 : 5,
bottom: 10),
child: GestureDetector(
onTap: () {
setState(() {
Navigator.of(context).pushNamed(route);
});
print("tapped");
},
child: Card(
elevation: 3,
shape: RoundedRectangleBorder(
side: BorderSide(
width: 1.0,
style: BorderStyle.solid,
color: _selectedIndex == index && color != null
? color
: Color(0xFF3D416E)),
borderRadius: BorderRadius.circular(10)),
color: Color(0xFF3D416E),
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Stack(
alignment: Alignment(0, 0),
children: <Widget>[
Container(
width: 43,
height: 43,
decoration: BoxDecoration(
color: Color(0xFF3D416E),
borderRadius: BorderRadius.circular(15)),
),
Icon(
icon,
color: color,
),
index != 1
? SizedBox(
height: 4,
)
: SizedBox(
height: 0,
),
],
),
Text(
heading,
style: TextStyle(
color: Colors.white,
fontSize: 18,
fontWeight: FontWeight.w600),
),
SizedBox(
height: 4,
),
Text(
itemCount,
style: TextStyle(
color: Colors.grey,
fontSize: 12,
fontWeight: FontWeight.w300),
)
],
))),
),
// ),
);
}
}
receiptListScreen 看起来像:
class ReceiptListScreen extends StatelessWidget {
static const routeName = '/receipts-list';
void selectReceipt(BuildContext ctx, String id) {
Navigator.of(ctx).pushNamed(ReceiptDetailScreen.routeName,
arguments: {'id': id, });
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color(0xFF363567),
appBar: AppBar(
title: Text('Your Receipts'),
actions: [
IconButton(
onPressed: () {
Navigator.of(context).pushNamed(AddReceiptScreen.routeName);
},
icon: Icon(Icons.add),
),
],
),
body: FutureBuilder(
future: Provider.of<GreatPlaces>(context, listen: false)
.fetchAndSetReceipts(),
builder: (ctx, snapshot) => snapshot.connectionState ==
ConnectionState.waiting
? Center(
child: CircularProgressIndicator(),
)
: Consumer<GreatPlaces>(
child: Center(
child: const Text('Got No Receipts yet, start adding?!'),
),
builder: (ctx, greatPlaces, ch) => greatPlaces.items.length <= 0
? ch
: ListView.builder(
itemCount: greatPlaces.items.length,
itemBuilder: (ctx, i) => ListTile(
leading: CircleAvatar(
backgroundImage: FileImage(greatPlaces.items[i].image),
),
title: Text(greatPlaces.items[i].title,style: TextStyle(color: Colors.white),),
onTap: () {
selectReceipt(context,greatPlaces.items[i].id );
},
),
),
),
),
);
}
}
最后收据DetailScreen 看起来像:
class ReceiptDetailScreen extends StatelessWidget {
static const routeName = '/receipt-details';
@override
Widget build(BuildContext context) {
final id = ModalRoute.of(context).settings.arguments;
final selectedReceipt = Provider.of<GreatPlaces>(context, listen: false).findById(id);
return Scaffold(
appBar: AppBar(title: Text(selectedReceipt.title),),
body: Column(
children: [
Container(height: 250, width: double.infinity,
child: Image.file(
selectedReceipt.image,
fit: BoxFit.cover,
width: double.infinity,
),
),
SizedBox(height: 10,),
Text(selectedReceipt.purchaseDate),
SizedBox(height :10),
Text(selectedReceipt.warrantyPeriod),
],
),
);
}
}
好像materialapp的上下文没有进入receiptdetailsceen,但我不知道我哪里出错了。
【问题讨论】: