美文网首页UItempAndroid
AndroidX SplashScreen:全新App启动页面

AndroidX SplashScreen:全新App启动页面

作者: goodl | 来源:发表于2021-11-07 17:45 被阅读0次

    Android 12 添加了 SplashScreen API,它可为所有应用启用新的应用启动动画。这包括启动时的进入应用运动、显示应用图标的启动画面,以及向应用本身的过渡。

    Android 12 上效果固然不错,可如果不兼容低版本系统的话,实属鸡肋。
    AndroidX 推出了一个叫 SplashScreen 的同名 API,很显然它就是用来兼容低版本的 SplashScreen 功能库。

    现在 App 大多点击图标启动后,一般都会有几个固定的界面:

    • Splash 启动页,展示 logo
    • Advertising 广告页,展示开屏广告、节日活动等
    • Guide 用户引导页面,展示重点功能,一般只展示一次
    abc.png

    如果不适配 SplashScreen,在 Android 12 上,系统默认为 App 生成的启动页,加上 App 自身的启动页,就会有两个启动页,显然不是我们期望的效果。
    同时为了兼容低版本,这时候就需要引入 SplashScreen 库:

    1.0 引入 SplashScreen 库

    目前最新版本为 1.0.0-alpha02,可在 官网 查询最新版本

    implementation "androidx.core:core-splashscreen:1.0.0-beta01"
    

    1.1 添加样式

    themes.xml:

    <style name="Theme.TestSplashScreen.Starting" parent="Theme.SplashScreen">
        # 启动画面的背景,默认使用 windowBackground
        <item name="windowSplashScreenBackground">@color/...</item>
        # 指定 icon,支持静态 drawable 或动画 vector drawable
        <item name="windowSplashScreenAnimatedIcon">@drawable/...</item>
        # 动画 icon 时长,上限 1000 ms
        <item name="windowSplashScreenAnimationDuration">1000</item>
        # 启动画面退出后 Activity 的主题
        <item name="postSplashScreenTheme">@style/Theme.TestSplashScreen.Launcher</item>
    </style>
    
    <style name="Theme.TestSplashScreen.Launcher">
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
        <item name="android:windowTranslucentStatus">true</item>
        <item name="android:windowTranslucentNavigation">true</item>
    </style>
    

    AndroidManifest.xml:

    <activity
        android:name=".LauncherActivity"
        android:exported="true"
        android:screenOrientation="portrait"
        android:theme="@style/Theme.TestSplashScreen.Starting">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    

    1.2 修改现有的启动页 LauncherActivity

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val splashScreen = installSplashScreen() // 在 setContentView 之前调用
        setContentView(R.layout.activity_launcher) // 可选,可删除该行
        ...
    }
    

    这样最基本的适配就结束了。

    2.2 延长启动页面

    通过 SplashScreen#setKeepVisibleCondition 延长启动页

    private var keepOnScreen = AtomicBoolean(true)
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val splashScreen = installSplashScreen()
        setContentView(R.layout.activity_launcher)
    
        lifecycleScope.launch {
            delay(2000)
            keepOnScreen.compareAndSet(true, false)
        }
        splashScreen.setKeepOnScreenCondition { keepOnScreen.get() }
    }
    

    这样,启动页延长至 2 秒

    2.2 定制启动页退场动画

    通过 SplashScreen#setOnExitAnimationListener 设置动画效果
    这里分别设置了,SplashScreen 页面和中间 icon 的退场动画

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val splashScreen = installSplashScreen()
        setContentView(R.layout.activity_launcher)
    
        splashScreen.setOnExitAnimationListener { provider ->
            showSplashIconExitAnimator(provider.iconView)
            // 两个动画的时长可以不一样,这里监听 splashScreen 动画结束
            showSplashExitAnimator(provider.view) {
                provider.remove()
                // 进入主界面,顺便给个 FadeOut 退场动画
                startActivity(Intent(this, MainActivity::class.java))
                finish()
                overridePendingTransition(0, R.anim.fade_out)
            }
        }
    }
    
    // splash screen view 退场动画:透明度 + 揭露
    private fun showSplashExitAnimator(view: View, onExit: () -> Unit) {
        val alphaOut = ObjectAnimator.ofFloat(view, View.ALPHA, 1f, 0.2f)
    
        val cx = view.width / 2
        val cy = view.height / 2
        // get the start radius for the clipping circle
        val startRadius = hypot(cx.toDouble(), cy.toDouble()).toFloat()
        val revealOut = ViewAnimationUtils.createCircularReveal(
            view, cx, cy, startRadius, 0f
        )
    
        AnimatorSet().apply {
            duration = 300
            interpolator = DecelerateInterpolator()
            playTogether(alphaOut, revealOut)
            doOnEnd { onExit() }
        }.also { it.start() }
    }
    
    // splash icon 退场动画:透明度 + 缩放
    private fun showSplashIconExitAnimator(view: View) {
        val alphaOut = ObjectAnimator.ofFloat(view, View.ALPHA, 1f, 0.2f)
        val scaleOut = ObjectAnimator.ofFloat(
            view,
            View.SCALE_X,
            View.SCALE_Y,
            Path().apply {
                moveTo(1f, 1f)
                lineTo(0.2f, 0.2f)
            }
        )
    
        AnimatorSet().apply {
            duration = 300
            interpolator = DecelerateInterpolator()
            playTogether(alphaOut, scaleOut)
        }.also { it.start() }
    }
    

    参考:
    https://developer.android.com/guide/topics/ui/splash-screen/migrate
    https://developer.android.com/about/versions/12/features/splash-screen

    相关文章

      网友评论

        本文标题:AndroidX SplashScreen:全新App启动页面

        本文链接:https://www.haomeiwen.com/subject/rcmezltx.html