2026'da Android SplashScreen API'si: beyaz flaş olmadan soğuk başlangıç
Android'in SplashScreen API'sine pratik bir rehber — tema kurulumu, kimsenin okumadığı animasyonlu ikon boyut sınırları ve henüz hazır olmayan veriler için keepOnScreenCondition.
Her Android uygulaması, siz istemiş olsanız da olmasanız da Android 12’den beri bir açılış ekranı gösteriyor. Sistem, kullanıcı başlatıcıya dokunduğu anda uygulama ikonunuzdan ve tema renklerinizden otomatik olarak birini çizer — asıl sahip olduğunuz seçim, varsayılanı kabul etmek mi yoksa androidx.core.splashscreen’i göndermeyi düşündüğünüz ekranı çizecek şekilde yapılandırmak mı olduğudur. Gördüğüm kötü açılış ekranlarının çoğu, birisi onları kötü tasarladığı için kötü değil. Kimse hiçbir şeyi yapılandırmadığı ve sistemin en iyi tahmini boşluğu doldurduğu için kötüler.
Granyn’i inşa ederken bu yazıdaki her hatayı yaptım; panosu ilk kare gösterilmeye değer olmadan önce Room’dan yüklenen bir ilk bakiye rakamına ihtiyaç duyuyor. Beyaz flaşı ve açılış ekranının bir tık fazla asılı kalmasını durduran kurulum bu.
Açılış ekranını neden istemeseniz de alırsınız
Android 12 (API 31) ile başlayarak, platform her soğuk başlangıcı yakalar ve Activity’niz içerik görünümünü bağlamadan önce sistem tarafından çizilen bir açılış penceresi gösterir. Bu atlayabileceğiniz bir kütüphane özelliği değil — varsayılan framework davranışıdır. androidx.core.splashscreen’in size verdiği şey, o sistem penceresini API 23’e kadar tutarlı bir şekilde yapılandırmanıza izin veren bir uyumluluk katmanıdır; aksi halde 12+ sürümlerde gerçeğini, daha eski sürümlerde ise düz beyaz veya siyah bir dikdörtgen alırsınız.
Kurulumu atlarsanız sistemin varsayılanını alırsınız: temanızdan çekilen düz bir renk üzerinde başlatıcı ikonunuz, animasyon yok, ne kadar süre kalacağı üzerinde kontrol yok. Bu bozuk değil ama markalı bir uygulamanın istediği şey de nadiren budur ve uyumluluk kütüphanesi olmadan 12 öncesi cihazlarda, temanız uygulanmadan önce rahatsız edici bir beyaz flaş olabilir.
Temayı bağlamak
Açılış ekranı neredeyse tamamen XML’de, setContentView çalışmadan önce uygulanan bir tema olarak yapılandırılır:
<!-- res/values/themes.xml -->
<style name="Theme.App.Starting" parent="Theme.SplashScreen">
<item name="windowSplashScreenBackground">@color/brand_background</item>
<item name="windowSplashScreenAnimatedIcon">@drawable/splash_icon</item>
<item name="windowSplashScreenAnimationDuration">500</item>
<item name="postSplashScreenTheme">@style/Theme.App</item>
</style>
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
installSplashScreen()
super.onCreate(savedInstanceState)
setContent { AppTheme { GranynApp() } }
}
}
installSplashScreen()’in super.onCreate()’ten önce çalışması gerekir — sonra çağırırsanız uyumluluk kütüphanesi pencereyi zamanında yakalayamaz ve sessizce sistem varsayılanına geri dönersiniz. postSplashScreenTheme, açılış ekranı kapatıldıktan sonra pencerenin geçtiği temadır; bunu ayarlamayı unutmak Activity’nizin, gerçek içeriğe uygulanmış açılış-penceresi özellikleriyle bir süre takılı kalmasına neden olur.
Kimsenin ısırılana kadar okumadığı ikon boyut sınırı
windowSplashScreenAnimatedIcon’ın sert bir kısıtı vardır: drawable, 240×240dp’lik bir dairenin içinde çizilir ve daha büyük olan her şey ölçeklenmek yerine sessizce kırpılır. Bu, gördüğüm en yaygın açılış ekranı hatasıdır — biri, 72×72dp görünür daire içinde 108×108dp bir ön plan katmanı için tasarlanmış uyarlanabilir başlatıcı ikonunu yeniden kullanır ve ya açılış sınırının ötesine taşar ya da tam olarak tek bir ekran yoğunluğunda bozuk görünen bir şekilde kırpılır.
Çözüm, başlatıcı varlığını yeniden amaçlamak yerine, 240dp kısıtı için kendi başına boyutlandırılmış ve ortalanmış özel bir açılış ikonudur:
res/drawable/splash_icon.xml (tek vektör, uyarlanabilir katman yok, 240x240dp'ye sığar)
İkonun animasyonlu olması gerekiyorsa (bir AnimatedVectorDrawable), aynı boyut tavanı geçerlidir ve windowSplashScreenAnimationDuration, platformun onu bekleyeceği süreyi sınırlar — API 31+‘ta en fazla 1000ms, gerçi uyumluluk kütüphanesi eski API’lerde bu tavanı aynı şekilde uygulamaz, ki bu da yalnızca tek bir işletim sistemi sürümünü kontrol ederseniz kendi tutarsız test kaynağınız olur.
Veri hazır olmadığında: keepOnScreenCondition
Granyn için asıl önemli olan kısım ikon değildi — zamanlamaydı. Açılış ekranı, ilk kare çizilmeye hazır olur olmaz kapanır ve bu, bir Compose ekranı için ViewModel’in gösterecek bir şeyi olmadan önce olabilir. Kendi haline bırakıldığında, bu, açılış ekranı kaybolduktan sonra bakiyenin yarım saniye sonra yüklenmesine kadar boş bir pano flaşı üretir — bu ekstra bir tık daha kalan açılış ekranından daha kötüdür.
SplashScreen.setKeepOnScreenCondition, bir koşul temizlenene kadar açılış penceresini açık tutar:
class MainActivity : ComponentActivity() {
private val viewModel: DashboardViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
val splashScreen = installSplashScreen()
super.onCreate(savedInstanceState)
splashScreen.setKeepOnScreenCondition {
!viewModel.isReady.value
}
setContent { AppTheme { GranynApp(viewModel) } }
}
}
Buradaki isReady, panonun bakiyesi için ilk Room sorgusu gerçekten sonuç döndürdüğünde true’ya dönen bir StateFlow<Boolean>’dır. Koşul her karede yoklanır, bu yüzden onu ucuz bir boolean okuması olarak tutun — asla lambda içinde doğrudan bir suspend çağrısı veya bir veritabanı isabeti olmasın.
İki şey bunu sonsuza kadar uygulamayı askıda tutmanın bir yolu değil, güvenli hale getiriyor. Birincisi, bir tavan koyun — eğer isReady hiç true olmazsa (bozuk bir veritabanı, takılan bir sorgu), açılış ekranı zaman aşımına uğramalı ve arayüzün, sonsuza kadar donuk kalmak yerine kendi yükleme veya hata durumunu göstermesine izin vermelidir:
private val isReady = MutableStateFlow(false)
init {
viewModelScope.launch {
withTimeoutOrNull(2000) {
dashboardFlow.first { it != null }
}
isReady.value = true
}
}
İkincisi, setKeepOnScreenCondition yalnızca çıkışı geciktirir — girdiyi veya uygulamanın geri kalanının başlamasını engellemez, bu yüzden onu ağacın daha aşağısındaki gerçek bir yükleme durumunun yerine kullanmayın. Size, uygulamanın donduğu izlenimi vermeden önce en fazla birkaç yüz milisaniyelik bir sabır satın alır.
Önemliyse, çıkış animasyonu
Varsayılan olarak açılış görünümü yalnızca kaldırılır. Çıkışta özel bir solma veya ölçekleme marka hissi için önemliyse, setOnExitAnimationListener size, kendiniz kapatmadan önce animasyon uygulayabileceğiniz gerçek açılış görünümünü verir:
splashScreen.setOnExitAnimationListener { splashView ->
splashView.view.animate()
.alpha(0f)
.setDuration(200)
.withEndAction { splashView.remove() }
.start()
}
Sonda splashView.remove()’u atlamak, açılış görünümünü içeriğinizin üzerinde süresiz olarak bağlı bırakır — sıcak yeniden yükleme geliştirme döngüsünde iyi görünen ama sonra kalıcı olarak donmuş bir başlangıç ekranı gönderen tek satırlık bir kaçırma.
Gerçekten önemli olan
Hiçbir şeyi yapılandırmadığınızda sistemin size verdiği varsayılan bozuk değil ama kasıtlı da değil — açılış temasını super.onCreate()’ten önce kurun, ikonu yeniden kullanılan uyarlanabilir başlatıcı ikonu yerine gerçek 240dp kısıtı için boyutlandırın ve keepOnScreenCondition’a yalnızca ilk karenin gerçekten ihtiyaç duyduğu belirli, zamanlı bir veri parçası olduğunda başvurun. Çıkış animasyonu tamamen atlanması kolay olan kısımdır ve çoğu uygulama için bu doğru karardır — buradaki kazanım kendi başına hareket eklemek değil, beyaz flaşı ve boş pano titremesini kaldırmaktır.
// İlgili okumalar
Günlükten dahası
Jetpack Compose'da Material You dinamik renk: duvar kağıdı kazandığında marka renginizi korumak
dynamicColorScheme() paletinizi kullanıcının duvar kağıdından türetilen biriyle değiştirir. Marka renklerini kaybetmek yerine uyumlaştırmak için pratik bir rehber.
Android In-App Review API: sıkıcı olmadan puan istemek
Google'ın In-App Review API'sine pratik bir rehber — gerçekte nasıl çalıştığı, ne zaman tetiklenmesi gerektiği ve alışılmış 'bizi puanlayın' popup'ının Play Store puanınızı sessizce nasıl zedelediği.
2026'da Android'de erişilebilirlik: gerçekten uygulanan bir TalkBack ve Compose semantiği kontrol listesi
2026 için pratik bir Android erişilebilirlik kontrol listesi — TalkBack, Compose semantiği, dokunma hedefleri ve her ekranda yayınlamadan önce yaptığım test turu.