Splash

Kyu hyunSung·2025년 2월 3일

Android

목록 보기
5/10

반갑다 게이들.

오늘은 스플래시에 대해서 간단한 꿀팁만 남기고 갈 예정이다.

아 참고로스플래시 검색하면 래퍼런스 넘쳐나는게

나는 여기서 제일 깔끔한 방법을 알려 줄 것이다.

1. 안드로이드 12

안드로이드 12 전후로 나뉘긴 하다만,

이 형님 지금 사망하셨다.

그냥 웬만하면 안드로이드 12이상이라 생각하자.

2. 흔히 보이는 개짓거리

와 레이아웃 만들었다 개이쁘네~

코드만들어서 연결해야지~~

엄.

딱 봐도 뭔가 불편하다. 우리가 원하는 것은

이렇게 스르륵 나오면서 위아래 헤더에 꽉 차서 이쁘게 나오는 것이다.

3. Splash API

일단 전제조건은,

화려한 모습의 스플래시는 배제해야한다

구글은 기본적인 시스템 스플래시로는 앱 아이콘을 띄우는 것을 추천하는 편이다.

요런 애들마냥 딱 깔끔한 배경에 앱 아이콘만을 보여주는것을 대부분 선호한다

방법을 알아보자

3-1. 기본 설정

build.gradle.kts(Module:app)

  • 신버젼이 나온다면 그거에맞춰 적어주도록 하자.
android {
    compileSdk = 31
}
...

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

3-2. res/values/themes.xml

parent="Theme.SplashScreen"

  • windowSplashScreenBackground
    - 배경이다
  • windowSplashScreenAnimatedIcon
    - 커스텀 아이콘 등록가능
  • windowSplashScreenBrandingimage
    - 하단 브랜딩 이미지 등록가능(근데 이건 좀 구글에서 비추하긴함)

내가 쓴 코드는 이렇다.

    <!-- 스플래시 스크린(시작 화면) 테마 -->
    <style name="SplashTheme" parent="Theme.SplashScreen">
        <item name="windowSplashScreenBackground">@color/Primary_Orange1</item>

        <item name="windowSplashScreenAnimatedIcon">@drawable/ic_transparent_layer_splash</item>

        <!-- 스플래시 스크린 이후 전환될 테마 지정 -->
        <item name="postSplashScreenTheme">@style/Theme.UMC</item>
    </style>
    

여기서 조금 주의깊게 봐야 할 부분이

drawable인데, 만약 그냥 커스텀 아이콘만 떡 하니 올리면 생기는 상황이

뭐 예로들면 이런 아이콘을 커스텀으로 쓰고싶다 치자. 그럼 당연히

이런화면이 나와야 정상이지만 현실은

이따구로 처 나온다. 이유는 단순하다.

AndroidMenfest.xml을 보면

여기 ic_launcher같은 기본 아이콘들이 문제이다.

구글은 기본적으로 앱의 아이콘을 스플래시의 아이콘으로 쓰는 것을 추천한다.

그래서 페이스북과 유튜브도 그런식으로 같은 아이콘에 같은 스플래시화면인것이다.

자, 여기서 우리는 두가지 방법이 있다.

시스템 스플래시 따라가기

제일 쉽고 권장되는 방법이다. 저 동글뱅이는 아이콘 크기니까

만약 여러분들이 만들어놓은 아이콘 디자인이 있다면, 그거를 따로 프로젝트 앱의 아이콘으로 설정해놓으면 알아서 적용된다.

아이콘 적용시키는법은 따로 찾아보도록하자.

배경색과 동일하면 저렇게 티가안난다

커스텀 스플래시

만약 자신이 원하는 아이콘을 하고싶다면, 우선

SVG를 drawable에 넣어두자.

그다음 해야할 행동이

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <color android:color="@android:color/transparent"/>
    </item>
</layer-list>

요런식의 layer-list를 넣고, 투명화를 시키자

그런다음


<item name="windowSplashScreenAnimatedIcon">@drawable/님이 만든 layer-list.xml</item>

그러면

요렇게나온다

???: 아니 그러면 시발 저 아이콘 속성은 하나밖에못쓰는데 그럼 어캄 ?

우리는 Layer-list 를 만들었다.

Layer를 쌓으면 끝나는 일이지않는가 ?

그 밑에 item으로 원하는 아이콘을 추가하자

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <color android:color="@android:color/transparent"/>
    </item>

    <item
        android:gravity="center"
        android:drawable="@drawable/ic_splash_icon"/>
</layer-list>

그러면 이제 완전히 적용된 것이다.

3-3 Main ActiviyVS Splash Activity

여기서부턴 개인의선택이다.

만약 초기 데이터통신이나 다른 서버 작업들이 스플래시 화면 도중 처리가 필요 할 것 같으면

Splash Activty로 만들어주고,

class SplashActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        // 스플래시 스크린 설치는 반드시 super.onCreate 전에
        val splashScreen = installSplashScreen()
        super.onCreate(savedInstanceState)

        // 스플래시 화면 유지를 위한 변수
        var keepSplashOnScreen = true

        // 스플래시 화면 유지 조건 설정
        splashScreen.setKeepOnScreenCondition { keepSplashOnScreen }

        // 로딩 작업을 시뮬레이션
        Handler(Looper.getMainLooper()).postDelayed({
            keepSplashOnScreen = false
            startActivity(Intent(this, OnboardingMainActivity::class.java))
            finish()
        }, 3000) // 3초 딜레이
    }
}

그게아니고 바로 보여주는 거라면

Main Activity에 바로 넣어주도록하자.

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        // 스플래시 스크린 설정은 super.onCreate() 이전에 해야 합니다
        val splashScreen = installSplashScreen()
        
        // 필요한 경우 스플래시 화면을 더 오래 유지할 수 있습니다
        splashScreen.setKeepOnScreenCondition { condition ->
            // true를 반환하면 스플래시 화면이 유지됩니다
            // false를 반환하면 메인 화면으로 전환됩니다
            false  // 기본값으로 바로 전환
        }
        
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }
}

3-4 AndroidManifest.xml

마지막으로 AndroidManifest 속성에 정의해주도록하자.

  • android:name=".Splash.SplashActivity"
    - 클래스 경로지정 (MainActivity면 그걸로 설정)
  • android:theme="@style/SplashTheme"
    - Theme.xml에서 정의 이름 적어주면됨
  • android:exported="true"
    - 다른 앱에서 이 액티비티를 실행할 수 있도록 허용
    무조건 true
  • intent-filter :앱의 시작점 알림
    • action android:name="android.intent.action.MAIN"
      - 메인 진입점
    • <category android:name="android.intent.category.LAUNCHER"
      - 이 액티비티가 앱 런처에 표시
            
       <activity
            android:name=".Splash.SplashActivity"
            android:theme="@style/SplashTheme"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

4.Compose로 만들어보기

방법은 build.gradle에 Splash API 정의하는거랑
Mainifest.xml에 표기하는거까진 똑같음

// app/build.gradle.kts
dependencies {
    // SplashScreen API
    implementation("androidx.core:core-splashscreen:1.0.1")
    
    // Compose 관련 의존성들 (이미 있을 수 있음)
    implementation("androidx.compose.ui:ui:1.5.4")
    implementation("androidx.compose.material3:material3:1.1.2")
    implementation("androidx.compose.runtime:runtime:1.5.4")
    implementation("androidx.navigation:navigation-compose:2.7.5")
    
    // 기타 필요한 의존성들...
}

  • res/values/themes.xml
<!-- res/values/themes.xml -->
<resources>
    <!-- 기본 앱 테마 -->
    <style name="Theme.Barrion" parent="Theme.Material3.DayNight.NoActionBar">
        <!-- 기본 테마 속성들... -->
    </style>
    
    <!-- 스플래시 스크린 테마 -->
    <style name="Theme.Barrion.Splash" parent="Theme.SplashScreen">
        <!-- 스플래시 화면 배경색 -->
        <item name="windowSplashScreenBackground">@color/white</item>
        
        <!-- 스플래시 화면 아이콘 -->
        <item name="windowSplashScreenAnimatedIcon">@drawable/ic_splash</item>
        
        <!-- 스플래시 화면이 사라진 후 사용할 테마 -->
        <item name="postSplashScreenTheme">@style/Theme.Barrion</item>
        
        <!-- 선택적: 브랜딩 이미지 (Android 12부터 지원) -->
        <!-- <item name="windowSplashScreenBrandingImage">@drawable/branding</item> -->
    </style>
</resources>
  • AndroidManifest.xml
<!-- AndroidManifest.xml -->
<application
    android:name=".BarrionApplication"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/Theme.Barrion">
    
    <activity
        android:name=".MainActivity"
        android:exported="true"
        android:theme="@style/Theme.Barrion.Splash">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    
    <!-- 기타 액티비티... -->
</application>
  • MainActivity에 정의
// MainActivity.kt
override fun onCreate(savedInstanceState: Bundle?) {
    val splashScreen = installSplashScreen()
    
    // 초기화 완료 플래그
    var isInitialized = false
    
    // 스플래시 화면 유지
    splashScreen.setKeepOnScreenCondition { !isInitialized }
    
    // 백그라운드 작업
    lifecycleScope.launch {
        delay(1500) // 1.5초 지연
        isInitialized = true // 완료 처리
    }
    
    super.onCreate(savedInstanceState)
    // 나머지 코드...
}

4-1 좀 더 어렵게하는방법

  • ViewModel 생성
// 경로: features/onboarding/src/main/java/com/example/onboarding/presentation/splash/SplashViewModel.kt
// 또는
// 경로: presentation/src/main/java/com/example/presentation/splash/SplashViewModel.kt

package com.example.onboarding.presentation.splash  // 또는 com.example.presentation.splash

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import javax.inject.Inject

/**
 * 스플래시 화면 초기화를 관리하는 ViewModel
 */
class SplashViewModel @Inject constructor(
    // 필요한 레포지토리나 유스케이스 의존성 주입
) : ViewModel() {
    
    private val _isInitialized = MutableStateFlow(false)
    val isInitialized: StateFlow<Boolean> = _isInitialized.asStateFlow()
    
    init {
        initializeApp()
    }
    
    private fun initializeApp() {
        viewModelScope.launch {
            // 1. 필요한 초기화 작업 수행
            // 예: 사용자 인증 상태 확인, 데이터 초기화 등
            
            // 2. 최소 스플래시 화면 표시 시간 보장
            delay(1500) // 1.5초 지연
            
            // 3. 초기화 완료
            _isInitialized.value = true
        }
    }
}
  • MainActivity
// app/src/main/java/com/example/barrion/MainActivity.kt

package com.example.barrion

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.activity.viewModels
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface
import androidx.compose.ui.Modifier
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.lifecycle.lifecycleScope
import androidx.navigation.compose.rememberNavController
import com.example.onboarding.presentation.splash.SplashViewModel  // 또는 com.example.presentation.splash.SplashViewModel
import com.example.ui.theme.BarrionTheme
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch

@AndroidEntryPoint
class MainActivity : ComponentActivity() {
    
    // Hilt로 ViewModel 주입
    private val viewModel: SplashViewModel by viewModels()
    
    override fun onCreate(savedInstanceState: Bundle?) {
        val splashScreen = installSplashScreen()
        
        // 뷰모델의 초기화 상태에 따라 스플래시 화면 표시 조절
        splashScreen.setKeepOnScreenCondition {
            !viewModel.isInitialized.value
        }
        
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        
        lifecycleScope.launch {
            // 초기화가 완료된 후 행동 설정 (필요한 경우)
            viewModel.isInitialized.collectLatest { isInitialized ->
                if (isInitialized) {
                    // 초기화 완료 후 필요한 작업
                    // 예: 첫 실행 여부에 따라 온보딩 화면 또는 메인 화면으로 이동 등
                }
            }
        }
        
        setContent {
            BarrionTheme {
                Scaffold { innerPadding ->
                    Surface(
                        modifier = Modifier
                            .fillMaxSize()
                            .padding(innerPadding),
                        color = MaterialTheme.colorScheme.background
                    ) {
                        // 앱의 메인 네비게이션
                        val navController = rememberNavController()
                        BarrionNavHost(navController = navController)
                    }
                }
            }
        }
    }
}
  • 모듈간 의존성 설정
// app/build.gradle.kts

dependencies {
    implementation(project(":features:onboarding"))  // 또는 implementation(project(":presentation"))
    implementation("androidx.core:core-splashscreen:1.0.1")
    // 기타 의존성...
}

출처

[Android] Android12 Splash Screen (안드로이드12 스플래시)
스플래시 화면
[Kotlin][Android] Splash Screen(로딩 화면) 구현하기

profile
디지털 치매 예방

0개의 댓글