본문 바로가기

flutter

[Flutter] Flutter Navigator 사용법 (5)

Photo by Dayne Topkin on Unsplash

Flutter 공식문서의 Navigator 챕터에서 이전 화면에 데이터를 반환하는 방법에 대해 정리해보았다.

이전 화면에 데이터 반환하기

새로운 화면으로부터 이전 화면으로 데이터를 반환해야하는 경우가 있음. 예를 들어, 사용자에게 두 가지 옵션을 보여주는 화면에서 사용자가 한 옵션을 클릭하면 첫 번째 화면에 알려주고 그에 따른 실행을 하려는 경우 Navigator.pop()을 사용하여 다음과 같이 진행할 수 있음.

  1. 홈 화면을 정의함.
  2. 선택 창을 띄우는 버튼을 추가.
  3. 두 개의 버튼을 가진 선택 창을 보여줍니다.
  4. 하나의 버튼을 클릭하면 선택 창을 닫습니다.
  5. 선택된 정보를 홈 화면의 snackbar에 보여줍니다.
  6. 홈 화면을 정의. 예제에서는 홈 화면에서는 버튼 하나가 있고 버튼을 클릭하면 연동 창을 띄움.
class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Returning Data Demo'),
      ),
      // 다음 단계에서 SelectionButton 위젯을 만들 것입니다.
      body: Center(child: SelectionButton()),
    );
  }
}

연동 창을 띄우는 버튼을 추가. SelectionButton을 만들고 사용자가 클릭했을 때, SelectionScreen을 띄움. SelectionScreen이 결과를 반환할 때까지 대기.

class SelectionButton extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
   return RaisedButton(
     onPressed: () {
       _navigateAndDisplaySelection(context);
     },
     child: Text('Pick an option, any option!'),
   );
 } // SelectionScreen을 띄우고 navigator.pop으로부터 결과를 기다리는 메서드
 _navigateAndDisplaySelection(BuildContext context) async {
   // Navigator.push는 Future를 반환합니다. Future는 선택 창에서 
   // Navigator.pop이 호출된 이후 완료될 것입니다.
   final result = await Navigator.push(
     context,
     // 다음 단계에서 SelectionScreen를 만들 것입니다.
     MaterialPageRoute(builder: (context) => SelectionScreen()),
   );
 }
}

두 개의 버튼을 가진 선택 창을 표시.

두 개의 버튼을 다른 화면에서 사용자가 하나의 버튼을 클릭하면 현재 창을 닫고 그 결과를 홈 화면에 알려줌. UI를 정의하고 다음 단계에서는 데이터를 반환하는 코드를 추가.

class SelectionScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Pick an option'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: RaisedButton(
                onPressed: () {
                  // "Yep" 문자열과 함께 이전 화면으로 돌아갑니다...
                },
                child: Text('Yep!'),
              ),
            ),
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: RaisedButton(
                onPressed: () {
                  // "Nope" 문자열과 함께 이전 화면으로 돌아갑니다.
                },
                child: Text('Nope.'),
              ),
            )
          ],
        ),
      ),
    );
  }
}

하나의 버튼을 클릭하면 창을 닫음. 첫 번째 화면으로 데이터를 반환하기 위해, Navigator.pop() 메서드를 사용.

//Yep 버튼RaisedButton(
  onPressed: () {
    // Yep 버튼은 결과로 "Yep!"을 반환.
    Navigator.pop(context, 'Yep!');
  },
  child: Text('Yep!'),
);//Nope 버튼
RaisedButton(
  onPressed: () {
    // Nope 버튼은 결과로 "Nope!"을 반환.
    Navigator.pop(context, 'Nope!');
  },
  child: Text('Nope!'),
);

선택된 정보를 홈 화면의 snackbar에 표시함. 예제에서는 결과 값을 보여줄 수 있도록 Snackbar를 띄우기 위해 SelectionButton의 _navigateAndDisplaySelection 메서드를 수정.

_navigateAndDisplaySelection(BuildContext context) async {
  final result = await Navigator.push(
    context,
    MaterialPageRoute(builder: (context) => SelectionScreen()),
  );  // 선택 창으로부터 결과 값을 받은 후, 이전에 있던 snackbar는 숨기고 새로운 결과 값을
  // 표시.
  Scaffold.of(context)
    ..removeCurrentSnackBar()
    ..showSnackBar(SnackBar(content: Text("$result")));
}

완성된 예제

import 'package:flutter/material.dart';void main() {
  runApp(MaterialApp(
    title: 'Returning Data',
    home: HomeScreen(),
  ));
}class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Returning Data Demo'),
      ),
      body: Center(child: SelectionButton()),
    );
  }
}class SelectionButton extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return RaisedButton(
      onPressed: () {
        _navigateAndDisplaySelection(context);
      },
      child: Text('Pick an option, any option!'),
    );
  }  // SelectionScreen을 띄우고 navigator.pop으로부터 결과를 기다리는 메서드
  _navigateAndDisplaySelection(BuildContext context) async {
    // Navigator.push는 Future를 반환합니다. Future는 선택 창에서 
    // Navigator.pop이 호출된 이후 완료될 것입니다.
    final result = await Navigator.push(
      context,
      MaterialPageRoute(builder: (context) => SelectionScreen()),
    );    // 선택 창으로부터 결과 값을 받은 후, 이전에 있던 snackbar는 숨기고 새로운 결과 값을
    // 표시.
    Scaffold.of(context)
      ..removeCurrentSnackBar()
      ..showSnackBar(SnackBar(content: Text("$result")));
  }
}class SelectionScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Pick an option'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: RaisedButton(
                onPressed: () {
                  // 창을 닫고 결과로 "Yep!"을 반환.
                  Navigator.pop(context, 'Yep!');
                },
                child: Text('Yep!'),
              ),
            ),
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: RaisedButton(
                onPressed: () {
                  // 창을 닫고 결과로 "Nope!"을 반환.
                  Navigator.pop(context, 'Nope.');
                },
                child: Text('Nope.'),
              ),
            )
          ],
        ),
      ),
    );
  }
}