最新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中引用
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'
  2. 定义主题:

xml 复制代码
    <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:
xml 复制代码
        <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代码参考:
kotlin 复制代码
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

相关推荐
stevenzqzq7 小时前
android中dp和px的关系
android
一一Null9 小时前
Token安全存储的几种方式
android·java·安全·android studio
JarvanMo10 小时前
flutter工程化之动态配置
android·flutter·ios
时光少年12 小时前
Android 副屏录制方案
android·前端
时光少年12 小时前
Android 局域网NIO案例实践
android·前端
alexhilton12 小时前
Jetpack Compose的性能优化建议
android·kotlin·android jetpack
流浪汉kylin13 小时前
Android TextView SpannableString 如何插入自定义View
android
火柴就是我14 小时前
git rebase -i,执行 squash 操作 进行提交合并
android
你说你说你来说15 小时前
安卓广播接收器(Broadcast Receiver)的介绍与使用
android·笔记
你说你说你来说15 小时前
安卓Content Provider介绍及使用
android·笔记