Pop (上下文)返回黑屏

我的颤振项目结构是这样的

Main() //Run App with MaterialApp and Routes
L HomePage() //Default route (/), with BottomNavigation
L MoviesPage() //Default BottomNavigation Index and shows a list of movies form TMDB
L DetailsPage()
L SeriesPage()
L SupportPage()

在点击任何电影之后,它都会前进到 DetailsPage () ,但是当我从 DetailsPage ()调用 Navigator.pop 时,它应该会返回到之前的屏幕,但是它没有。

CanPop (context)返回 false 但是硬件返回按钮工作得非常好,那么我该如何修复它呢?

飞镖

class BerryMain extends StatelessWidget {
@override
Widget build(BuildContext context) {
// TODO: implement build
return MaterialApp(
home: Inferno(
{
'/': (context, argumets) => HomePage(),
'/detailspage': (context, arguments) => DetailsPage(arguments),
},
).home(context),
);
}
}

网页

class HomePage extends StatefulWidget {
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return _HomePageState();
}
}


class _HomePageState extends State<HomePage> {
int _currentIndex = 0;
final List<Widget> _childnav = [MoviesPage(), SeriesPage(), SupportPage()];


void onTabPressed(...)


@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text('...'),
actions: <Widget>[
IconButton(
icon: Icon(Icons.search),
onPressed: () {},
)
],
),
body: _childnav[_currentIndex],
bottomNavigationBar: BottomNavigationBar(
onTap: onTabPressed,
currentIndex: _currentIndex, //this property defines current active tab
items: [
BottomNavigationBarItem(
icon: Icon(Icons.movie), title: Text('Movies')),
BottomNavigationBarItem(icon: Icon(Icons.tv), title: Text('Series')),
BottomNavigationBarItem(icon: Icon(Icons.help), title: Text('Help'))
],
),
);
}
}

电影网页

//Inside ListView Builder
Virgil.pushNamed(context, '/detailspage', arguments: args);

详情页

//Inside MaterialApp > Scaffold > SliverAppbar > BackButton
Navigator.pop(context)

我使用的是 维吉尔,但我不认为这是问题所在。

67914 次浏览

I resolve it using this code:

Navigator.pushReplacementNamed(context, '/route');

According to this Answer I figured it out a way.

You should pass the MoviesPage context to the DetailsPage. And that context should be called in Navigator.pop(context);

for Example: FIRST SCREEN

class FirstScreen extends StatelessWidget {
final BuildContext context;


FirstScreen(this.context);///here u have to call the build Context of FirstScreen


@override
Widget build(BuildContext context) {
return new MaterialApp(
home: FirstScreenScreen(this.context));
}
}


class FirstScreenScreen extends StatefulWidget {
final BuildContext context;


FirstScreenScreen(this.context);/// and here also.


@override
_FirstScreenState createState() => _FirstScreenState();
}


class _FirstScreenState extends State<FirstScreenScreen> {
@override
Widget build(BuildContext context) {
return new Scaffold(
body: Container(
child: new RaisedButton(onPressed: (){


navigateAndDisplaySelection(context);


},
child: new Text('Go to SecondPage'),
),
),
);
}
}

SECOND SCREEN

 class SecondScreen extends StatelessWidget {
final BuildContext context;


SecondScreen(this.context);///here u have to call the build Context of FirstScreen


@override
Widget build(BuildContext context) {
return new MaterialApp(
home: SecondScreenScreen(this.context));
}
}


class SecondScreenScreen extends StatefulWidget {
final BuildContext context;


SecondScreenScreen(this.context);/// and here also.


@override
_SecondScreenState createState() => _SecondScreenState();
}


class _SecondScreenState extends State<SecondScreenScreen> {
@override
Widget build(BuildContext context) {
return new Scaffold(
body: Container(
child: new RaisedButton(onPressed: (){
Navigator.pop(widget.context);///this context is passed from firstScreen
},
child: new Text('Go Back'),
),
),
);
}
}

Pass Data & Return
if you want pass data and return, add a constructor with parameter in SecondScreen and call setState in method Fisrtlike this:

 navigateAndDisplaySelection(
BuildContext context) async {
// Navigator.push returns a Future that will complete after we call
// Navigator.pop on the Second Screen!
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => new SecondScreen(context)),
);
setState(() {
/// the passed value data will change here, when you change in second screen
});
}

This can happen if your MoviesPage has another MaterialApp widget. Most of the time you want to use Scaffold as a top widget for a new page/screen, but if you accidentally use MaterialApp instead, nothing warns you.

What happens, is that MaterialApp creates a new Navigator, so if you switch from one page with MaterialApp to another, you now have two Navigators in the widget tree.

The call Navigator.of(context) looks for the closest Navigator, so it'll use the one, newly created in your MoviesPage. As the history of your route transitions is stored in a first Navigator, this one can't pop back – it has empty route history.

Hence, the black screen.

Long story short, to fix this, just use Scaffold as a top widget instead of MaterialApp in all nested screens.

I had a very similar problem and my solution was to pass BuildContext context from the created StatelessWidget to a global variable and pop that context from the global variable. So...

var globalContext; // Declare global variable to store context from StatelessWidget


class SecondScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
globalContext = context; // globalContext receives context from StetelessWidget.


return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
canvasColor: Colors.transparent,
primarySwatch: Colors.blue,
),
home: SecondScreenPage(title: 'SECOND SCREEN'),
);
}
}


class SecondScreenPage extends StatefulWidget {
SecondScreenPage({Key key, this.title}) : super(key: key);


final String title;


@override
_SecondScreenPageState createState() => _SecondScreenPageState();
}


class _SecondScreenPageState extends State<SecondScreenPage>() {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Second Screen"),
leading: IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () => Navigator.pop(globalContext), // POPPING globalContext
)
),
...
}

Now I don't get a black screen and I'm at my first page as if I had clicked on Android's back button. =)

I don't know if that is a good practice. If anyone knows a way to do that "more correctly", please feel free to answer.

I had similar issues while poping back views, the way I fixed was instead of Navigator.of(context).pop(); I use Navigator.of(context).maybePop();.

No more black screens after that.

Flutter App should have only 1 MaterialApp Why??? It is a core component that give access to all other elements

Technically thinking Material App contains App Title and a Home Screen widget

Here is my implementation

void main() {
runApp(MyApp());
}


class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'First Flutter App',
home: FirstActivity());
}
}


class FirstActivity extends StatefulWidget {
@override
_FirstActivityState createState() {
return _FirstActivityState();
}
}


class _FirstActivityState extends State<FirstActivity> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('First Activity'),
),
body: Center(
child: RaisedButton(
child: Text('Move Forward'),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecondActivity()),
);
}),
),
);
}
}


class SecondActivity extends StatefulWidget {
@override
_SecondActivityState createState() {
return _SecondActivityState();
}
}


class _SecondActivityState extends State<SecondActivity> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Second Activity'),
),
body: Center(
child: RaisedButton(
child: Text('Move Back'),
onPressed: () {
Navigator.pop(context);
}),
),
);
}
}
  1. Import page where you want to go.

  2. Use Class of that Page-Ex.Appointment

Navigator.push(context,new MaterialPageRoute(builder: (context)=> new Appointment() ),);


3. Remove Push name from Navigator

Workaround is SystemNavigator.pop(); refer from this link

This behaviour also appears when the initialRoute is removed, something that can happen if you navigate to your first child by using:

Navigator.popAndPushNamed('...')

The solution is clearly simple tho, just use pushNamed instead.

Just add optionally param rootNavigator: true: Sample:

Navigator.of(context, rootNavigator: true).pop(context);

Edit: In some cases, this solution may not resolve your issue. Please make sure that there is only one MaterialApp widget in your app for all Pages.

Maybe in detail screen you are use MaterialApp as a main widget you need to just remove MaterialApp and diractly return Scaffold and maybe your problem will solve this is work for me.

Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Container(),
),
);
}

instead of

Widget build(BuildContext context) {
return Scaffold(
body: Container(),
);
}

to get rid of black screen, you can also use below method with as many pop() you want

Navigator.of(context)..pop()..pop();

Before navigating to another screen use Navigator.pop(context).

Example:

Navigator.pop(context),
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(uilder: (_) => GoogleMapScreenRemasterd()),
(Route<dynamic> route) => false),

I also faced that problem and Still i was getting black screen after trying all of those previous answers.I do not have any idea about MaterialApp or Scafold reason because my application main.dart was only using MaterialApp, So Scafold solution did not work for me.Now what Solved for me.

POP BACK CODE

Navigator.of(context, rootNavigator: true).pop(context)

CODE THAT DID NOT WORK

 Navigator.pushReplacement(context,CupertinoPageRoute(fullscreenDialog: false,builder: (context) => ChildClass())),

CODE THAT WORKED

 Navigator.push(context,MaterialPageRoute(builder: (context) => ChildClass())

this work for me, i think it's the better solution.

WidgetsBinding.instance.addPostFrameCallback((_) {
Navigator.pushReplacement(context, MaterialPageRoute(builder: (_) => Menu()));
}),

i have same issue like returning same screen return black screen

    void main() async {
runApp(MyApp());
}
    

class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return GetMaterialApp(home: Todo());
}
}
    

class Todo extends StatefulWidget {
const Todo({Key key}) : super(key: key);
    

    

@override
_TodoState createState() => _TodoState();
}
    

class _TodoState extends State<Todo> {
    

@override
Widget build(BuildContext context) {
return Scaffold(
body: RaisedButton(onPressed: (){
//print(controler.text);
//Navigator.push(context,MaterialPageRoute(builder: (context) => Todo("viral")));
//_sendDataBack(context);
Get.to(()=>Test());
    

},child: Text("submit"),),
) ;
    

}
}
    

other class
    

class Test extends StatefulWidget {
const Test({Key key}) : super(key: key);
    

@override
_TestState createState() => _TestState();
}
    

class _TestState extends State<Test> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: RaisedButton(onPressed: (){
Get.to(()=>MyApp());
    

},child: Text("submit"),),
) ;
    

}
}

and then i check my code and realize that i am passing wrong class i have to return class that have my widget tree so replace Myapp() to Todo() like below and that fix my issue

class Test extends StatefulWidget {
const Test({Key key}) : super(key: key);


@override
_TestState createState() => _TestState();
}


class _TestState extends State<Test> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: RaisedButton(onPressed: (){
Get.to(()=>MyApp());


},child: Text("submit"),),
) ;


}
}

This is a common problem. These are just simple Issues. This happens when you push New screen and there also MaterialApp() widget.

I would like to share my experience in this, as I had the same issue.

Basically, pop from empty screen stack is the major cause of this issue.

In my case, I was doing a periodic operation (reading some data from the camera) on scanner_screen (which was pushed to the stack by a button on my main_screen), when the camera finds a specific text, I call pop. The issue was that the camera was reading too fast, and thus I popped more than once, which means popping from an empty stack.

At first I though that popping is fast enough to call dispose on my scanner_screen to stop calling the periodic operation that keeps popping, but it was not. That is why I needed to make sure that periodic operation is stopped manually before popping from the screen stack.

I hope that may help somebody.

Check your Navigator.push code

Navigator.of(context).pushReplacement(
MaterialPageRoute(builder: (context) => Nextscreen()));

if you use .pushReplacement you cannot go back, it means you cannot use Navigator.pop(context).

otherwise, if you used

Navigator.push(context, MaterialPageRoute(builder: (context) => ListScreen(),),);

Kindly use this to get rid of the problem.

Navigator.of(context, rootNavigator: true).pop(context);

This solution may be help others to avoid black screens. As it helps me.

 if(Navigator.canPop(context)){
Navigator.of(context).pop();
}else{
SystemNavigator.pop();
}

Use Navigator.pushNamed instead of Navigator.pushReplacementNamed

Well, in the first version of my code Huy Nguyen's answer really helped me. After changing some base code and doing some state management, the fix stopped working.

Because it is my login screen and I don't need to return back to this page, I am removing all routes before. So my fix is basically to check if I can pop, if not just push to the route manually.

if (Navigator.canPop(context)) {
Navigator.of(context, rootNavigator: true).pop(context);
} else {
Navigator.of(context, rootNavigator: true)
.pushNamedAndRemoveUntil("/", (Route<dynamic> route) => false);
}

Please consider, that you may not be able to return data to the main screen here. In this case I am managing the state as it's pointed out here. I hope this helps someone.

On my case I was navigating via Navigator.pushReplacementNamed(context, '/profile'); But when i change the navigation like this: Navigator.pushNamed(context, '/profile'); Nav back is work properly

I had similar issues when I used Navigator.pop() it shows a black screen I used "maybePop()" method with "then" method and tested of the value if false then I pushed the rout to my Home screen. Like this:

Navigator.of(context).maybePop(context).then((value) {
if (value == false) {
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => Home(),
));
}
});

I have tried every answer but only this code solved the blank screen problem:

if (Navigator.canPop(context)) {
Navigator.of(context, rootNavigator: true).pop(context);
}