[Flutter] Onboarding Screen

비나·2022년 11월 6일
0

Flutter

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

📌 Onboarding Screen

이번에는 온보딩 스크린 관련 강의를 듣고 따라한 예제를 정리하려고 한다.
온보딩 스크린이 그래서 뭐냐면,
처음에 어플 설치하면 나오는 설명이나 도움말 이런거 있는 화면 그거 말하는 거다.
그래서 아무튼 일단은 온보딩 스크린을 만들기 위해 이미지 몇개를 다운로드 받는다.

내가 들은 강의에서는 Freepik 사이트에서 다운로드 받았는데,
나는 내가 자주 쓰는 Flaticon 사이트에서 이미지를 몇개 다운로드 받았다.
암튼 다운로드 대충 받았으면, 이제 예제를 보자.




📌 기본 구성

Onboarding 페이지를 구성하기 위한 기본 틀을 먼저 살펴보자.

일단 기본적으로 구성은 위와 같다.
이 구성을 하나씩 살펴보면 아래와 같이 이루어진다.

  1. 먼저 main.dart에 MyApp 위젯과 MyPage를 stateless 위젯으로 만들어 준다.
    그리고 MyApp에서 MaterialApp을 평소처럼 리턴해준다.

  2. 다음으로 MaterialApp의 home argument에 OnboardingPage() 위젯을 넣는다.
    MaterialApp에서 home의 역할은 앱이 처음 실행될때 보여질 화면을 지정한다.
    따라서 처음 앱이 실행되면 이 OnboardingPage() 부분이 보여지도록 해주는 것이다.

  3. 그리고 OnboardingPage에서 리턴값으로 IntroductionScreen() 위젯이 보여지도록 한다. 그리고 이 위젯에서 Onboarding Page의 화면 구성을 만든다.

  4. 마지막으로 IntroductionScreen() 위젯이 모든 페이지를 보여주고 done까지 완료되면,
    onDone argument에서 MyPage()를 push하여 MyPage, 즉 기본 홈 화면이 보여지도록 한다.

이제 이러한 구성을 바탕으로 작성한 코드 예제를 보도록 하자.


✅ 예제

🌟 main.dart

우선 main.dart에서는 MyApp()과 MyPage() 위젯들을 넣어주었다.

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

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: OnboardingPage(),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        // 바꿀 필요 없는 값 앞에는 const 붙여주는 연습하기 
        title: const Text('Main Page'),
      ),
      body: Center(
        child: Column(
          children: [
            Text('Main Screen',
            style: TextStyle(
                fontWeight: FontWeight.bold,
                fontSize: 25,
              ),
            ),
            ElevatedButton(
              onPressed: (){},
              child: Text('Go to Onboarding Screen'),
            )
          ],
        )
      ),
    );
  }
}

🌟 Onboarding.dart

그리고 Onboarding.dart 파일을 만들어 이곳에서 OnboardingPage 위젯을 만들고,
이 위젯에서 리턴 값으로 IntroductionScreen() 위젯을 주도록 한다.
그리고 IntroductionScreen이 done까지 수행하고 나면,
IntroductionScreen의 onDone argument에 MyPage()를 push 하는 코드를 작성한다.

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

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

  @override
  Widget build(BuildContext context) {
    return IntroductionScreen(
      pages: [
        PageViewModel(
          title: 'Welcome to my app',
          body: 'This is the 1st page'
        ),
        PageViewModel(
          title: 'Welcome to my app',
          body: 'This is the 1st page'
        ),
        PageViewModel(
          title: 'Welcome to my app',
          body: 'This is the 1st page'
        ),
      ],
      done: const Text('done'),
      // Onboarding page가 끝나면 어떻게 할 지 
      onDone: (){
        Navigator.of(context).push(
          MaterialPageRoute(builder: (context) => const MyPage())
        );
      },
      next: const Icon(Icons.arrow_forward),
    );
  }
}



📌 Onboarding Screen 만들기

이제 이를 바탕으로 이미지와 글을 추가하여, Onboarding screen을 만든 예제이다.

그런데 기존에 기본 틀에서는 Onboarding.dart 파일에서
IntroductionScreen의 onDone 인자 값으로 MyPage()를 push하는 부분이 좀 바뀌어야 한다.
왜냐하면 이 부분에서 그냥 push를 해주면 뒤로가기 버튼이 생기는데,
Onboarding page는 한번 보여지고 나서 다시 보이지 않기 때문에
이 부분을 pushReplacement로 바꾸어준다.

따라서 아래와 같은

onDone: (){
  Navigator.of(context).push(
    MaterialPageRoute(builder: (context) => const MyPage())
  );
}

이 부분을

onDone: (){
  Navigator.of(context).pushReplacement(
    MaterialPageRoute(builder: (context) => const MyPage())
  );
}

위와 같이 바꾸어 코드를 작성한다.


✅ 예제

🌟 main.dart

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

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

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

  @override
  Widget build(BuildContext context) {
    // ignore: prefer_const_constructors
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: const OnboardingPage(),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        // 바꿀 필요 없는 값 앞에는 const 붙여주는 연습하기 
        title: const Text('Main Page'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: [
            // ignore: prefer_const_constructors
            Text('Main Screen',
            style: const TextStyle(
                fontWeight: FontWeight.bold,
                fontSize: 25,
              ),
            ),
            ElevatedButton(
              onPressed: (){
                Navigator.of(context).pushReplacement(
                  MaterialPageRoute(builder: (context) => const OnboardingPage())
                );
              },
              child: Text('Go to Onboarding Screen'),
            )
          ],
        ),
      ),
    );
  }
}

🌟 Onboarding.dart

return 값으로 주는 IntroductionScreen에서 Onboarding page들을 구성하는데,
pages argument 안에 PageViewModel 위젯들을 넣어 보여지는 각각의 페이지를 구성할 수 있다.

그리고 여기서 image 삽입 시 decoration을 한번에 똑같이 해주기 위하여,
getPageDecoration() method를 만들어 처리한 것을 볼 수 있다.

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

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

  @override
  Widget build(BuildContext context) {
    return IntroductionScreen(
      pages: [
        PageViewModel(
          title: 'Welcome to my app',
          body: 'This is the 1st page',
          image: Image.asset('assets/book.png'),
          // 텍스트, 이미지, 배경요소에 대한 스타일 지정은 decoration으로 함  
          // 그런데 여기서 decoration을 넣으면 하나 하나 넣어야 함 -> 메소드로 해결 
          // decoration: PageDecoration()
          decoration: getPageDecoration()
        ),
        PageViewModel(
          title: 'Welcome to my app',
          body: 'This is the 2nd page',
          image: Image.asset('assets/computer.png'),
          decoration: getPageDecoration()
        ),
        PageViewModel(
          title: 'Welcome to my app',
          body: 'This is the 3rd page',
          image: Image.asset('assets/grad.png'),
          decoration: getPageDecoration()
        ),
      ],
      done: const Text('done'),
      // Onboarding page가 끝나면 어떻게 할 지 
      onDone: (){
        // pushReplacement로 해주면 뒤로 가기 버튼이 안생김
        Navigator.of(context).pushReplacement(
          MaterialPageRoute(builder: (context) => const MyPage())
        );
      },
      next: const Icon(Icons.arrow_forward),
      // skip 버튼 추가 
      showSkipButton: true,
      skip: Text('skip'),
      // page 표시하는 dot 꾸미기 
      dotsDecorator: DotsDecorator(
        color: Colors.lightGreen,
        size: const Size(10, 10),
        // active 상태인 dot 꾸미기 
        activeColor: Color.fromARGB(255, 46, 90, 57),
        activeSize: Size(22,10),
        activeShape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(24)
        )
      ),
      // 애니메이션 효과 적용 
      curve: Curves.ease,
    );
  }
  
  // PageViewModel의 이미지 decoration 인자 값으로 주기 위한 메서드
  PageDecoration getPageDecoration(){
    return PageDecoration(
      // title 스타일 
      titleTextStyle: TextStyle(
        fontSize: 28,
        fontWeight: FontWeight.bold,
        color: Color.fromARGB(255, 227, 227, 227)
      ),
      // 본문 스타일 
      bodyTextStyle: TextStyle(
        fontSize: 18,
        color: Color.fromARGB(255, 231, 255, 233),
      ),
      imagePadding: EdgeInsets.only(top: 40),
      pageColor: Color.fromARGB(255, 46, 90, 57)
    );
  }
}

✅ 화면 결과




📌 마무리

오늘은 코딩셰프 Flutter 순한맛 시즌2 강의의 Onboarding screen을 만드는 부분을 정리했다.
내일은 ListView 강의 들은 것을 정리해야겠다.
그래도 이제 약간은 전반적인 구성이 보이는 것 같아서 좀 기분이 좋다.
오늘은 그럼 여기까지 쓰고 포스팅을 마무리 해야겠다 😌✨




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

0개의 댓글