如何在非Activity类型的启动页(Splash Screen)中添加Progress Bar
给非Activity启动页添加进度条方案
因为你的启动页是通过主题的windowBackground实现的,没法直接在Activity里控制控件,所以可以通过分层Drawable + 后台任务更新进度的方式实现:
1. 重构启动页背景为Layer-List
把原来的单张背景图改成包含进度条的分层Drawable,创建drawable/splash_background.xml:
<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <!-- 原启动页背景图 --> <item android:drawable="@drawable/splash_image"/> <!-- 底部进度条(位置可自行调整) --> <item> <ProgressBar android:id="@+id/splash_progress" android:layout_width="match_parent" android:layout_height="6dp" android:layout_gravity="bottom" android:indeterminate="false" android:max="100" android:progressDrawable="@drawable/splash_progress_style"/> </item> </layer-list>
再创建进度条的样式文件drawable/splash_progress_style.xml:
<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <!-- 进度条背景 --> <item android:id="@android:id/background"> <shape android:shape="rectangle"> <solid android:color="#F0F0F0"/> <corners android:radius="3dp"/> </shape> </item> <!-- 进度条填充 --> <item android:id="@android:id/progress"> <clip> <shape android:shape="rectangle"> <solid android:color="#2196F3"/> <corners android:radius="3dp"/> </shape> </clip> </item> </layer-list>
2. 更新主题配置
把主题里的windowBackground替换成新的分层Drawable:
<style name="Theme" parent="Theme.MaterialComponents.Light.NoActionBar"> <item name="android:windowBackground">@drawable/splash_background</item> <item name="android:statusBarColor">@color/white</item> </style>
3. 后台扫描时更新进度
在应用的入口(比如自定义Application类)里执行PDF扫描任务,同时通过WindowManager获取启动页的ProgressBar并更新进度:
class PDFViewerApplication : Application() { override fun onCreate() { super.onCreate() startPDFScanTask() } private fun startPDFScanTask() { // 用协程执行后台扫描,避免阻塞主线程 CoroutineScope(Dispatchers.IO).launch { val totalPDFs = countTotalPDFs() // 先统计设备上所有PDF总数 var scannedCount = 0 // 递归扫描设备存储 scanDirectory(Environment.getExternalStorageDirectory()) { scannedCount++ val progress = (scannedCount.toFloat() / totalPDFs * 100).toInt() // 更新进度条 updateSplashProgress(progress) } // 扫描完成,跳转到主界面 withContext(Dispatchers.Main) { startActivity(Intent(this@PDFViewerApplication, MainActivity::class.java).apply { addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) }) } } } private fun updateSplashProgress(progress: Int) { runOnUiThread { val windowManager = getSystemService(WINDOW_SERVICE) as WindowManager val decorView = windowManager.currentWindowMetrics?.window?.decorView decorView?.findViewById<ProgressBar>(R.id.splash_progress)?.progress = progress } } // 统计设备上PDF总数的逻辑,需自行实现权限处理 private fun countTotalPDFs(): Int { // 这里写统计逻辑,比如遍历存储目录计数 return 0 } // 扫描目录的逻辑,每找到一个PDF就回调更新计数 private fun scanDirectory(dir: File, onFoundPDF: () -> Unit) { dir.listFiles()?.forEach { file -> if (file.isDirectory) { scanDirectory(file, onFoundPDF) } else if (file.name.endsWith(".pdf", ignoreCase = true)) { onFoundPDF() } } } }
额外提示
- 如果你的应用是Android 12及以上,也可以直接用系统的SplashScreen API,通过
SplashScreen.setOnExitAnimationListener来添加进度条,这种方式更官方且兼容性更好。 - 记得申请
READ_EXTERNAL_STORAGE权限(Android 10及以下),或者使用Scoped Storage(Android 10+)来访问设备文件,否则扫描会失败。 - 进度条的位置、大小、颜色都可以根据需求调整,比如改成圆形进度条放在屏幕中间。
内容的提问来源于stack exchange,提问作者Syed Irfan Hussaini
相关产品推荐
相关产品推荐

