본문 바로가기
⛏️ | 개발 기록/⏰ | Schedule Planner

[Android, Kotlin] Android 12 버전 이상에서 Compose로 Custom Splash Screen 생성하기 (9)

by immgga 2023. 11. 10.

출처: https://blog.stackademic.com/creating-a-stunning-splash-screen-with-fading-logo-animations-in-android-2e6a9cea01ae

 

이번 포스팅에서는 지난 포스팅에서 언급했다시피, 한 번 로그인했으면 로그인 정보가 저장되어 여러 번 로그인을 하지 않아도 되는 자동 로그인 기능을 만들어 볼까 한다.

 

필자는 자동 로그인 기능을 만들기 위해서

Splash Screen을 활용하고자 한다.

간단하게 로직을 설명하자면,

  1. 앱 실행 후 Splash Screen이 나타남
  2. Splash Screen이 켜져 있는 동안 Firebase 로그인 정보가 있는지 확인한다.( 로그인 정보는 State로 확인, 있으면 true, 없으면 false)
  3. State의 상태에 따라서 시작 Route를 설정한다.(true면 main route, false면 login route)

이렇게 간단하게 로직을 설계해 주었다.

Android 12 버전부터는 Splash가 기본으로 생성되도록 변경되었다.

기본으로 생성되어서 굳이 안 만들어도 된다는 편리한 점이 있지만 Splash에 필자와 같은 State를 확인하는 로직을 만들고 싶은 경우에는 기본 Splash로는 만들기 힘들다.

 

필자가 알기로는 안드로이드 12 이전처럼 Screen을 만드는 방법(직접 Screen 파일을 생성)과, style theme로 만드는 방법이 있는데

필자는 후자의 방법을 선택하도록 하겠다.

 

그러면 바로 Splash Screen부터 만들어 보도록 하겠다.

 

1. Gradle 라이브러리 추가

splash screen을 관리할 수 있는 함수들을 사용하기 위해 다음과 같은 라이브러리를 추가해야 한다.

// splash
implementation("androidx.core:core-splashscreen:1.0.1")

 

2. Splash Screen 만들기

다음으로는 style.xml에서 splash screen을 위한 theme를 만들어 주도록 하자.

꼭 style.xml에서 작업을 해야 하는 것이 아니고, 따로 splash.xml과 같이 파일을 생성해서 작업해도 상관없다 :)

<style name="Theme.SplashTheme" parent="Theme.SplashScreen">
    <item name="windowSplashScreenBackground">@color/white</item>
    <item name="windowSplashScreenAnimatedIcon">@drawable/ic_splash_app_logo</item>
    <item name="postSplashScreenTheme">@style/Theme.PlannerV2</item>
</style>
  • windowSplashScreenBackground: splash의 배경색을 설정한다.
  • windowSplashScreenAnimatedIcon: splash의 icon을 설정한다.(애니메이션 처리된 icon뿐만 아닌, 평범한(?) icon도 사용 가능하다.)
  • postSplashScreenTheme: splash의 테마를 설정한다. 이 부분은 자신의 안드로이드 프로젝트의 기본으로 생성되는 테마로 설정하면 된다.

 

다음은 manifest로 가서 생성한 theme를 적용하는 작업을 해주자.

<application
    <!-- . . . -->
    android:theme="@style/Theme.SplashTheme"
    tools:targetApi="31">
    <activity
        android:name=".view.MainActivity"
        android:exported="true"
        android:label="@string/app_name"
        android:theme="@style/Theme.SplashTheme">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

<application> 안의 theme와 <activity> 안의 theme를 위에 생성한 theme로 바꿔준다.

 

 

3. Splash 적용

이제 로그인이 되었는지 확인하는 State를 설정하는 로직을 만들어 보겠다. ViewModel을 만들어서 따로 생성해 주었다.

private val _loginState = MutableStateFlow<Boolean?>(null)
val loginState = _loginState.asStateFlow()

private val _splashSate = MutableStateFlow(true)
val splashState = _splashSate.asStateFlow()

fun checkLogin() {
    viewModelScope.launch {
        val auth = FirebaseAuth.getInstance()
        _loginState.value = auth.currentUser != null
        if (_loginState.value != null) _splashSate.value = false
    }
}

초기의 State를 null로 지정하고 로그인이 되어 있으면 true로 설정하고 아니면 false로 설정해 주었다.

또 다른 State는 splash screen이 열려 있는 상태를 저장하기 위해 만들어 주었고, _loginState가 초기값(null)에서 변경되었으면 splashState를 false(종료)로 지정해 주었다. 

 

마지막으로 MainActivity에 Splash를 적용하는 코드를 작성한다.

class MainActivity : ComponentActivity() {
    private val splashViewModel by viewModels<SplashViewModel>()
    private val loginState: Boolean? by lazy { splashViewModel.loginState.value }
    private val splashState: Boolean by lazy { splashViewModel.splashState.value }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        splashViewModel.checkLogin()
        installSplashScreen().setKeepOnScreenCondition {
            splashState
        }

        setContent {
        	. . .
        }
    }
}

viewModel 변수와 State 변수를 만들어 주었다. State 변수는 lazy를 이용해 변수를 사용할 때, 초기화가 이루어지도록 작성해 주었다.(by lazy는 한 번 초기화가 되면 다음에 사용할 때에는 저장된 state를 사용하므로 안심해도 된다.)

다음으로 ViewModel의 checkLogin()으로 ViewModel 로직을 적용해 주었고,

installSplashScreen()을 이용해 Splash 화면을 띄워 주었다.

또한 setKeepOnScreenCondition {}을 이용해 loginState가 null(state의 초기값)이 아닐 경우 splash가 종료되도록 만들어 주었다.

setKeepOnScreenCondition은 람다 안에 splashState를 넣어서 상태를 관리해 주자.

true일 때는 splash가 열리는 상태가 되고, false일 때에는 splash가 종료된다.

고정값 true 또는 false를 넣으면 splash 화면이 영원히(?) 지속되기 때문에 주의하자.

setKeepOnScreenCondition 말고도 Splash가 종료될 때의 Animation을 설정하는 setOnExitAnimationListener()이 있으므로 사용하고자 하는 분들은 사용해도 좋을 것 같다.

 

구현을 완료하고 Splash 화면을 보면 다음과 같이 나오는 경우도 있을 수 있다.

문제의 화면

 

이렇게 icon이 splash icon의 영역을 벗어나는 경우에는 png icon의 경우에는 따로 일정 너비를 설정해주어야 하는데 vector xml 파일로 구성되어 있는 icon은 <group>을 생성해 너비를 직접 설정해 줄 수 있다.

<vector android:height="300dp" android:viewportHeight="91"
    android:viewportWidth="91" android:width="300dp" xmlns:android="http://schemas.android.com/apk/res/android">
    <group android:pivotX="45" android:pivotY="45" android:scaleX="0.5" android:scaleY="0.5">
        <!-- 여기에 기존의 icon 넣기 -->
    </group>
</vector>

 

필자의 경우에는 viewport가 91이기 때문에 pivot을 viewport의 반인 45로 설정해 주었고, scale은 0.5로 설정해 주었다.

저렇게 설정하면 splash에 얼추 맞을 것이다. 맞지 않는다면 직접 조절해 가면서 찾는 방법밖에 없다.

 

오른쪽이 설정 전, 왼쪽이 설정 후

 

위와 같은 Preview가 뜬다면 정상적으로 적용된 것이다!

 

구현을 완료했으니 바로 실행해서 결과를 보도록 하자.

 

4. 구현 결과

로그인을 완료한 후 앱을 종료했다가 다시 실행했을 때 어떻게 동작하는지 확인해 보자.

 

 

FirebaseAuth의 current user 정보가 저장되기 때문에 자동으로 Plan Screen으로 넘어가진다.

 

정리

  • FirebaseAuth 로그인 정보가 저장된다는 것을 이용해 자동 로그인 기능을 구현해 보았다.
  • 안드로이드 12 버전에서 Splash Screen의 사용법을 알게 되었던 시간이었다.
  • 나중엔 로그아웃도 만들 수도?

참고: https://www.youtube.com/watch?v=Loo4i5IrZ4Y&t=605s

728x90