[Flutter] flutter_native_splash를 활용하여, 밥아저씨처럼 손쉽게 네이티브 스플래시 만들기

Hans Park·2022년 2월 26일
2

Flutter

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

😳 누구나 한번쯤 경험해봤던 '그 버벅거림'


<위 영상은 Debug모드로 빌드되었습니다.>

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

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {

  
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Container(
          color: Colors.blue,
        ),
      ),
    );
  }
}

릴리즈모드로 빌드할땐 덜 하지만,
앱을 실행시킬 때 초반에 나오는 '그 버벅거림'이 있다.

main함수에서 Duration만으로 스플래시 화면을 적용하려하니
화면 전 흰 화면이 잠시 나오고, 이를 해결할 방법을 찾아야 했다.

https://pub.dev/packages/flutter_native_splash 버전체크

왜 버벅거리지?

이유는 플러터의 작동방식에 있다.

플러터는 앱이 실행될 때, 기본 앱 (네이티브 앱)이 플러터를 로드하는 동안 잠깐의 짧은 대기시간이 존재한다.
이 시간동안 기본 앱의 흰색 화면이 스크린에 표시되며, 마치 버벅거리는 것처럼 보인다.

(flutter의 자세한 내부구조와 렌더링 원리는 아래 블로그를 통해 확인할 수 있다.)
(https://brunch.co.kr/@myner/3)

버벅거리는 것 같은 화면을 방지하려면,
네이티브 어플 단에서 플러터가 화면에 rendering하기 전까지
splash화면을 보여주면 된다.

📦 flutter_native_splash

https://pub.dev/packages/flutter_native_splash

이 패키지는, 네이티브 단의 기본 시작화면의 배경색, 시작이미지(png), 브랜딩(회사) 등을 설정하고 정렬할 수 있는 패키지이다. iOS, Android 및 웹의 네이티브 코드들을 자동으로 생성하고, 다크모드, 전체화면과 플랫폼별 옵션 등을 지원한다.

이 패키지를 사용하면 네이티브 단(Android, iOS, Web)에서의 splash 화면을 설정에 맞게 만들어주고, Flutter가 첫 화면의 프레임을 렌더링하기 전까지 해당 화면이 노출된다.

👩‍🏫 사용법

  1. flutter_native_splash패키지를 다운받는다.
dependencies:
  flutter_native_splash: ^2.0.5
  1. pubspec.yaml에 아래 내용을 넣거나, 루트 프로젝트 폴더에 flutter_native_splash.yaml이름의 새 파일을 생성 후 아래 코드를 삽입한다.
    해당 코드는 패키지 사이트 여기에서 확인할 수 있다.

    주석이 굉장히 친절하게 설명하고 있기 때문에, 따로 해당파일을 파헤쳐보진 않으려 한다.

flutter_native_splash:

  # This package generates native code to customize Flutter's default white native splash screen
  # with background color and splash image.
  # Customize the parameters below, and run the following command in the terminal:
  # flutter pub run flutter_native_splash:create
  # To restore Flutter's default white splash screen, run the following command in the terminal:
  # flutter pub run flutter_native_splash:remove

  # color or background_image is the only required parameter.  Use color to set the background
  # of your splash screen to a solid color.  Use background_image to set the background of your
  # splash screen to a png image.  This is useful for gradients. The image will be stretch to the
  # size of the app. Only one parameter can be used, color and background_image cannot both be set.
  color: "#42a5f5"
  #background_image: "assets/background.png"

  # Optional parameters are listed below.  To enable a parameter, uncomment the line by removing
  # the leading # character.

  # The image parameter allows you to specify an image used in the splash screen.  It must be a
  # png file and should be sized for 4x pixel density.
  #image: assets/splash.png

  # This property allows you to specify an image used as branding in the splash screen. It must be
  # a png file. Currently, it is only supported for Android and iOS.
  #branding: assets/dart.png

  # Specify your branding image for dark mode.
  #branding_dark: assets/dart_dark.png

  # To position the branding image at the bottom of the screen you can use bottom, bottomRight,
  # and bottomLeft. The default values is bottom if not specified or specified something else.
  #
  # Make sure this content mode value should not be similar to android_gravity value and
  # ios_content_mode value.
  #branding_mode: bottom

  # The color_dark, background_image_dark, and image_dark are parameters that set the background
  # and image when the device is in dark mode. If they are not specified, the app will use the
  # parameters from above. If the image_dark parameter is specified, color_dark or
  # background_image_dark must be specified.  color_dark and background_image_dark cannot both be
  # set.
  #color_dark: "#042a49"
  #background_image_dark: "assets/dark-background.png"
  #image_dark: assets/splash-invert.png

  # The android, ios and web parameters can be used to disable generating a splash screen on a given
  # platform.
  #android: false
  #ios: false
  #web: false

  # The position of the splash image can be set with android_gravity, ios_content_mode, and
  # web_image_mode parameters.  All default to center.
  #
  # android_gravity can be one of the following Android Gravity (see
  # https://developer.android.com/reference/android/view/Gravity): bottom, center,
  # center_horizontal, center_vertical, clip_horizontal, clip_vertical, end, fill, fill_horizontal,
  # fill_vertical, left, right, start, or top.
  #android_gravity: center
  #
  # ios_content_mode can be one of the following iOS UIView.ContentMode (see
  # https://developer.apple.com/documentation/uikit/uiview/contentmode): scaleToFill,
  # scaleAspectFit, scaleAspectFill, center, top, bottom, left, right, topLeft, topRight,
  # bottomLeft, or bottomRight.
  #ios_content_mode: center
  #
  # web_image_mode can be one of the following modes: center, contain, stretch, and cover.
  #web_image_mode: center

  # To hide the notification bar, use the fullscreen parameter.  Has no effect in web since web
  # has no notification bar.  Defaults to false.
  # NOTE: Unlike Android, iOS will not automatically show the notification bar when the app loads.
  #       To show the notification bar, add the following code to your Flutter app:
  #       WidgetsFlutterBinding.ensureInitialized();
  #       SystemChrome.setEnabledSystemUIOverlays([SystemUiOverlay.bottom, SystemUiOverlay.top]);
  #fullscreen: true
  
  # If you have changed the name(s) of your info.plist file(s), you can specify the filename(s) 
  # with the info_plist_files parameter.  Remove only the # characters in the three lines below,
  # do not remove any spaces:
  #info_plist_files:
  #  - 'ios/Runner/Info-Debug.plist'
  #  - 'ios/Runner/Info-Release.plist'

생각보다 코드의 양도 많고 splash 정보만 따로 설정하기 용이하기 때문에, 새 파일을 만드는 것을 추천한다.

  1. 패키지를 실행하기 위해 터미널에서 아래와 같이 명령어를 실행한다.
    flutter pub run flutter_native_splash:create
    YAML 파일 위치를 지정하려면 터미널에서 명령과 함께 --path를 추가한다.
    flutter pub run flutter_native_splash:create --path=path/to/my/file.yaml

  1. (옵션) 만약 스플래시 화면동안 유저 정보 등 시간이 걸리는 작업이 필요할 경우, 직접 스플래시 화면 전환을 제어할 수 있다.
import 'package:flutter_native_splash/flutter_native_splash.dart';

void main() {
  WidgetsBinding widgetsBinding = WidgetsFlutterBinding.ensureInitialized();
  FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding);
  runApp(const MyApp());
}

// whenever your initialization is completed, remove the splash screen:
    FlutterNativeSplash.remove();
  • preserve, remove
    FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding);를 사용하면, Flutter에서 첫 프레임을 렌더링하였더라도 네이티브단의 스플래시화면을 없애지 않는다.

유저정보나 로그인 정보 등 앱 시작 시 필요한 정보나 permission을 받아야 할 때, 원하는 행위가 다 끝난 후 FlutterNativeSplash.remove();를 사용하여 스플래시 화면을 없앨 수 있다.

💡 유의사항

패키지를 통한 스플래시 화면 수정 / 삭제 시

이 패키지는 flutter에서 특별히 사용되는 함수들이 아니라, 터미널을 통해 패키지를 사용하여 네이티브 패키지(프로젝트) 내에 코드를 직접 삽입하는 패키지이다.

스플래시 화면을 삭제하려면
flutter pub run flutter_native_splash:remove
을 사용하여 네이티브에 적용된 파일과 코드들을 없앨 수 있으며,

삭제 후 yaml파일 수정 후, 다시 create하여 새로 생성하는 것으로 스플래시화면을 수정할 수 있다.

화면전환조건

preserve, remove함수를 사용하여 스플래시 화면을 없앴는데 flutter가 첫번째 프레임을 렌더링하지 못하였을 경우는, flutter가 렌더링 하기 전까지 스플래시 화면을 유지해준다.

즉,
flutter 첫번째 프레임 렌더링
&& ( preserve함수사용? (remove함수호출? true : false) : true)
== true
가 만족되어야 스플래시 화면이 사라진다.

removeAt

removeAt함수도 있으나, 잘 작동하지 않는 것 같아 따로 설명을 하지 않았다.

fullscreen

해당 내용은 flutter_native_splash.yaml에 더 자세히 나와있다.

  # To hide the notification bar, use the fullscreen parameter.  Has no effect in web since web
  # has no notification bar.  Defaults to false.
  # NOTE: Unlike Android, iOS will not automatically show the notification bar when the app loads.
  #       To show the notification bar, add the following code to your Flutter app:
  #       WidgetsFlutterBinding.ensureInitialized();
  #       SystemChrome.setEnabledSystemUIOverlays([SystemUiOverlay.bottom, SystemUiOverlay.top]);
  #fullscreen: true

Android에서 splash내 image를 적용했지만, 빈 화면으로 스플래시가 나오는 에러

android에서 image가 제대로 나오지 않는 현상이 있을 수 있다.
혹은 에뮬레이터에서는 잘 작동하지만 휴대폰에서는 잘 작동하지 않을 수 있다.
이는 안드로이드 내 drawable 폴더에 관한 이슈로, night모드, API21이상 모드 등 몇가지 폴더에 우리가 넣은 image: ###.png파일이 들어있지 않아 발생한다.

이는 res내 필요없는 drawable폴더를 삭제하거나, flutter_native_splash.yaml내 dark모드를 일반 모드에서와 같이 설정해주면 해결된다.

Android 빈 화면도 뜨지 않는 에러

AndroidManifest에서 activity태그 내 android:theme를 확인한다.
@style 내 LaunchTheme로 변경해주고 다시 시도해본다.

📚 참고하면 좋을만한 글

🖊 출처

profile
장안동 개발새발
post-custom-banner

0개의 댓글