Android 12之启动画面Splash Screens -- 适配
Posted 言并肃
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 12之启动画面Splash Screens -- 适配相关的知识,希望对你有一定的参考价值。
android 12之启动画面Splash Screens(一) -- 适配
从 Android 12 开始,在所有应用的冷启动和温启动(应用重启)期间,系统一律会显示默认启动画面。系统默认启动画面由应用的启动图标和主题的 windowBackground
构成。
在搭载 Android 12 或更高版本的设备上未适配启动画面Splash Screens,则体验效果会受到很大影响。
启动画面的工作流程
当用户启动应用而应用的进程未运行(冷启动)或 activity 尚未创建(温启动)时,会发生以下事件。(在热启动期间从不显示启动画面)
- 系统使用指定主题以及自定义的任何动画显示启动画面(包括应用图标、图标背景和窗口背景),实际就是在
DecorView
添加一个SplashScreenView
用以显示启动画面。 - 当应用准备就绪时,系统会关闭启动画面并显示应用的
ContentView
。
启动画面的元素
使用启动画面的元素需要注意以下几点:
-
应用图标可以是静态或带动画的(矢量)图标,默认为应用的启动图标。动画的时长建议不超过 1000毫秒。
Android示例入门套件 news_avd_02.xml:
-
可以为应用图标添加图标背景;图标背景为了过渡图标与窗口背景之间的颜色对比度。如果使用一个自适应图标,当该图标与窗口背景之间的对比度足够高时,就会显示其背景。
-
与自适应图标一样,前景的三分之一被遮盖。
-
窗口背景由不透明的单色组成。如果窗口背景已设置且为纯色,则未设置相应的属性时默认使用该背景。
-
品牌图片尺寸应为 200×80 dp,带有图标背景的应用图标尺寸应为 240×240 dp(同时位于直径 160 dp 的圆圈内),图标背景的应用图标尺寸应为 288×288 dp(同时位于直径 192 dp 的圆圈内)。
品牌logo(200*80):
图标+图标背景+窗口背景+品牌logo的效果:
-
动画图标格式必须是动画形式的矢量可绘制对象 (AVD) XML。 尺寸:AVD 图标的大小必须是自适应图标大小的四倍,如下所示:
图标面积必须是 432 dp(即 108 dp 的 4 倍,108 dp 是无遮盖自适应图标的面积)。图片内部三分之二的区域在启动器图标上可见,并且必须是 288 dp(即 72 dp 的四倍,72 dp是自适应图标内部遮盖区域的面积)。 建议动画的时长不超过 1,000 毫秒。可以使用延迟启动,但不能超过 166毫秒。
启动画面的主题相关属性
windowSplashScreenBackground
属性单色填充背景:<item name="android:windowSplashScreenBackground">@android:color/holo_orange_light</item>
windowSplashScreenAnimatedIcon
替换默认的窗口中心的启动画面图标。如果该对象可通过AnimationDrawable
和AnimatedVectorDrawable
呈现动画效果和进行绘制,还需要设置windowSplashScreenAnimationDuration
以在显示起始窗口的同时播放动画。<item name="android:windowSplashScreenAnimatedIcon">@drawable/news_avd_v02</item>
windowSplashScreenAnimationDuration
指定启动画面图标动画的时长。设置后对实际启动画面的显示时间不会有影响,可以在自定义启动画面退出动画时使用SplashScreenView#getIconAnimationDuration
检索图标动画的时长。如需了解详情,请参阅让启动画面显示更长时间。<item name="android:windowSplashScreenAnimationDuration">500</item>
windowSplashScreenIconBackgroundColor
设置启动画面图标后面的背景。当窗口背景与图标之间的颜色对比度不够高时,起到颜色过渡的作用。<item name="android:windowSplashScreenIconBackgroundColor">@android:color/holo_purple</item>
windowSplashScreenBrandingImage
设置要显示在启动画面底部的品牌logo图片。<item name="android:windowSplashScreenBrandingImage">@drawable/alimama</item>
自定义启动画面的退出动画
通过 Activity.getSplashScreen()
自定义启动画面的退出动画:
getSplashScreen().setOnExitAnimationListener(splashScreenView ->
final ObjectAnimator slideUpAnimator = ObjectAnimator.ofFloat(
splashScreenView,
View.TRANSLATION_Y,
0f,
-splashScreenView.getHeight()
);
slideUpAnimator.setInterpolator(new AnticipateInterpolator());
slideUpAnimator.setDuration(200L);
// 需要在动画结束后移除SplashScreenView
slideUpAnimator.addListener(new AnimatorListenerAdapter()
@Override
public void onAnimationEnd(Animator animation)
splashScreenView.remove();
);
slideUpAnimator.start();
);
更多请参考自定义用于关闭启动画面的动画
迁移启动画面(自定义启动画面)
- 在
build.gradle
文件中,更改您的compileSdkVersion
,并在依赖项中添加SplashScreen
compat库。build.gradle android compileSdkVersion 31 ... dependencies ... implementation 'androidx.core:core-splashscreen:1.0.0-beta02'
- 创建一个父级为
Theme.SplashScreen
的主题,并将postSplashScreenTheme
的值设为Activity
应使用的主题,同时将windowSplashScreenAnimatedIcon
设为可绘制对象或带动画的可绘制对象。其他属性可视需要进行设置。
如果要在图标下添加背景颜色,您可以使用<style name="Theme.Component.Start" parent="Theme.SplashScreen"> <item name="android:windowSplashScreenAnimatedIcon">@drawable/news_avd_v02</item> <item name="android:windowSplashScreenAnimationDuration">200</item> <item name="android:windowSplashScreenBackground">@android:color/holo_orange_light</item> <item name="android:windowSplashScreenIconBackgroundColor">@android:color/holo_purple</item> <item name="android:windowSplashScreenBrandingImage">@drawable/ic_logo</item> <!-- 必须 --> <item name="postSplashScreenTheme">@style/Theme.Component</item> </style>
Theme.SplashScreen.IconBackground
主题及设置windowSplashScreenIconBackground
属性。 - 在清单中,将启动 activity 的主题替换为您在上一步创建的主题。
<manifest> <application android:theme="@style/Theme.App.Start"> <!-- or --> <activity android:theme="@style/Theme.App.Start"> ...
- 在启动 activity 中,先调用
installSplashScreen
,然后再调用super.onCreate()
。public class MainActivity extends Activity @Override protected void onCreate(Bundle savedInstanceState) //处理splash screen过渡 SplashScreen splashScreen = SplashScreen.installSplashScreen(this); super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);
installSplashScreen
会返回启动画面对象,您可以根据需要使用该对象自定义动画,或让启动画面在屏幕上显示更长时间。Google建议不超过1000毫秒。
*必须按以上步骤执行,否则出现异常现象。
自定义启动画面的异常情况
- 在自定义SplashScreen画面后,启动应用时程序奔溃且出现下面异常时
Caused by: java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity.
SplashScreen.installSplashScreen(this)
未执行或未在super.onCreate()
前执行。 - 在自定义SplashScreen画面后,启动应用,启动画面显示后出现Activity界面的ActionBar挡住UI内容界面的控件,ActionBar操作栏异常情况如下图示:
出现上面界面异常情况说明未使用父级为Theme.SplashScreen
的主题。
自定义启动画面
如果想保留原启动画面Activity
(SplashActivity
),原逻辑保持SplashActivity
为主入口,在启动画面结束后显示SplashActivity
的内容。Google建议完全移除自定义启动画面 Activity
。
不显示原启动界面(SplashActivity)
若旧版本中定义了SplashActivity
类似的过渡Activity
,可调用SplashScreen.setKeepOnScreenCondition
来阻塞SplashScreen的执行达到持续显示的效果,再通过startActivity
过渡到主显示Activity
界面。维持SplashScreen启动界面再finish
是为了避免出现不好的跳转体验。
public class SplashActivity extends Activity
@Override
protected void onCreate(Bundle savedInstanceState)
SplashScreen splashScreen = SplashScreen.installSplashScreen(this);
super.onCreate(savedInstanceState);
// //一直停留在SplashScreen启动界面
splashScreen.setKeepOnScreenCondition(() -> true );
startActivity(new Intent(this, MainActivity.class));
finish();
...
将原启动界面显示在SplashScreenView上
SplashScreenView
就是DecorView
的子View,用下面方式,可以将原SplashScreenView
上移除,并添加自定义的启动布局。此方式依然会显示启动图标的启动画面,在画面结束后显示自定义布局,可以设置点击按钮移除 SplashScreenView.remove()
移除启动画面,显示 Activity
的内容,
getSplashScreen().setOnExitAnimationListener(splashScreenView ->
splashScreenView.removeAllViews();
View view = LayoutInflater.from(MainActivity.this).inflate(R.layout.layout_splash, null, false);
splashScreenView.addView(view);
view.setOnClickListener(v -> splashScreenView.remove());
);
结束
更多内容请参考谷歌文档:启动画面Splash screens。
Splash Screen的framework原理参考下篇文章:Android 12之启动画面Splash Screens(二) – framework原理。
Spring Boot 访问静态资源缺少 scr/main/resources
【中文标题】Spring Boot 访问静态资源缺少 scr/main/resources【英文标题】:Spring Boot access static resources missing scr/main/resources 【发布时间】:2016-07-22 04:05:23 【问题描述】:我正在开发一个 Spring Boot 应用程序。我需要在开始时解析一个 XML 文件 (countries.xml)。问题是我不知道把它放在哪里以便我可以访问它。 我的文件夹结构是
ProjectDirectory/src/main/java
ProjectDirectory/src/main/resources/countries.xml
我的第一个想法是将它放在 src/main/resources 中,但是当我尝试创建文件 (countries.xml) 时,我得到一个 NPE,并且堆栈跟踪显示我的文件在 ProjectDirectory 中查找(所以 src/main /resources/ 未添加)。我尝试创建文件(resources/countries.xml),路径看起来像 ProjectDirectory/resources/countries.xml(所以再次没有添加 src/main)。
我尝试添加这个没有结果
@Override
public void addResourceHandlers(final ResourceHandlerRegistry registry)
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
super.addResourceHandlers(registry);
我知道我可以手动添加 src/main/,但我想了解它为什么不能正常工作。我还尝试了 ResourceLoader 的示例 - 同样没有结果。
谁能指出问题出在哪里?
更新: 仅供参考——在构建项目后,我遇到了访问文件的问题,所以我将 File 更改为 InputStream
InputStream is = new ClassPathResource("countries.xml").getInputStream();
【问题讨论】:
你是在 web.xml 或任何配置文件中添加这个文件来告诉应用它存在 仅将文件添加到文件夹不会帮助应用扫描文件 我没有 web.xml,我有一个基于 Java 的配置。你能告诉我我应该考虑什么吗?也许你有任何样品?非常感谢!!! luboskrnac 的好推荐 对于基于注释的解决方案:***.com/a/39472514/159837 【参考方案1】:只需使用 Spring 类型ClassPathResource。
File file = new ClassPathResource("countries.xml").getFile();
只要这个文件在类路径中的某个地方,Spring 就会找到它。在开发和测试期间可以是src/main/resources
。在生产中,它可以是当前运行目录。
编辑: 如果文件在胖 JAR 中,则此方法不起作用。在这种情况下,您需要使用:
InputStream is = new ClassPathResource("countries.xml").getInputStream();
【讨论】:
非常感谢!!这真的救了我!它现在确实按预期工作 如何将此文件转换为 JSONObejct? (起初数据是 JSONobject) 只是添加到@luboskrnac 的答案,也尝试使用File file = new ClassPathResource(".\countries.xml").getFile();
Per this answer resource.getFile()
期望文件位于实际文件系统上,并且此解决方案在 JAR 中无法用于访问存储在 src/main/resources
下的资源。我已经用一个简单的 Spring Boot 应用程序确认了。
@smeeb 谢谢。使用 InputStream inputStream = new ClassPathResource("countries.xml").getInputStream();
对我有用【参考方案2】:
获取类路径中的文件:
Resource resource = new ClassPathResource("countries.xml");
File file = resource.getFile();
要读取文件 onStartup 使用@PostConstruct
:
@Configuration
public class ReadFileOnStartUp
@PostConstruct
public void afterPropertiesSet() throws Exception
//Gets the XML file under src/main/resources folder
Resource resource = new ClassPathResource("countries.xml");
File file = resource.getFile();
//Logic to read File.
这是一个Small example,用于在 Spring Boot App 启动时读取 XML 文件。
【讨论】:
感谢您的回答!第一部分,按照你和 luboskrnac 的建议救了我! @ElenaChubukina 看看示例。你说你需要在启动时解析 xml.... 谢谢!解析文件的部分没有问题(只有在类路径上查找文件的部分) - 我使用 CommandLineRunner,它对我来说很好【参考方案3】:在使用 Spring Boot 应用程序时,当它部署为 JAR 时,很难使用 resource.getFile()
获取类路径资源,因为我遇到了同样的问题。
此扫描使用 Stream 解决,它将找出放置在类路径中任何位置的所有资源。
下面是相同的代码sn-p -
ClassPathResource classPathResource = new ClassPathResource("fileName");
InputStream inputStream = classPathResource.getInputStream();
content = IOUtils.toString(inputStream);
【讨论】:
它有效。还有一件事,请在你的springboot应用程序中使用依赖:你需要使用以下构造
InputStream in = getClass().getResourceAsStream("/yourFile");
请注意,您必须在文件名前添加此斜杠。
【讨论】:
【参考方案5】:您可以使用以下代码从资源文件夹中读取字符串中的文件。
final Resource resource = new ClassPathResource("public.key");
String publicKey = null;
try
publicKey = new String(Files.readAllBytes(resource.getFile().toPath()), StandardCharsets.UTF_8);
catch (IOException e)
e.printStackTrace();
【讨论】:
【参考方案6】:我用的是spring boot,所以我可以简单使用:
File file = ResourceUtils.getFile("classpath:myfile.xml");
【讨论】:
【参考方案7】:我用的是Spring Boot,我的解决方法是
"src/main/resources/myfile.extension"
希望对某人有所帮助。
【讨论】:
【参考方案8】:由于java.net.URL不足以处理各种底层资源,Spring引入了org.springframework.core.io.Resource。要访问资源,我们可以使用@Value 注解或 ResourceLoader 类。 @自动连线 私有资源加载器资源加载器;
@覆盖 public void run(String... args) 抛出异常
Resource res = resourceLoader.getResource("classpath:thermopylae.txt");
Map<String, Integer> words = countWords.getWordsCount(res);
for (String key : words.keySet())
System.out.println(key + ": " + words.get(key));
【讨论】:
以上是关于Android 12之启动画面Splash Screens -- 适配的主要内容,如果未能解决你的问题,请参考以下文章