Android – 防止启动时出现白屏
众所周知,许多Android应用程序在第一个Activity
聚焦之前,会非常简短地显示白色屏幕。 在以下情况下会出现此问题:
-
扩展全局
Application
类并在其中执行重要的初始化的Android应用程序。Application
对象总是在第一个Activity
(在debugging器中可以观察的事实)之前创build的,所以这是有道理的。 这是我的情况延误的原因。 -
在启animation面之前显示默认预览窗口的Android应用程序。
设置android:windowDisablePreview = "true"
显然不起作用。 我也不能将闪屏的父主题设置为Theme.Holo.NoActionBar
,因为[不幸]我的闪屏使用了一个ActionBar
。
同时,不扩展Application
类的Application
不会在启动时显示白屏。
事情是,理想情况下, 在显示第一个Activity
之前 ,需要在Application
对象中执行初始化。 所以我的问题是,如何在不使用Application
对象的情况下对应用程序启动执行这些初始化? 可能使用Thread
或Service
,我想?
这是一个值得思考的有趣的问题。 我不能绕过它通常的方式(通过设置NoActionBar
主题),不幸的是我的飞溅屏幕实际上有一个ActionBar
由于一些不相关的原因。
注意:
我已经提到以下问题:
-
如何修复应用程序的白屏启动?
-
Android的初始屏幕是白色的?
-
在splashscreen之前的白色屏幕
-
Android应用程序启动时的白色背景
-
为什么开始在Android中运行应用程序时出现白屏1秒?
参考文献:
-
模式 – 启动屏幕 。
-
品牌启动屏幕:Android的新飞溅 。
-
飞溅屏幕正确的方式 。
与白色背景的问题是由于android的冷启动,而应用程序加载到内存造成的,可以避免这个问题:
public class OnboardingWithCenterAnimationActivity extends AppCompatActivity { public static final int STARTUP_DELAY = 300; public static final int ANIM_ITEM_DURATION = 1000; public static final int ITEM_DELAY = 300; private boolean animationStarted = false; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { setTheme(R.style.AppTheme); getWindow().getDecorView().setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION); super.onCreate(savedInstanceState); setContentView(R.layout.activity_onboarding_center); } @Override public void onWindowFocusChanged(boolean hasFocus) { if (!hasFocus || animationStarted) { return; } animate(); super.onWindowFocusChanged(hasFocus); } private void animate() { ImageView logoImageView = (ImageView) findViewById(R.id.img_logo); ViewGroup container = (ViewGroup) findViewById(R.id.container); ViewCompat.animate(logoImageView) .translationY(-250) .setStartDelay(STARTUP_DELAY) .setDuration(ANIM_ITEM_DURATION).setInterpolator( new DecelerateInterpolator(1.2f)).start(); for (int i = 0; i < container.getChildCount(); i++) { View v = container.getChildAt(i); ViewPropertyAnimatorCompat viewAnimator; if (!(v instanceof Button)) { viewAnimator = ViewCompat.animate(v) .translationY(50).alpha(1) .setStartDelay((ITEM_DELAY * i) + 500) .setDuration(1000); } else { viewAnimator = ViewCompat.animate(v) .scaleY(1).scaleX(1) .setStartDelay((ITEM_DELAY * i) + 500) .setDuration(500); } viewAnimator.setInterpolator(new DecelerateInterpolator()).start(); } } }
布局
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="?colorPrimary" android:orientation="vertical" > <LinearLayout android:id="@+id/container" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center" android:gravity="center" android:orientation="vertical" android:paddingTop="144dp" tools:ignore="HardcodedText" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_marginTop="16dp" android:alpha="0" android:text="Hello world" android:textAppearance="@style/TextAppearance.AppCompat.Widget.ActionBar.Title.Inverse" android:textColor="@android:color/white" android:textSize="22sp" tools:alpha="1" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_marginTop="8dp" android:alpha="0" android:gravity="center" android:text="This a nice text" android:textAppearance="@style/TextAppearance.AppCompat.Widget.ActionBar.Subtitle.Inverse" android:textSize="20sp" tools:alpha="1" /> <Button android:id="@+id/btn_choice1" android:layout_width="200dp" android:layout_height="wrap_content" android:layout_marginTop="48dp" android:scaleX="0" android:scaleY="0" android:text="A nice choice" android:theme="@style/Button" /> <Button android:id="@+id/btn_choice2" android:layout_width="200dp" android:layout_height="wrap_content" android:layout_marginTop="4dp" android:scaleX="0" android:scaleY="0" android:text="Far better!" android:theme="@style/Button" /> </LinearLayout> <ImageView android:id="@+id/img_logo" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:src="@drawable/img_face" tools:visibility="gone" /> </FrameLayout>
img的脸
<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android" android:opacity="opaque"> <item android:drawable="?colorPrimary"/> <item> <bitmap android:gravity="center" android:src="@drawable/img_face"/> </item>
将此主题添加到清单中的splashscreen
<?xml version="1.0" encoding="utf-8"?> <resources> <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"> <!-- Customize your theme here. --> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> <item name="android:windowBackground">@null</item> </style> <style name="AppTheme.CenterAnimation"> <item name="android:windowBackground">@drawable/ll_face_logo</item> </style>
这会产生这样的效果
更多的细节和更多的解决scheme,你可以检查这个BlogPost
请将此行添加到您的应用主题中
<item name="android:windowDisablePreview">true</item>
首先,要删除白屏阅读此 – https://www.bignerdranch.com/blog/splash-screens-the-right-way/
但更重要的是,优化您的初始负载,并在有时间运行时推迟繁重工作。 如果你想让我们看看它,请在这里发布你的应用程序类。
在生命周期callback方法中,您可以声明用户离开并重新进入活动时活动的行为。 请记住,Android的devise方式,每个应用程序都有一个生命周期。 如果你在onCreate()
方法(这是用来加载布局文件的方法,并且使用任何控件onCreate()
加载了太多的负载,那么白色的屏幕将变得更加明显,因为布局文件将花费更长的时间加载。
我build议在开始活动时使用几种不同的方法。 onStart()
(被称为应用程序加载后的第一件事), onActivityCreated()
(在布局显示后调用,如果在开始活动时进行任何数据处理,则调用)。
为了让你更容易,下面是官方的活动生命周期图:
你有没有尝试在你的启动器活动的主题中设置android:windowBackground
属性为颜色还是可绘制?
比如这个:
<item name="android:windowBackground">@android:color/black</item>
当添加到启动器活动主题将启动时显示黑色(而不是白色)。 这是一个简单的技巧来隐藏长初始化,同时显示您的用户的东西,即使你的应用程序对象的子类,它也可以正常工作 。
避免使用其他构造(甚至是线程)来执行长时间的初始化任务,因为最终可能无法控制这种构造的生命周期。 应用程序对象是完成这种types的操作的正确位置。
两个属性都起作用
<style name="AppBaseThemeDark" parent="@style/Theme.AppCompat"> <!--your other properties --> <!--<item name="android:windowDisablePreview">true</item>--> <item name="android:windowBackground">@null</item> <!--your other properties --> </style>
你有没有尝试把onActivityCreated
初始化?
内部Application
类:
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() { @Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) { if(activity.getClass().equals(FirstActivity.class) { // try without runOnUiThread if it will not help activity.runOnUiThread(new Runnable() { @Override public void run() { new InitializatioTask().execute(); } }); } } @Override public void onActivityStarted(Activity activity) { } @Override public void onActivityResumed(Activity activity) { } @Override public void onActivityPaused(Activity activity) { } @Override public void onActivityStopped(Activity activity) { } @Override public void onActivitySaveInstanceState(Activity activity, Bundle outState) { } @Override public void onActivityDestroyed(Activity activity) { } });
正如你已经知道为什么这个白色屏幕在那里,由于后台进程或应用程序初始化或大型文件,所以只需检查下面的想法克服这一点。
为了防止在应用程序的开始这个白色的屏幕,一种方式是闪屏,这只是一种方式不是最终的,你必须使用。
当你从splash.xml文件中显示启animation面时,这个问题也会保持不变,
因此,您必须在style.xml文件中创build启动屏幕的ont样式,并且必须将窗口背景设置为您的启动图像,然后将该主题应用于清单文件中的启动活动。 所以现在当你运行应用程序时,首先它将设置主题,通过这种方式,用户将能够直接看到图像而不是白色屏幕。
我有同样的问题,你必须更新你的风格。
style.xml
<!-- Base application theme. --> <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"> <!-- Customize your theme here. --> <item name="drawerArrowStyle">@style/DrawerArrowStyle</item> <item name="android:windowNoTitle">true</item> <item name="android:windowDisablePreview">true</item> <item name="android:windowBackground">@null</item> <item name="android:windowIsTranslucent">true</item> </style>
你的清单文件应该如下所示。
<application android:name=".MyApplication" android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme"> // Other stuff </application>
Outout:
希望这会帮助你。
只需在values / styles.xml中写入项目即可:
<item name="android:windowBackground">@android:color/black</item>
例如,在AppTheme中:
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <item name="windowNoTitle">true</item> <item name="windowActionBar">false</item> <item name="android:windowFullscreen">true</item> <item name="android:windowContentOverlay">@null</item> <item name="android:windowBackground">@android:color/black</item> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> </style>
我会build议看看在这个页面给出的答案。 使用Style属性解决。 它不会打扰用户。