最新android icon和splashScreen适配兼容至2024android

android在12做了splashScreen的变动,即,android12+有自带的screenSplash过渡,不论你是否自己有变化,都会插入该动画。
android8做了icon的巨大变动。13做了图标的主题兼容。

一、icon制作

制作

使用android自带的工具,对着res目录,右键,new,image Asset:

  1. 模式默认Launcher Icons(Adaptive and Legacy);
  2. Path选择你的切图或者svg更好;
  3. 一般可能需要Resize一下,调整图片的占比(本人实测80%~85%左右,各自根据实际调整),否则显示太靠边不好看;
    请添加图片描述
  4. Background layer一般选择纯色,比如FFFFFF。
    请添加图片描述
    然后Next,就生成了。
    最后在AndroidManifest xml中引用
        android:icon="@mipmap/new_icon"
        android:roundIcon="@mipmap/new_icon_round"
兼容android13主题变化

为了兼容android13的主题做法,给2个anydpi-v26,xml添加monochrome标签。直接引用new_icon_foreground即可。
可以参考下图。
请添加图片描述

为何普通xml和round xml的内容一模一样?

然而,我们查看这2个xml,就会有疑问,为什么,我们发现普通xml和round xml的内容一模一样?

经过查询stackoverflow,得到了解释,我用大白话讲一遍:
对于v26以下的手机,anydpi-v26这个目录自然是不会被引用的,因此,我们androidManifest.xml中@mipmap/new_icon或者new_icon_round,都将直接引用到具体dpi目录的具体图片本身。
而高于26的版本,他系统的round图标的方式,并不是根据round本身图来决定,则是始终使用foregound图+background图拼成的。
请添加图片描述
因此,解释了为什么2个xml一模一样,而且为什么我们需要在代码里面留下new_icon和new_icon_round这2种图的原因,这是为了低版本自己去取而留下的。
这也解释了引用帖子https://blog.csdn.net/minping9101/article/details/129436383中提到的huawei或者某些应用市场,他们默认会从mipmap中取我们androidmanifest的icon名字对应的图标,就相当于低版本的android一样。

如果不用兼容26以下。比如minSdk就是26。则可以删除new_icon和new_icon_round了。

最后,
如果你觉得图片太多,可以删除,google store的图;可以删除mdpi的目录和xxxdpi的目录图。一般情况用不到。

二、SplashScreen

如果是个全新app,不做这个兼容,在android12以下老版本就会白屏比较久;在以上就默认添加了过渡。
如果是老app,你有一个自己品牌过度activity,那么在android12以上就会过度2次。
所以还是有必要兼容处理一下的。这里给出我个人的解决代码,以便以后快速复制新项目。

如果我们忽略官方那种动来动去的效果的话,很简单。如果需要使用那种动画和自定义延长时间等特殊则参考文章末尾链接自行研究,一般情况我们不需要动画。

  1. 引入gradle:
    implementation 'androidx.core:core-splashscreen:1.0.1'
  1. 定义主题:
    <style name="SplashTheme" parent="Theme.SplashScreen">
        <item name="postSplashScreenTheme">@style/YourAppTheme</item>
        <item name="windowSplashScreenAnimatedIcon">@drawable/ic_splash</item>
        <item name="windowSplashScreenBackground">#ffffff</item>
        <item name="windowSplashScreenAnimationDuration">1000</item>
<!--        <item name="android:windowBackground">@drawable/bg_splash_window</item>-->
    </style>

一般情况,你的YourAppTheme app主题已经继承了Theme.xxx.NoBar等。如果没有,则继承Theme.AppCompat。否则报错windowSplashScreenAnimatedIcon 提供你的图片。这里有一点要求。因此,你需要让图画居中,四周留白要多一点,自行调整。

品牌图片:尺寸必须为 200×80 dp。
具有图标背景的应用图标:尺寸必须为 240×240 dp,且位于直径 160 dp 的圆圈内。
无图标背景的应用图标:尺寸必须为 288×288 dp,并且位于直径 192 dp 的圆圈内。
例如,如果图片的完整尺寸为 300×300 dp,则图标需要位于直径 200 dp 的圆圈内。圆圈以外的所有内容都会变为不可见(已遮盖)。

  1. 引入AndroidManifest的启动activity:
        <activity
            android:name="com.xxx.XXSplashActivity"
android:configChanges="screenSize|keyboard|keyboardHidden|fontScale|locale|orientation|screenLayout|uiMode|navigation"
            android:exported="true"
            android:screenOrientation="portrait"
            android:theme="@style/SplashTheme">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
  1. SplashActivity代码参考:

private var lastLauncherApp = 0L

class SplashActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        val splashScreen = installSplashScreen()
        super.onCreate(savedInstanceState)
        setContentView(createLayout())
        splashScreen.setKeepOnScreenCondition { true }
        launcherApp(intent)
    }

    /**
     * 创建基础界面。无需设置图标。通过主题搞定的。
     */
    open fun createLayout(): ViewGroup {
        val layout = RelativeLayout(this)
        layout.layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
        return layout
    }

    override fun onNewIntent(intent: Intent?) {
        super.onNewIntent(intent)
        launcherApp(intent)
    }

    fun goActivity() {
    	startActivityFix(Intent(this, MainActivity::class.java))
    }

    fun launcherApp(intent: Intent?) {
        //直接从android Studio run起来会初始化多次。
        val cur = System.currentTimeMillis()
        if (cur - lastLauncherApp > 1000L) {
            lastLauncherApp = cur
        } else {
            return
        }

        goActivity()

        this.finish()
    }
}

//某个Util类:
fun Context.startActivityFix(intent: Intent, opts:Bundle? = null) {
    if (this !is Activity) {
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
    }
    try {
        ActivityCompat.startActivity(this, intent, opts)
    } catch (e:Exception) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
            // Android 10 或更高版本
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        } else {
            // Android 10 以下版本
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP)
        }
        ActivityCompat.startActivity(this, intent, opts)
    }
}

参考资料:
https://blog.csdn.net/minping9101/article/details/129436383
https://zhuanlan.zhihu.com/p/556819230?eqid=e969f5150007822f0000000664868205&utm_id=0
https://developer.android.google.cn/develop/ui/views/launch/splash-screen?hl=zh-cn

相关推荐

  1. android 手机平板如何

    2024-03-11 20:54:01       28 阅读
  2. Android 14 之 - 隐式/显示 Intent 广播

    2024-03-11 20:54:01       20 阅读
  3. Android 手机屏幕方式原理

    2024-03-11 20:54:01       58 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-03-11 20:54:01       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-03-11 20:54:01       100 阅读
  3. 在Django里面运行非项目文件

    2024-03-11 20:54:01       82 阅读
  4. Python语言-面向对象

    2024-03-11 20:54:01       91 阅读

热门阅读

  1. Spring Data的Repositories----Query by Example

    2024-03-11 20:54:01       42 阅读
  2. L1阶段题解方法总结

    2024-03-11 20:54:01       31 阅读
  3. 使用docker安装logstash的具体方法

    2024-03-11 20:54:01       38 阅读
  4. [蓝桥杯]接龙数列(C语言)

    2024-03-11 20:54:01       42 阅读
  5. docker使用笔记

    2024-03-11 20:54:01       39 阅读
  6. LeetCode_Hot100_栈_155最小栈_Python

    2024-03-11 20:54:01       40 阅读