Flutter MaterialPageRoute 导航到黑色背景的屏幕时如何解决?
Posted
技术标签:
【中文标题】Flutter MaterialPageRoute 导航到黑色背景的屏幕时如何解决?【英文标题】:How to solve it when Flutter MaterialPageRoute navigates to a screen with black background? 【发布时间】:2020-05-01 09:19:51 【问题描述】:我第一次在我的一个项目中使用 Flutter,它是一个报纸应用程序。
当我尝试使用我的Drawer
中的MaterialPageRoute
从main.dart
导航到newsfeed_for_other_category.dart
时出现问题。在该屏幕中,它显示新闻,但背景为黑色。但在我的main.dart
正文中调用的屏幕newsfeed_screen.dart
中,它完美显示。
我在下面发布代码。
main.dart
import 'package:flutter/material.dart';
import './SizeConfig.dart';
import './screens/newsfeed_screen.dart';
import 'package:curved_navigation_bar/curved_navigation_bar.dart';
import 'factory/widget_factory.dart';
import 'widgets/top_news_widget.dart';
import 'package:splashscreen/splashscreen.dart';
import './widgets/drawer.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: 'Newspaper App',
theme: ThemeData(
primarySwatch: Colors.blue,
//backgroundColor: Colors.lightGreenAccent,
),
home: MyHomePage(title: 'The Business Standard'),
routes: <String, WidgetBuilder>
'/screen1': (BuildContext context) => new NewsFeedScreen(216, 5, "Top News"),
'/screen2' : (BuildContext context) => new NewsFeedScreen(4, 7, "National"),
'/screen3' : (BuildContext context) => new NewsFeedScreen(13, 70, "International"),
/*'/screen4' : (BuildContext context) => new Screen4()*/
,
);
class MyHomePage extends StatefulWidget
MyHomePage(Key key, this.title) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
class _MyHomePageState extends State<MyHomePage>
int _counter = 0;
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>(debugLabel: '_MainScreenKey');
Widget build(BuildContext context)
return SplashScreen(
seconds: 3,
navigateAfterSeconds: AfterSplash(),
title: Text(
'The Business Standard',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20.0
),
),
image: Image.asset(
'assets/TBS_logo.jpg',
),
backgroundColor: Colors.white,
styleTextUnderTheLoader: TextStyle(),
photoSize: 100.0,
onClick: ()=>print("Flutter Egypt"),
loaderColor: Colors.red
);
class AfterSplash extends StatefulWidget
@override
_AfterSplashState createState() => _AfterSplashState();
class _AfterSplashState extends State<AfterSplash>
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>(debugLabel: '_MainScreenKey');
@override
Widget build(BuildContext context)
SizeConfig().init(context);
return Scaffold(
key: _scaffoldKey,
appBar: AppBar(
backgroundColor: Colors.white,
title: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Image.asset(
'assets/TBS.png',
fit: BoxFit.cover,
height: 45,
)
],
),
leading: IconButton(
icon: Icon(Icons.dehaze),
color: Colors.black,
onPressed: () => _scaffoldKey.currentState.openDrawer(),
),
),
drawer: SideDrawer(),
body: NewsFeedScreen(22, 71, "Sports"),
bottomNavigationBar: CurvedNavigationBar(
backgroundColor: const Color(0xFF2b4849),
items: <Widget>[
Icon(Icons.bookmark, size: 30,),
Icon(Icons.perm_identity, size: 30,),
Icon(Icons.settings, size: 30,),
],
onTap: (index)
if(index == 2)
_scaffoldKey.currentState.showSnackBar(const SnackBar(
content: const Text('Will open Settings menu')));
else if(index == 0)
_scaffoldKey.currentState.showSnackBar(const SnackBar(
content: const Text('Implement Bookmark function')));
else
_scaffoldKey.currentState.showSnackBar(const SnackBar(
content: const Text('Will show User profile and information')));
,
),
);
newsfeed_for_other_category.dart,我正在导航的页面,这是黑色背景显示的地方。
import 'package:flutter/material.dart';
import '../SizeConfig.dart';
import '../widgets/headlines.dart';
import '../widgets/secondary_headlines.dart';
import '../widgets/listed_news.dart';
import '../models/NewsPost.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'dart:developer';
import '../screens/newsPost_details.dart';
import '../screens/newsfeed_for_specific_category.dart';
import 'package:flutter_swiper/flutter_swiper.dart';
import '../transition_animation_routes/ScaleTransitionRoute.dart';
import '../widgets/top_news_widget.dart';
class NewsfeedForOtherCategory extends StatefulWidget
int categoryId;
int childrenCategoryId;
String categoryName;
NewsfeedForOtherCategory(this.categoryId, this.childrenCategoryId, this.categoryName);
@override
_NewsfeedForOtherCategoryState createState() => _NewsfeedForOtherCategoryState(this.categoryId, this.childrenCategoryId, this.categoryName);
class _NewsfeedForOtherCategoryState extends State<NewsfeedForOtherCategory>
int categoryId;
int childrenCategoryId;
String categoryName;
_NewsfeedForOtherCategoryState(this.categoryId, this.childrenCategoryId, this.categoryName);
bool _isRequestSent = false;
List<NewsPost> newsPostList = [];
@override
Widget build(BuildContext context)
SizeConfig().init(context);
if(!_isRequestSent)
_sendRequest();
return Container(
alignment: Alignment.center,
child: !_isRequestSent
? CircularProgressIndicator()
: Container(
child: ListView.builder(
itemCount: newsPostList.length,
scrollDirection: Axis.vertical,
itemBuilder: (BuildContext context, int index)
return _getNewsPostWidgets(index);
),
),
);
void _sendRequest() async
String url = "https://tbsnews.net/json/category/news/"+this.categoryId.toString()+"/"+this.childrenCategoryId.toString()+"";
http.Response response = await http.get(url);
List<dynamic> decode = json.decode(response.body);
log('response: $response');
List results = decode[0]['items'];
for (var jsonObject in results)
var post = NewsPost.getNewsPostFromAPI(jsonObject);
newsPostList.add(post);
print(post);
setState(() => _isRequestSent = true);
Widget _getNewsPostWidgets(int index)
var newsPost = newsPostList[index];
if(index < this.newsPostList.length)
if(index == 0)
return GestureDetector(
onTap: ()
Navigator.push(
context,
ScaleTransitionRoute(
page: NewsPostDetails(newsPostList, index)
)
);
,
child: Column(
children: <Widget>[
Container(
padding: EdgeInsets.fromLTRB(10, 0, 0, 0),
//constraints: BoxConstraints(minWidth: double.infinity, maxWidth: double.infinity),
constraints: BoxConstraints.expand(
width: double.infinity,
height: 40
),
color: const Color(0xFF2b4849),
child: Text(
this.categoryName,
style: TextStyle(
fontSize: 33,
color: Colors.white
),
),
),
BlockHeadline(newsPost)
],
)
);
else
return GestureDetector(
onTap: ()
Navigator.push(
context,
ScaleTransitionRoute(
page: NewsPostDetails(newsPostList, index)
)
);
,
child: ListedNews(newsPost),
);
else
return Container(
color: const Color(0xFF2b4849),
child: index == 3 ? FlatButton(
child: Text(
"Load More",
style: TextStyle(
color: Colors.white
),
),
onPressed: ()
Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) => NewsFeedForSpecificCategory(newsPostList)
)
);
,
) : Container(),
);
openNewsPostDetails(List<NewsPost> newsPostList, int index)
Navigator.push(
context,
ScaleTransitionRoute(
page: NewsPostDetails(newsPostList, index)
)
);
drawer.dart
import 'package:flutter/material.dart';
import '../SizeConfig.dart';
import '../screens/newsfeed_for_other_category.dart';
class SideDrawer extends StatelessWidget
@override
Widget build(BuildContext context)
SizeConfig().init(context);
return SizedBox(
width: SizeConfig.safeBlockHorizontal*50,
child: Theme(
data: Theme.of(context).copyWith(canvasColor: const Color(0xFF2b4849)),
child: Drawer(
child: ListView(
children: <Widget>[
ListTile(
title: Text(
'Top News',
style: TextStyle(
fontSize: 20,
color: Colors.white
),
),
onTap: ()
Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) => NewsfeedForOtherCategory(216, 5, "Top News")
)
);
,
),
],
),
),
),
);
在我的主屏幕中,在main.dart
中的AfterSplashState
小部件的主体中调用newsfeed_screen.dart
,如下所示,这就是它应该的样子。
但是在我使用drawer
导航到的屏幕NewsfeedForOtherCategory
中看起来像下面的黑色背景。
我也尝试使用Navigator.of(context, rootNavigator: true).pushNamed('/route')
和pushReplacementNamed()
代替MaterialPageRoute
。但是没用。
这是我找到的相关question,我尝试了他们提供的解决方案,但对我不起作用。
还要提一下,我正在导航的页面没有 MaterialApp
小部件,只有 main.dart
有它。所以应该没有问题。
我使用的是 Ubuntu 16.04 机器。
你的一些线索将是无价的。非常感谢您的宝贵时间。
【问题讨论】:
【参考方案1】:NewsfeedForOtherCategory
页面是黑色的,因为它没有 Material
容器。
您可以简单地用Material
小部件或Scaffold
(它具有一些附加功能,如抽屉、浮动操作按钮)来包装它。
从您的屏幕截图中,我可以看到通知栏溢出了一些小部件。您可以在Material
或Scaffold
的body
内部使用SafeArea
来克服这个问题。
【讨论】:
非常感谢您对实际问题的解释。干杯!【参考方案2】:用脚手架将主容器包裹在NewsfeedForOtherCategory
中,您就有了解决方案。
...
return Scaffold(
body: Container(
alignment: Alignment.center,
child: !_isRequestSent
? CircularProgressIndicator()
: Container(
child: ListView.builder(
itemCount: newsPostList.length,
scrollDirection: Axis.vertical,
itemBuilder: (BuildContext context, int index)
return _getNewsPostWidgets(index);
),
),
);
);
...
【讨论】:
非常感谢你的朋友!向你致敬:-D【参考方案3】:在 NewsfeedForOtherCategory 小部件的构建功能中, 试着把你有的东西包在一个脚手架里。 喜欢:
return Scaffold(
body: Container(
alignment: Alignment.center,
child: !_isRequestSent
? CircularProgressIndicator()
: Container(
child: ListView.builder(
itemCount: newsPostList.length,
scrollDirection: Axis.vertical,
itemBuilder: (BuildContext context, int index)
return _getNewsPostWidgets(index);
),
),
),
),
【讨论】:
【参考方案4】:当我们在两个屏幕之间导航时,两个屏幕父级都应该是支架
如果你不想使用脚手架,你也可以使用容器颜色属性
尝试将您的容器包装在 NewsfeedForOtherCategory 屏幕中的脚手架中 像这样
...
@override
Widget build(BuildContext context)
return Scaffold(
body: Container(
),
);
...
或者你可以像这样设置容器颜色为白色
...
@override
Widget build(BuildContext context)
return Container(
color: Colors.white,
child:
//enter code here
);
...
【讨论】:
以上是关于Flutter MaterialPageRoute 导航到黑色背景的屏幕时如何解决?的主要内容,如果未能解决你的问题,请参考以下文章
如何从 Flutter 中的通知导航到应用程序中的特定 MaterialPageRoute
在 Flutter 中的 MaterialPageRoute 之后尝试 showDialogue 时出现“'context != null': is not true”错误?
Flutter MaterialPageRoute 不会在原生 iOS navigatorViewController 上导航
Flutter:类型 'Future<dynamic>' 不是类型 'Widget' 的子类型 // MaterialPageRoute<dynamic>(null))