[Flutter] Navigator

비나·2022년 11월 2일
0

Flutter

목록 보기
6/16
post-thumbnail

📌 Navigator

오늘 포스팅은 드디어 Navigator!!
역시 Navigator까지는 해야 좀 재밌다.

일단 Navigator 공부는 아래와 같은 순서로 정리할 예정이다.

  • Route의 개념
  • MaterialPageRoute 위젯과 context
  • 페이지 이동 기능 구현 완성

이번 공부도 코딩셰프 Flutter 순한맛 시즌 1을 보고 정리하는 내용이다.


✅ Route

먼저 Flutter에서 Route란 화면에서 보여지는 하나의 페이지를 의미한다.
Flutter에서는 모든 Route 객체들을 stack 자료구조로 관리한다.

🌟 Stack

스택 자료구조는 LIFO(후입선출) 구조를 가진다.
데이터를 책 쌓듯이 쌓았다가 위에서 부터 다시 빼간다.

데이터를 넣을 때는 push,
데이터를 꺼낼 때는 pop을 사용한다.

Route는 모든 객체를 이러한 자료구조로 관리하는 것이다.

따라서 구현을 할때 화면 위에 화면을 쌓았다가,
다시 화면 하나를 없애는 식으로 구현해야한다.


✅ Navigator - 페이지 2개

그래서 페이지 2개를 이동할 수 있도록 구현하면 다음과 같다.


👩‍💻 페이지 2개 이동하기 구현

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Navigator',
      theme: ThemeData(primarySwatch: Colors.grey),
      home: FirstPage(),
    );
  }
}

class FirstPage extends StatelessWidget {
  const FirstPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('1st page'),
        centerTitle: true,
        elevation: 0.0,
      ),
      body: Center(
        child: ElevatedButton(
          child: Text('Go to the 2nd page'),
          onPressed: (){
           // context에 있는 현  페지 위치 정보에 근거해서 위 쌓기 위해 context 필요 
            Navigator.push(context, MaterialPageRoute(  
              builder: (context) => SecondPage(),  // builder로 이동할 라우터를 지정해 줌 
            ));
          }),
        ),
    );
  }
}

class SecondPage extends StatelessWidget {
  const SecondPage({super.key});

  @override
  Widget build(BuildContext context2) {
    return Scaffold(
      appBar: AppBar(
        title: Text('2nd page'),
        centerTitle: true,
        elevation: 0.0,
      ),
      body: Center(
        child: ElevatedButton(
          child: Text('Go to the 1st page'),
          onPressed: (){
          	// 다시 pop 해서 context2를 제거하고 첫번째 페이지로 돌아감
            Navigator.pop(context2);
          }),
        ),
    );
  }
}

💻 결과 화면

결과 화면을 보도록 하자.
첫번째 사진은 First Page 상태일 때 이고, 두번째 사진은 Second page를 열었을 때 이다.

코드를 구현한 것 처럼 두번째 페이지를 여는 경우,
First Page 위에 Second Page가 쌓이는 형태로 구현된 것을 볼 수 있다.


🌟 First Page 구현 시

첫번째 페이지 구현하는 경우 builder가 있는데,
builder는 이동할 라우터를 지정해 주는 일종의 안전장치이다.
그런데 Second Page에서는 다른 context(Context2)를 받아서 pop을 해주기 때문에
builder에서 굳이 인자 값으로 context 안넘겨줘도 된다.
underscore(_)는 비어있는 인자 값을 의미한다.

class FirstPage extends StatelessWidget {
  const FirstPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('1st page'),
        centerTitle: true,
        elevation: 0.0,
      ),
      body: Center(
        child: ElevatedButton(
          child: Text('Go to the 2nd page'),
          onPressed: (){
            Navigator.push(context, MaterialPageRoute(
	      	  // 인자값으로 context 안넘겨줘도 됨
              builder: (_) => SecondPage(), // _:인자값이 비어 있는 경우 
            ));
          }),
        ),
    );
  }
}

✅ Navigator - 페이지 여러 개

다음은 페이지 여러 개를 만들어 이동하는 코드이다.
우선 페이지 여러 개를 이동해야 하니까,
main.dart 파일 이외에 다른 dart 파일들을 만들어 준다.

우선 여러 페이지간의 이동을 구현을 위해서는 Route 사용을 위한 MaterialApp()위젯 안의 arguments 알아야 한다.

아래 두개의 arguments를 사용하므로, 꼭 알아두자.

  • initialRoute : 화면에 제일 처음 출력되는 아규먼트 역할(home의 역할)
    home 아규먼트랑 같이 쓸 수 없음(같이 쓰면 에러 발생)
  • routes : 이동할 페이지들의 이름을 지정하고 생성함
    Map 자료구조를 가짐 - Key : Value
    String : Widget builder

그리고 이전에는 push를 사용하였다면, 여기서는 pushNamed를 사용하여 push 하여 준다.

그럼 위의 arguments와 pushNamed를 이용하여 이제 예제를 구현해보자.

아래 예제는 main.dart 파일 이외에 3개의 스크린 파일을 만들어서 구현했다.

👩‍💻 main.dart

main.dart 파일에서는 각 화면으로 이동하는 것을 routes로 구현한다.

import 'package:flutter/material.dart';
import 'ScreenA.dart';
import 'ScreenB.dart';
import 'ScreenC.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      initialRoute: '/',
      routes: {
        '/' : (context) => ScreenA(),	// home화면은 ScreenA
        '/b' : (context) => ScreenB(),
        '/c' :(context) => ScreenC()
      },
    );
  }
}

👩‍💻 ScreenA.dart

ScreenA.dart 파일에서는 home이 될 화면을 구현한다.

import 'package:flutter/material.dart';

class ScreenA extends StatelessWidget {
  const ScreenA({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('ScreenA'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ElevatedButton(
              onPressed: (){
                //pushNamed를 사용해서 push 해줌 
                Navigator.pushNamed(context, '/b');
              },
              child: Text('Go to ScreenB')
            ),
            SizedBox(
              height: 50,
            ),
            ElevatedButton(
              onPressed: (){
                //pushNamed를 사용해서 push 해줌 
                Navigator.pushNamed(context, '/c');
              },
              child: Text('Go to ScreenC')
            ),
          ],
        ),
      ),
    );
  }
}

👩‍💻 ScreenB.dart

ScreenB.dart와 ScreenC.dart 파일에서는 그냥 보여질 화면이라 간단한 텍스트만 넣었다.

import 'package:flutter/material.dart';

class ScreenB extends StatelessWidget {
  const ScreenB({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('ScreenB'),
      ),
      body: Center(
        child: Text('Hello, ScreenB'),
      ),
    );
  }
}

👩‍💻 ScreenC.dart

import 'package:flutter/material.dart';

class ScreenC extends StatelessWidget {
  const ScreenC({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('ScreenC'),
      ),
      body: Center(
        child: Text('Hello, ScreenC'),
      ),
    );
  }
}

💻 결과 화면




📌 마무리

오늘은 이렇게 간단하게 Navigator 구현하는 부분을 공부했다.
어제 강의 하나 들은거랑 오늘 하나 들은 걸로 겨우겨우 오늘의 포스팅도 성공,,ㅜ
내일은 대학원 수업 없는 날이라 과제 정리도 하고 순한맛 시즌1 강좌도 최대한 마무리 지어봐야겠다.
일단 이번주 목표는 순한맛 시즌1 완강하기 🎯✨




참고
- Flutter
- Dart packages
- 코딩셰프 Flutter 담백한 맛
- 코딩셰프 Flutter 순한맛 시즌1
profile
아자아자 코딩라이푸 ٩(๑❛ʚ❛๑)۶

0개의 댓글