Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flutter switch between fragments by supporting back to previous fragment

in this link in SF, @martinseal1987 show us how can we use separated widgets link with android fragments.

I implemented this solution on my project and after running project i dont have any problem to show first widgets as an Fragment, but when i press to back button my screen goes to black and couldn't back to previous widgets as an fragment

i think that is should be this:

enter image description here

Problem is on navigateBack and customPop methods and i can attach fragment by pressing on button

import 'package:flutter/material.dart';

void main()
{
  runApp(MaterialApp(
    title: 'AndroidMonks',
    home: Scaffold(
      appBar: AppBar(
        title: Text('Androidmonks'),
        backgroundColor: Colors.orangeAccent,
      ),
      body: Home(),
    ),
  ));
}

class Home extends StatefulWidget {
  Home({
    Key key,
  }) : super(key: key);

  @override
  State<Home> createState()=>_Home();
}

class _Home extends State<Home> {
  String title = "Title";
  int _currentIndex = 0;
  final List<int> _backstack = [0];

  @override
  Widget build(BuildContext context) {
    navigateTo(_currentIndex);
    //each fragment is just a widget which we pass the navigate function
    List<Widget> _fragments =[Fragment1(),Fragment2(),Fragment3()];
    //will pop scope catches the back button presses
    return WillPopScope(
      onWillPop: () {
        customPop(context);
      },
      child: Scaffold(
        body: Column(
          children: <Widget>[
            RaisedButton(
              child:Text('PRESS'),
              onPressed: (){
                _currentIndex++;
                navigateTo(_currentIndex);
              },
            ),
            Expanded(
              child: _fragments[_currentIndex],
            ),
          ],
        ),
      ),
    );
  }


  void navigateTo(int index) {
    _backstack.add(index);
    setState(() {
      _currentIndex = index;
    });

    _setTitle('$index');
  }

  void navigateBack(int index) {
    setState(() {
      _currentIndex = index;
    });

    _setTitle('$index');
  }

  customPop(BuildContext context) {
    if (_backstack.length - 1  > 0) {
      navigateBack(_backstack[_backstack.length - 1]);
    } else {
      _backstack.removeAt(_backstack.length - 1);
      Navigator.pop(context);
    }
  }
  //this method could be called by the navigate and navigate back methods
  _setTitle(String appBarTitle) {
    setState(() {
      title = appBarTitle;
    });
  }
}

class Fragment2 extends StatefulWidget {
  @override
  State<Fragment2> createState() => _Fragment2();
}

class _Fragment2 extends State<Fragment2> {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: RaisedButton(
          child: Text("_Fragment2"),
          onPressed: (){
          }),
    );
  }
}


class Fragment1 extends StatefulWidget {
  @override
  State<Fragment1> createState() => _Fragment1();
}

class _Fragment1 extends State<Fragment1> {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text("_Fragment1"),
    );
  }
}


class Fragment3 extends StatefulWidget {
  @override
  State<Fragment3> createState() => _Fragment3();
}

class _Fragment3 extends State<Fragment3> {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text("_Fragment3"),
    );
  }
}
like image 697
DolDurma Avatar asked May 20 '19 14:05

DolDurma


2 Answers

I fixed some logic in your code please carefully check the changes, if you have any question don't hesitate, here is the working code

import 'package:flutter/material.dart';

void main()
{
  runApp(MaterialApp(
    title: 'AndroidMonks',
    home: Scaffold(
      appBar: AppBar(
        title: Text('Androidmonks'),
        backgroundColor: Colors.orangeAccent,
      ),
      body: Home(),
    ),
  ));
}

class Home extends StatefulWidget {
  Home({
    Key key,
  }) : super(key: key);

  @override
  State<Home> createState()=>_Home();
}

class _Home extends State<Home> {
  String title = "Title";
  List<Widget> _fragments =[Fragment1(),Fragment2(),Fragment3()];
  int _currentIndex = 0;
  final List<int> _backstack = [0];

  @override
  Widget build(BuildContext context) {
    //navigateTo(_currentIndex);
    //each fragment is just a widget which we pass the navigate function

    //will pop scope catches the back button presses
    return WillPopScope(
      onWillPop: () {
        return customPop(context);
      },
      child: Scaffold(
        body: Column(
          children: <Widget>[
            RaisedButton(
              child:Text('PRESS'),
              onPressed: (){
                _currentIndex++;
                navigateTo(_currentIndex);
              },
            ),
            Expanded(
              child: _fragments[_currentIndex],
            ),
          ],
        ),
      ),
    );
  }


  void navigateTo(int index) {
    _backstack.add(index);
    setState(() {
      _currentIndex = index;
    });

    _setTitle('$index');
  }

  void navigateBack(int index) {
    setState(() {
      _currentIndex = index;
    });

    _setTitle('$index');
  }

  Future<bool> customPop(BuildContext context) {
    print("CustomPop is called");
    print("_backstack = $_backstack");
    if (_backstack.length   > 1) {
      _backstack.removeAt(_backstack.length - 1);
      navigateBack(_backstack[_backstack.length - 1]);

      return Future.value(false);
    } else {

      return Future.value(true);
    }
  }
  //this method could be called by the navigate and navigate back methods
  _setTitle(String appBarTitle) {
    setState(() {
      title = appBarTitle;
    });
  }
}

class Fragment2 extends StatefulWidget {
  @override
  State<Fragment2> createState() => _Fragment2();
}

class _Fragment2 extends State<Fragment2> {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: RaisedButton(
          child: Text("_Fragment2"),
          onPressed: (){
          }),
    );
  }
}


class Fragment1 extends StatefulWidget {
  @override
  State<Fragment1> createState() => _Fragment1();
}

class _Fragment1 extends State<Fragment1> {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text("_Fragment1"),
    );
  }
}


class Fragment3 extends StatefulWidget {
  @override
  State<Fragment3> createState() => _Fragment3();
}

class _Fragment3 extends State<Fragment3> {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text("_Fragment3"),
    );
  }
}

a

like image 59
Saed Nabil Avatar answered Oct 24 '22 01:10

Saed Nabil


You can achieve this type of navigation using LocalHistoryRoute.of(context).addLocalHistoryEntry and Navigator.pop().

like image 40
Collin Jackson Avatar answered Oct 24 '22 03:10

Collin Jackson