플러터에서 앱 화면 / 위젯 간의 이동을 구현할 땐 Navigator 클래스를 사용한다.
1. 화면 이동하기
다음 코드를 이용하여 현재 화면을 스택에 저장한 후, 다음 화면으로 이동할 수 있다. 나는 Setting 버튼을 클릭하면 Setting창으로 이동할 수 있도록 만들었고, 다음은 Setting 아이콘의 onPressed: 안에 들어있는 함수이다.
Navigator.of(context).push(
MaterialPageRoute(
builder: (BuildContext context) {
return SettingsScreen();
},
),
);
Navigator.of() 안에는 파라미터로 context를 넣어주는데, 현재 문맥을 의미하며 push를 이용하여 스택의 가장 위에 이후에 불러올 화면을 넣어준다. 만약 나중에 Navigator 클래스를 이용하여 pop을 했을 때 이곳에 들어있던 context(문맥)의 가장 위 화면이 삭제되면서 바로 밑의 화면이 보이게 된다.
이후 MaterialPageRoute 안에서 SettingsScreen 클래스를 반환해주면 세팅창을 화면에 띄울 수 있다.
2. 화면 pop해서 이전 화면으로 돌아가기
세팅창을 Navigator로 push해주면 현재 화면에는 세팅창이 보이게 된다. 세팅창에서 버튼을 눌렀을 때, 다시 이전 화면으로 돌아갈 수 있도록 만들어주고 싶다.
onPressed: () => {
Navigator.of(context).pop();
}
해당 코드를 사용하면, 현재 context(문맥)에서 가장 위에 있는 현재 화면을 없애고, 이전 화면으로 돌아가게 된다.
3. 화면 이동할 때 변수 저장해서 전달해주기
화면을 이동할 때, 설정창에서 변수를 저장하면 해당 변수를 HomeScreen에서 사용하고 싶다.
Navigator.of(context).pop(maxNumber.toInt());
아까의 코드인데 pop 메서드의 파라미터로 반환값만 지정해주었다. 이 방법을 사용하면 버튼을 클릭했을 때, 화면이 넘어가면서 이 클래스의 지역 변수를 이전 화면으로 넘겨줄 수가 있다.
push할때의 메인화면도 async함수로 변경해야 한다. 그래야 세팅창에서 변수를 전달받을 때까지 기다릴 수 있기 때문이다.
void onSettingsPop() async {
final result = await Navigator.of(context).push<int>(
MaterialPageRoute(
builder: (BuildContext context) {
return SettingsScreen();
},
),
);
if (result != null) {
setState(() {
maxNumber = result;
});
}
}
세팅 아이콘을 onPressed했을 때 호출되는 함수이다. async함수를 사용했고, pop이 되어 세팅창에서 현재 창으로 되돌아올 때 result 변수에 pop()안에 들어있던 파라미터 값이 저장된다. 값은 화면이 pop()될 때 초기화되므로, 비동기적으로 수행하기 위해 await 키워드를 붙여서 동작이 완료될 때까지 화면을 정지시켰다. 세팅창이 pop()될 때 해당 함수가 완료된다.
result가 null일 경우, 즉 세팅창에서 저장을 하지 않고 세팅창을 이탈해 main화면으로 돌아오는 경우가 있을 수 있다. 이런 경우 이전의 maxNumber가 계속 maxNumber일 수 있도록 다시 저장해주어야 한다.