• 关于安卓12闪屏页适配(一)


    背景

    老生常谈的内容,启动页适配。
    安卓12系统开始,启动app,系统就贴心给你上一个“系统级别”的启动页。遮住了原有的众多app中的启动闪屏页大部分事件。导致很多app的自定义闪屏页显示时间都缩短,甚至无法查看,因此需要进行适配。

    环境

    与环境无关,你项目能跑进行
    编译sdk需要在12以上

    思路

    从官方的建议,有以下解决方法:
    (1)旧业务全部转移到新适配启动页
    (2)沿用旧的启动页(效果不是太好)
    本文,将会使用(2)的方法折中实现。

    实现思路

    (一)引入splashscreen进行全方位适配
    build.gradle
    引入implementation “androidx.core:core-splashscreen:1.0.0”
    启动页中,setContentView()方法前,调用方法:
    installSplashScreen()
    然后,设置SplashScreen对象的监听,如:
    setOnExitAnimationListener()
    setKeepOnScreenCondition()


    setKeepOnScreenCondition是保持安卓12系统启动页的开关,代码如下:

    mSplashScreen.setKeepOnScreenCondition(object : 
    			SplashScreen.KeepOnScreenCondition {
                    override fun shouldKeepOnScreen(): Boolean {
                        Log.d("Splash", "Splash shouldKeepOnScreen")
                        return false
                    }
                })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    return false代表不保持,return true代表保持。正常情况下,return 了false,就会触发方法:
    setOnExitAnimationListener(),特殊情况,有些系统rom阉割了这一部分,就会没有这个回调,这个逻辑也是要纳入适配的范畴。
    然后定义一个theme,用作启动页:

        
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    核心代码如下:

        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            // 初始化操作(必须放在setContentView()之前)
            val needToShow = isNeedShowSplash()
            val mSplashScreen: SplashScreen? = if (needToShow) installSplashScreen() else null
            setContentView(R.layout.activity_splash)
            if (needToShow && mSplashScreen != null) {
                // Splash展示完毕的监听方法
                mSplashScreen.setOnExitAnimationListener(object : SplashScreen.OnExitAnimationListener {
                    override fun onSplashScreenExit(splashScreenViewProvider: SplashScreenViewProvider) {
                        Log.d("Splash", "Splash onSplashScreenExit")
                        mHadExitAnim = true
                        splashScreenViewProvider.remove()
                        toMainActivity()
                    }
                })
                mSplashScreen.setKeepOnScreenCondition(object : SplashScreen.KeepOnScreenCondition {
                    override fun shouldKeepOnScreen(): Boolean {
                        Log.d("Splash", "Splash shouldKeepOnScreen")
                        return false
                    }
                })
    
                MainScope().launch {
                    delay(200)
                    if (mHadExitAnim) {
                        return@launch
                    }
                    //没有,按普通逻辑执行
                    mHadExitAnim = true
                    toMainActivity()
                }
            } else {
                toMainActivity()
            }
        }
    
        private fun toMainActivity() {
            Handler(Looper.getMainLooper()).postDelayed(Runnable {
                startActivity(Intent(this@SplashActivity, MainActivity::class.java))
            }, 3000)
        }
    
        /**
         * 是否需要启动闪屏页
         * */
        fun isNeedShowSplash(): Boolean {
            return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    这里有个MainScope的delay(200),是用于适配一些国产系统rom阉割导致setOnExitAnimationListener没有回调的情况,不可缺少,否则部分机型不能进入下一个页面。

    (二)使用原生进行适配
    原生适配,思路和(一)大致一样。区别就是在于,不引入三方依赖进行适配了,仅仅在页面开始绘制的一瞬间,把系统的启动页面退出。核心代码如下:

        private var mHadExitAnim = false
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_splash2)
    
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
                Log.d("Splash", "Splash 2 安卓12以上")
                splashScreen.setOnExitAnimationListener {
                    Log.d("Splash", "Splash 2 setOnExitAnimationListener")
                    it.remove()
                    mHadExitAnim = true
                    toMainActivity()
                }
    
                MainScope().launch {
                    delay(200)
                    if (mHadExitAnim) {
                        return@launch
                    }
                    //没有,按普通逻辑执行
                    mHadExitAnim = true
                    toMainActivity()
                }
            } else {
                Log.d("Splash", "Splash 2 安卓12以下")
                toMainActivity()
            }
    
    
        }
    
        private fun toMainActivity() {
            Handler(Looper.getMainLooper()).postDelayed(Runnable {
                startActivity(Intent(this@SplashActivityOnly, MainActivity::class.java))
            }, 3000)
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    总结

    目前比较常规的,就是这几种方法了。对于(一)方法,定制性高,不过就强制使用了系统的闪屏页了。对于(二),仅仅是减少系统闪屏页出现的时长。
    以上就是适配启动页的一些思路。最后附上官方链接:
    https://developer.android.google.cn/guide/topics/ui/splash-screen/migrate?hl=zh-cn

    that’s all-------------------------------------------------------------------------------------------

  • 相关阅读:
    Redis 数据类型
    彻底搞懂WeakMap和Map
    GO编程实践:如何高效使用变量
    代码随想录算法训练营第五十七天| 392.判断子序列 115.不同的子序列
    戏说数据仓库,商业智能BI中数据仓库的本质是什么?
    世界首部使用USB-C接口iPhone面世
    大数据必学Java基础(九十):通过反射获取运行时类的完整结构
    HTML 图像
    #gStore-weekly | SPARQL 执行过程中高级查询函数的求值(上)
    什么是闭包
  • 原文地址:https://blog.csdn.net/motosheep/article/details/132908312