seong

Flutter - PopScope(예전 WillPopScope) 뒤로가기(취소키) 컨트롤 하기 본문

Flutter/Flutter

Flutter - PopScope(예전 WillPopScope) 뒤로가기(취소키) 컨트롤 하기

hyeonseong 2023. 11. 23. 00:04

PopScope이란?

- 기존에는 WillPopScope를 사용 했지만 v3.12.0-1.0.pre 버전 이후로는 사용되지 않고, PopScope를 사용을 권장한다.

자세한 내용은 아래 페이지에서 확인이 가능하다.

WillPopScope : https://api.flutter.dev/flutter/widgets/WillPopScope-class.html
PopScope : https://api.flutter.dev/flutter/widgets/PopScope-class.html

- 기기를 사용할 때 의도치 않게 뒤로가기 버튼을 누를 경우가 있다.

이럴 경우 만약 데이터를 가지고 있다가 의도치 않게 뒤로가기를 눌러 페이지가 초기화 되는 경우를 막아주는 역할을 한다.

사용법

Scaffold PopScope로 감싸주면 된다.

주요 생성자

1. canPop

- true일 경우 : 기본 탑재 되어 있는 뒤로가기 버튼 활성화

- false일 경우 : 기본 탑재 되어 있는 뒤로가기 버튼 비활성화  

 

2.  onPopInvoked :뒤로가기 이벤트가 발생 했을때 호출되는 함수

 

주요 코드

 PopScope(
              canPop: false, 
              onPopInvoked: (bool didPop) {
                  
              //didPop == true , 뒤로가기 제스쳐가 감지되면 호출 된다.
                if (didPop) {
                  print('didPop호출');
                  return;
                }
                _showBackDialog();
              },
              child: TextButton(
                onPressed: () {
                  _showBackDialog();
                },
                child: const Text('이전 페이지'),
              ),
            ),

전체 코드 

1. 첫번째 페이지 

간단하게 Navigator로 페이지 이동 하는 부분이다.

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

  @override
  Widget build(BuildContext context) {
    return PopScope(
      child: Scaffold(
        appBar: AppBar(
          title: const Text("FirstScreen"),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              const Text('첫번째 페이지'),
              TextButton(
                onPressed: () {
                  Navigator.of(context).pushNamed('/second');
                },
                child: const Text('다음 페이지'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

 

2. 두번째 페이지

두번째 페이지에는 2개의 위젯, 1개의 함수가 있다.

-  페이지를 정말 빠져나갈지 물어보는 showDialog함수,

- PopScope가 감싸고 있는 TextButton

- 아무것도 감싸지 않은 기본 TextButton -> 해당 버튼은 PopScope에 영향을 받지않고 dialog를 띄우지 않고 바로 뒤로간다.

class SecondScreen extends StatefulWidget {
  const SecondScreen({super.key});

  @override
  State<SecondScreen> createState() => _SecondScreenState();
}

class _SecondScreenState extends State<SecondScreen> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("SecondScreen"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text('두번째 페이지'),
            PopScope(
              canPop: false, 
              onPopInvoked: (bool didPop) {
                if (didPop) {
                  // IOS 뒤로가기 버튼, ButtonWidget이건 뒤로가기 제스쳐가 감지되면 호출 된다.
                  print('didPop호출');
                  return;
                }
                _showBackDialog();
              },
              child: TextButton(
                onPressed: () {
                  _showBackDialog();
                },
                child: const Text('이전 페이지'),
              ),
            ),
          ],
        ),
      ),
    );
  }

  void _showBackDialog() {
    showDialog<void>(
      context: context,
      builder: (BuildContext context) {
        return AlertDialog(
          title: const Text('정말 뒤로 가시겠습니까?'),
          content: const Text(
            '현재 페이지를 나가시겠습니까?',
          ),
          actions: <Widget>[
            TextButton(
              style: TextButton.styleFrom(
                textStyle: Theme.of(context).textTheme.labelLarge,
              ),
              child: const Text('아니오'),
              onPressed: () {
                Navigator.pop(context);
              },
            ),
            TextButton(
              style: TextButton.styleFrom(
                textStyle: Theme.of(context).textTheme.labelLarge,
              ),
              child: const Text('네'),
              onPressed: () {
                Navigator.pop(context);
              },
            ),
            TextButton(
              onPressed: () {
                Navigator.pop(context);
              },
              child: const Text("Scope를 감싸지않은 버튼"),
            )
          ],
        );
      },
    );
  }
}

3. 동작 결과

1) canPop를 false로 했을 경우 

" < "기본 뒤로 가기 버튼을 클릭 했을 때 바로 이전 페이지로 이동하는게 아니라 dialog함수가 실행된다.

PopScope를 감싼 버튼을 클릭 해도 dialog가 실행된다.

2) canPop을 true로 했을 경우 

 

 

'Flutter > Flutter' 카테고리의 다른 글

Flutter - 뒤로가기 버튼 클릭시 앱 종료  (1) 2023.12.03
Flutter - 1. UpStage API (API_KEY발급)  (0) 2023.11.28
Flutter - Constraints  (0) 2023.11.20
Flutter - ScreenUtil  (1) 2023.10.20
Flutter - Weather앱 TabBar 만들기  (0) 2023.10.18