ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Flutter기초] Navigator push/pop 과 페이지간 값 리턴하기
    개발/flutter 2021. 8. 8. 17:30

    Modern Collection View 와 MVVM 패턴 가이드

     

    [iOS] Modern Collection View & MVVM 패턴 가이드 - 인프런 | 강의

    MVVM 패턴과 Modern Collection View를 사용해 네트워킹을 구현하고, 다양하고 동적인 Collection View를 자유자재로 다룰 수 있게 됩니다., - 강의 소개 | 인프런

    www.inflearn.com

    이 화면에서 다른 화면으로 전환을 하고싶을때 사용할수 있는 다양한 방식이있다.

    Tabbar을 사용할수도 있고 상태를 바꿔서(Stateful) 화면을 바꿀수 있지만 가장 간단하고 많이쓰이는것은

    Navigator를 사용하는것이다.

    Navigator - push / pop 을 사용하여 새로운 페이지를 위에 얹거나 뺄수있다.

    그럼으로써 가장 상단에있는 view를 유저들은 볼수있는것이다.

    자료구조의 Stack과 같다고 보면된다.

     

    page 3 가 마지막에 navigator에 push 되었다면 사용자는 page3를 볼수있다.

    page3 가 pop이 된다면 page2가 가장 위에있으므로 사용자는 page2를 볼수있다.

     

    간단히 구현해보자 우선 화면 가운데 Page를 알릴 텍스트와 버튼을 구현해보자.

     

    (앞으로 구어체로 바꾸어 작성하겠습니다.)

    밑의 제가 짠 코드를 보기전에 

    Center , Column,Container 을 활용해 위의 UI를 직접 구현해보는것이 좋습니다.

    Column의 Alignment를 잘활용하고 container의 margin을 사용하면 됩니다.

    Go to Page2 는 Text의 색을 파란색으로 그리고 크기를 20으로 바꿨습니다.

    Text의 속성에있는 style 에 TextStyle() 속성을 넣어주면 구현할수 있습니다.

     

    버튼 기능을 위해서는 GestureDetector 로 감싸주어 버튼 이벤트를 받을수있구요.

     

    정답코드는 이렇습니다.

    body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Text("This is Page 1"),
                GestureDetector(
                  onTap: () {
                  //버튼이 클릭될시 구현될 기능
                  },
                  child: Container(
                      padding: EdgeInsets.only(top: 20),
                      child: Text(
                        "Go to Page 2",
                        style: TextStyle(color: Colors.blue, fontSize: 20),
                      )),
                )
              ],
            ),
          ),

    이제 onTap 함수 안에 Navigator push를 구현해야합니다. 그런데 이때 context, route 두개의 속성이 필요합니다.

    context는 build 함수에서 제공됩니다. context에 대한 자세한 내용은 생략하고 간단하게는 현재 페이지의 위치를 알려주는거라고 생각하면됩니다. 그래서 그 위에 push를 할수 있죠

    route에는 이제 MatarialPageRoute가 들어갑니다. 넘어갈 페이지를 넣어주는 것입니다. 

    그러면 우선 페이지가 우선 구현되어야 합니다.

    Page1과 비슷하게 구현해줍니다. 상태가 바뀌는 동적인 페이지가 아니므로 stateless로 구현해줍니다.

    class PageTwo extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Text("This is Page 2"),
                GestureDetector(
                  onTap: () {},
                  child: Container(
                      padding: EdgeInsets.only(top: 20),
                      child: Text(
                        "Go to Page 1",
                        style: TextStyle(color: Colors.blue, fontSize: 20),
                      )),
                )
              ],
            ),
          ),
        );
      }
    }

    페이지는 Scaffold로 감싸줘야합니다. page1 과 동일하게 텍스트만 바꿔 구현했습니다.

    이제 push를 구현하면 됩니다.

     GestureDetector(
                  onTap: () {
                    Navigator.push(context,
                        MaterialPageRoute(builder: (context) => PageTwo()));
                  },

     

    이렇게 함으로써 pageTwo 페이지로 넘어갈수있습니다.

    반대로 Page1 으로 넘어가려면 어떻게해야할까요? 

    page2를 위에서 빼면됩니다. pop을 사용하면 되죠

    page2 onTap함수에서 pop을 넣어줍니다.

    GestureDetector(
                  onTap: () {
                    Navigator.pop(context);
                  },

    Pop은 그냥 빼면 되므로 context만 있으면 됩니다.

    이렇게 간단히 push와 pop을 해보았습니다.

     

    다음은 push와 pop을 이용해 다음 페이지로 데이터를 전달하는법을 알아보겠습니다.

     

    아까 사용했던 Navigator.push를 자세히 보면

     

    가장 앞에있는 "Future<T>" 를 볼수 있습니다.

    이는 리턴 타입을 의미합니다. 해당 함수를 사용해서 Future<T> 라는 타입을 리턴 받는다는 것이죠

    Future는 무엇일까요? 의미 그대로 미래의 값입니다. 

    흔히 서버로부터 데이터를 받아오던가 유저의 액션을 통해 데이터를 받아오는경우 시간이 걸립니다

    그동안 앱이 멈춰있으면 안되기 때문에 이를 비동기 방식으로 처리합니다.

    앱이 정상적으로 돌면서 데이터 받아오는것도 기다렸다가 받아오는것이죠

    자세히는 다음에 Future에대해 다루도록 하겠습니다. 

    그리고 <T> 는 실제 타입을 의미합니다. T 가 들어가있기 떄문에 모든 타입을 사용가능합니다.

     

    즉 push 함수로 어떤 타입이든 리턴 받을수가 있습니다.

    리턴을 받으려면 async/await 이나 then 으로 받아올수 있습니다.

    이번에는 await 을 사용하도록 하겠습니다.

     onTap: () async {
                    final data = await Navigator.push(context,
                        MaterialPageRoute(builder: (context) => PageTwo()));
                  },

    push 함수 앞에 await을 두어 push 함수 리턴값이 받아올때까지 기다렸다가 받아

    data 라는 변수에 넣어줬습니다.

    await을 쓰기 위해서는 이를 감싸고 있는 함수에 async 표시를 해줘야 합니다.

    그래야 비동기 함수임을 알릴수 있습니다.

     

    그럼 데이터는 어디서 보내줄까요?

    pop 에서 보내줍니다.

     

    Page 2 GestureDetector에있던 pop 함수에 다름과 같이 넣어줍니다.

     GestureDetector(
         onTap: () {
         Navigator.pop(context,"This is retuen value");
       },

    "This is return value" 라는 스트링 값을 리턴해 준것입니다. 이안에 어떤 데이터 타입이든 들어갈수 있습니다.

    그러면 pop 을 하는순간 전페이지의 push 함수에 리턴이 됩니다.

    리턴값을 받아 setState 함수를 사용해 첫 페이지의 텍스트를 변경하도록 하겠습니다. 

     

    그러려면 우선 텍스트를 변수에 넣어 사용합니다. 

    class _MyHomePageState extends State<MyHomePage> {
      String title = "This is Page 1";
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text(widget.title),
          ),
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Text(title),
                GestureDetector(
                  onTap: () async {
                    final data = await Navigator.push(context,
                        MaterialPageRoute(builder: (context) => PageTwo()));
                    
                  },
                  child: Container(
                      padding: EdgeInsets.only(top: 20),
                      child: Text(
                        "Go to Page 2",
                        style: TextStyle(color: Colors.blue, fontSize: 20),
                      )),
                )
              ],
            ),
          ),
        );
      }
    }

    title 변수에 초기값을 넣어주었고 

    column 가장 상단 text 에 title 변수를 넣어 줬습니다.

    그다음 onTap 함수 안에 setState 함수를 넣어줍니다.

     onTap: () async {
                    final data = await Navigator.push(context,
                        MaterialPageRoute(builder: (context) => PageTwo()));
                    setState(() {
                      title = data;
                    });
                  },

    이렇게 하면 data를 받아와 title이 변경 됩니다.

     

    이제 Page2 에 갔다가 Page1 에 가면

    Text가 변경됨을 확인할수 있습니다.

    댓글

Designed by Tistory.