[Flutter] Scaffold Messenger

비나·2022년 11월 4일
0

Flutter

목록 보기
8/16
post-thumbnail
post-custom-banner

📌 Scaffold Messenger

드디어,, 1년 전 강의로 공부하다 보니 Flutter 2.0 이후 바뀐 것들을 이번 강의에 배웠다.
그동안 구글링으로 누덕누덕 기우며 이게 맞나 ㅜㅡㅜ 하던 내용들이 드뎌 해결되었다 🥹

암튼 그래서 2.0 버전 이후 업데이트 된 내용 중 하나인 Scaffold messenger에 대해서 정리하여 보자.


✅ 기존 Snack bar

기존의 스낵바 구현은 Scaffold.of(context) method로 복잡하게 구현했다.
이렇게 구현하는 경우 가장 가까운 Scaffold 위젯의 context를 찾을 수 있도록 하기 위해,
builder 함수를 사용해야 한다.

이러한 스낵바의 구현 방법의 단점은 바로 다른 페이지로 이동하는 경우 라우터가 변경되는데,
다른 라우터로 이동한 후에는 스낵바가 구현되지 않는 상황이 생긴다는 것이다.
평소에 어플을 이용해서 음식을 배달시키거나 물건 주문하는 경우를 생각해보면,
주문이 완료되었다는 내용이나 결제가 완료되었다는 내용의 스낵바가 뜨는데 이러한 스낵바는 다른 페이지로 이동해도 계속 떠있어야 한다.
그런데 기존의 방법으로는 라우터가 변경되는 경우,
스낵바가 실행된 Scaffold 위젯을 벗어나기 때문에 스낵바가 구현이 이어서 되지 않는 것이다.


✅ Scaffold Messenger Class

그래서 기존의 방법을 개선한 것이 이 Scaffold Messenger 클래스이다.
이 방법을 통해 구현하면 아래의 그림처럼 위젯 트리 최 상위에서 여러 Scaffold들이 스낵바를 전달받을 수 있도록 하기 때문에,
화면에서 라우터가 바뀌어도 스낵바가 적용될 수 있도록 한다.

그럼 이제 이를 바탕으로 한 예제를 살펴보자.
아래의 예제는 첫번째 페이지에서 북마크 모양의 Float action button를 만들고,
이를 클릭하면 just clicked a snack bar 라는 내용의 스낵바가 구현되며 다른 페이지로 이동해도 스낵바를 유지하도록 하였다.

그리고 스낵바에 action으로 Undo를 주고 이를 클릭하면 Third page로 이동하게 하였다.
Third page에서는 Elevated button으로 cancel 버튼을 만들고,
이를 클릭하면 cancel completed 스낵바가 이전과 같이 해당 페이지(여기서는 Third page) 내에서만 유지되도록 하였다.

👩‍💻 Scaffold messenger class 예제

import 'package:flutter/material.dart';
import 'package:myapp/Nav-main.dart';

void main() {
  runApp(MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.lightBlue,
      ),
      home: MyPage(),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Scaffold Messenger'),
      ),
      body: HomeBody(),	// body에서 HomeBody 위젯을 리턴 
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.bookmark),
        onPressed: () {
          // ScaffoldMessenger에는 모든 자손 Scaffold들이 등록되어 있으므로,
          // 가장 가까운 Scaffold 찾아서 반환함
          ScaffoldMessenger.of(context).showSnackBar(
            SnackBar(
              content: Text("just clicked a snack bar !"),
              duration: Duration(seconds: 5),
              action: SnackBarAction(
                label: 'Undo',
                onPressed: (){
                  Navigator.push(
                    context,
                    MaterialPageRoute(builder: (context) => ThirdPage())
                  );
                },
              ),
            ),
          );
        },
      ),
    );
  }
}

// MyPage의 body 부분인 HomeBody 위젯 
class HomeBody extends StatelessWidget {
  const HomeBody({super.key});

  @override
  Widget build(BuildContext context) {
    return Center(
      child: ElevatedButton(
        child: Text('Go to the 2nd Page'),
        onPressed: () {
          Navigator.push(
              context,
              MaterialPageRoute(
                builder: (context) => SecondPage(),
              ));
        },
      ),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('2nd Page'),
      ),
      body: Center(
        child: Text(
          'hi, there',
          style: TextStyle(fontSize: 20.0, color: Colors.grey),
        ),
      ),
    );
  }
}

// Third page
class ThirdPage extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    // 각 페이지에 ScaffoldMessenger를 쓰면 이전 방식처럼 그 페이지에서만 스낵바 적용됨
    // 대신 이전 방식과 마찬가지로 builder 위젯을 사용해야 함 
    return ScaffoldMessenger(
      child: Scaffold(
        appBar: AppBar(
          title: Text('3rd Page'),
        ),
        body: Builder(
          builder: (context) {
            return Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Text(
                    'Undo your action ?',
                    style: TextStyle(fontSize: 20.0, color: Colors.redAccent),
                  ),
                  ElevatedButton(
                    onPressed: (){
                      ScaffoldMessenger.of(context).showSnackBar(
                        SnackBar(content: Text('Cancel completed'),
                        duration: Duration(seconds: 3),
                        ),
                      );
                    },
                    child: Text('Cancel'),
                  ),
                ],
              ),
            );
          }
        ),
      ),
    );
  }
}

💻 출력 화면

  1. 첫번째 Home 페이지에서 스낵바를 띄운 채로 Second page로 이동하는 경우
    스낵바가 라우터가 변경되어도 유지되는 것을 볼 수 있다.

  2. Third page에서 cancel을 누르고 cancel completed 스낵바가 띄워지는 경우
    다시 첫번째 Home으로 가면 스낵바가 사라지는 것을 볼 수 있다.




📌 마무리

이렇게 snack bar 부분을 Scaffold messenger 클래스를 이용하여 구현하는 것을 정리했다.
강의에서 이전 버전만 알려주려나 조마조마 했는데ㅜ
역시 바뀐것도 다 알려준다,,이거 진짜 좋은 강의다,,
이제 다음 포스팅에서 Flutter 2.0 이후 바뀐 button들 정리하면,
코딩셰프 Flutter 순한맛 시즌1 강의 정리 끝이다 😚
순한맛 시즌 2 강의는 몇개 없던데,, 주말에 시즌 2까지 다 들을 수 있으면 좋겠다.
아무튼 오늘 정리 button까지 할거라서 이번 포스팅은 여기서 마무리 🥱




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

0개의 댓글