본문 바로가기
프로그래밍/Flutter & Dart

Flutter 내비게이션 위젯 정리

by 어느덧중반 2021. 8. 30.
반응형

앱을 사용하다보면 다른 화면으로 전환하고 이전 화면으로 돌아가는 등의 액션을 하게된다.


1. 다른 화면으로 이동하는 방법

사전작업 : MainPage, SubPage 2가지 화면

- Navigator 클래스의 push() 메소드 이용 : 첫번째 인수 context, 두번째 인수 MaterialPageRoute 필요(머터리얼 디자인 화면간 전환)

- builder 프로퍼티에 이동할 페이지 나타내줌

- push() 메소드를 이용하면 메모리에 기존 화면이 계속 남아 있으므로, SubPage에서는 push()가 아닌 pop()메소드를 이용하자.

   * pop() : 현재 화면을 종료하고 이전 화면으로 돌아간다.

// 메인 페이지
class MainPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Main Page')
      ),
      body: RaisedButton(
        color: Colors.green,
        child: Text('Sub Page로 이동'),
        onPressed: () {
          Navigator.push(
            context,
            MaterialPageRoute(builder: (context) => SubPage())
          );
        },
      )
    );
  }
}

// 서브 페이지
class SubPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
            title: Text('Sub Page')
        ),
        body: RaisedButton(
          color: Colors.deepOrange,
          child: Text('Main Page로 이동'),
          onPressed: () {
            Navigator.push(
                context,
                MaterialPageRoute(builder: (context) => MainPage())
            );
          },
        )
    );
  }
}

각 버튼을 누르면 화면 전환이 된다

- MainPage -> SubPage에 값 전달하기

   SubPage에 값을 전달하려면 아래처럼 MainPage에서 파라미터를 넘기고 SubPage 생성자에서 셋팅해주자

  * MainPage 버튼클릭시 파라미터 넘기기 : SubPage(myCar: myCar)

  * SubPage 생성자에서 셋팅해주자 : SubPage({@required this.myCar});

class Car {
  String brand;
  String color;
  int price;

  Car(this.brand, this.color, this.price);
}

...

// 메인 페이지
class MainPage extends StatelessWidget {
        ...
        onPressed: () {

          final myCar = Car('RENAULT SAMSUNG', 'WHITE', 3000);

          Navigator.push(
            context,
            MaterialPageRoute(builder: (context) => SubPage(myCar: myCar))
          );
        },
      )
    );
  }
}

// 서브 페이지
class SubPage extends StatelessWidget {

  final Car myCar;

  SubPage({@required this.myCar});

  @override
  Widget build(BuildContext context) {
    ...
}

- 이전 화면으로 값 돌려주기

  원리 : 최초 MainPage에서 onPress할 때 asyncawait 키워드를 넣어주고 SubPage로부터 받은 데이터를 리턴받는다.

// 메인 페이지
class MainPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        ...
        onPressed: () async { // async 키워드를 추가

          final myCar = Car('RENAULT SAMSUNG', 'WHITE', 3000);
          final receive = await Navigator.push( // await 키워드 추가, 리턴값 받기
            context,
            MaterialPageRoute(builder: (context) => SubPage(myCar: myCar))
          );

          print(receive.toString());
        },
      )
    );
  }
}

// 서브 페이지
class SubPage extends StatelessWidget {
  ...
            Navigator.pop(context, 'returnData'); // pop시 돌려줄 데이터 추가
  ...
}

ex) MainPage > SubPage > MainPage 돌아오며 가져온 데이터 MainPage에서 보여주기

1. 'Sub Page로 이동' 클릭해서 화면 이동

  - async ~ await 키워드를 통해 넘어오는 값을 기다리게 된다. (넘어오는 값은 (Future) receive에 담을 예정) 

2. 'Main Page로 이동' 클릭해서 화면 이동

  - 'data From SubPage' 문자열을 화면 이동시 함께 넘겨준다.

3. 위 문자열을 receive로 받고 setState()로 returnMessage값을 변경해준다.

4. returnMessage값이 MainPage에 나타난다.

// 메인페이지
class MainPage extends StatefulWidget {
  @override
  _MainPageState createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {
  var returnMessage = "";

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
          title: Text('Main Page')
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: <Widget>[
            RaisedButton(
              color: Colors.green,
              child: Text('Sub Page로 이동'),
              onPressed: () async { // async 키워드를 추가

                final myCar = Car('RENAULT SAMSUNG', 'WHITE', 3000);
                final receive = await Navigator.push( // await 키워드 추가, 리턴값 받기
                    context,
                    MaterialPageRoute(builder: (context) => SubPage(myCar: myCar))
                );
                setState(() {
                  returnMessage = receive;
                });
              },
            ),
            Text(returnMessage)
          ],
        ),
      ),
    );
  }
}

// 서브 페이지
class SubPage extends StatelessWidget {

  final Car myCar;

  SubPage({@required this.myCar});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
            title: Text('Sub Page')
        ),
        body: Center(
          child: RaisedButton(
            color: Colors.deepOrange,
            child: Text('Main Page로 이동'),
            onPressed: () {
              Navigator.pop(context, 'data From SubPage'); // pop시 돌려줄 데이터 추가
            },
          ),
        )
    );
  }
}

async ~ await 를 이용해 SubPage -> MainPage 돌아올 때 값을 넘겨받는다.

 

2. routes를 활용한 내비게이션

위 방법으로는 페이지를 이동할 때 해당 페이지명을 작성해주었다. routes를 활용한 내비게이션을 이용하면 좀더 간결하게 구성 가능하다.

- routes는 MaterialApp에서 정의할 수 있다.

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MainPage(),
      routes: {
        '/main': (context) => MainPage(),
        '/sub': (context) => SubPage(),
      },
    );
  }
}

- routes 프로퍼티를 추가한 후에 아래 코드에서 소스를 2군데만 고치면 된다.

final receive = await Navigator.push(
  context,
  MaterialPageRoute(builder: (context) => SubPage(myCar: myCar))
);

  * Navigator.push -> Navigator.pushNamed (routes로 정한 예명 페이지를 호출)

  * MaterialPageRoute(~~~ 해당 페이지) -> routes명 (표현이 간결해짐)

final receive = await Navigator.pushNamed(context, '/sub');

 

반응형

댓글