Android-起動時に白い画面を表示しない


110

誰もが知っているように、多くのAndroidアプリは、最初Activityにフォーカスが当たる前に、ごく短時間、白い画面を表示します。この問題は、次の場合に発生します。

  • グローバルApplicationクラスを拡張し、そこで主要な初期化を実行するAndroidアプリ。Application オブジェクトは常に最初のオブジェクトActivity(デバッガーで確認できる事実)の前に作成されるため、これは理にかなっています。これが私の場合の遅延の原因です。

  • スプラッシュスクリーンの前にデフォルトのプレビューウィンドウを表示するAndroidアプリ。

android:windowDisablePreview = "true"ここでは明らかに設定は機能しません。また、[残念ながら]スプラッシュスクリーンはを使用しているため、スプラッシュスクリーンの親テーマをここTheme.Holo.NoActionBar説明するように設定することもできません。ActionBar

一方、Applicationクラスを拡張しないアプリは、起動時に白い画面を表示しません

問題は、理想的には、Applicationオブジェクトで実行される初期化は、最初のものが表示されるに行われる必要Activityがあることです。だから私の質問は、オブジェクト使用せずにアプリの起動時にこれらの初期化を実行するにはどうすればよいApplicationですか?おそらくThreadまたはを使用しているServiceと思いますか?

これは考えるべき興味深い問題です。NoActionBar私のスプラッシュ画面には実際にはActionBarいくつかの無関係な理由のために悲劇的にあるので、私は(テーマを設定することによって)通常の方法でそれをバイパスすることはできません。

注意:

私はすでに次の質問に言及しました:

参照:


1
あなたは自分で問題を見つけました、あなたはアプリケーションコンテキストで多くの初期化を行って、アクティビティのロードをブロックし、これを非同期にしようとし、いくつかのスレッドが終了するまでロードアクティビティを表示させます。
AxelH 2016年

これは役立つかもしれません
Max

1
理想的には、アプリケーションは処理をオフロードし、長い操作にメインスレッドを使用しません。これは広く受け入れられている方法です。アプリが読み込まれる前に操作を実行する必要がある場合は、UIとスレッドを共有しないでください。
Beshoy Hanna 2016

1
Applicationクラスからすべての初期化コードを移動した後でも、これがまだ問題であることに気付くかもしれません。これは、Androidの新しいバージョンのアプリを「コールドスタート」する方法が原因です。Googleは実際に今年Google I / Oでの起動時間に対処しましたが、私が覚えていることからNで修正されます。それまでの間、Googleが「ブランド化された起動画面」と呼ぶものを確認する必要があります。これを作成する方法の例を次に示します:antonioleiva.com/branded-launch-screen-最初に白い画面はもうありません;-)そして、スプラッシュスクリーンを使用しないでください-これはユーザーに迷惑です。
ダーウィンド2016年

1
Wrtテーマ、トリックはNoActionBarテーマを設定することではなく、初期のアクティビティのテーマを調整して、空のテーマ画面が完全に初期化された画面のように見えるようにすることです。
zapl

回答:


86

アプリがメモリに読み込まれている間の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 face

<?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>

このテーマをマニフェストのスプラッシュスクリーンに追加します

<?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>

これはこのような効果を生み出します

忙しい猫

詳細とソリューションについては、このBlogPostを確認して ください


3
最後にまだ白い画面とアニメーションが
役に立たなかった

これは簡単な実装です。問題の原因となっているコードの他の部分がある可能性があります。別の質問を開いて、お手伝いします:)
Ivan Milisavljevic

1
テーマ間でアニメーション化し、ドローアブルなしでバックカラーのみを変更してテーマを変更し、onWindowFocusChanged()でコンテンツを表示してアニメーション化し、遷移間で白く塗りつぶして、この問題を解決しました。テーマのアニメーションが多くを助けました
Mehvish Ali

92

この行をアプリのテーマに追加してください

<item name="android:windowDisablePreview">true</item>

詳細:https : //developer.android.com/topic/performance/vitals/launch-time#themed


25
アプリケーションを2秒間ハングしてからアプリケーションを起動しますが、私には役に立ちません!
Faakhir 2018年

4
格子は#ffffff色を表示していませんが、#000000を表示しています
Midhilaj 2018

@Faakhirそれであなたは何か解決策を見つけましたか?私はまだこの白い画面を削除し、起動時に遅延がない解決策を探しています。
Rupam Das

33

これらの2行をコピーして、マニフェストアプリのテーマ(res / styles / AppTheme)に貼り付けてください。その後、それは魅力のように動作します。

<item name="android:windowDisablePreview">true</item>
<item name="android:windowIsTranslucent">true</item>


20

この問題を解決するための推奨方法が回答にありません。ここに私の答えを追加します。起動時の白い画面の問題は、アプリを起動したときにシステムプロセスが描画する最初の空白の画面が原因で発生します。これを解決する一般的な方法は、これをstyles.xmlファイルに追加して、この初期画面をオフにすることです。

<item name="android:windowDisablePreview">true</item>

しかし、Androidのドキュメントによると、これにより起動時間が長くなる可能性があります。Googleによるこの初期の白い画面を回避する推奨される方法は、アクティビティのwindowBackgroundテーマ属性を使用して、開始アクティビティにシンプルなカスタムドローアブルを提供することです。

このような:

Drawable Layoutファイル、 my_drawable.xml

<layer-list xmlns:android="http://schemas.android.com/apk/res/android" android:opacity="opaque">
  <!-- The background color, preferably the same as your normal theme -->
  <item android:drawable="@android:color/white"/>
  <!-- Your product logo - 144dp color version of your app icon -->
  <item>
    <bitmap
      android:src="@drawable/product_logo_144dp"
      android:gravity="center"/>
  </item>
</layer-list>

で新しいスタイルを作成します styles.xml

<!-- Base application theme. -->
<style name="AppTheme">
    <!-- Customize your theme here. -->               
</style>

<!-- Starting activity theme -->
<style name="AppTheme.Launcher">
    <item name="android:windowBackground">@drawable/my_drawable</item>
</style>

このテーマをマニフェストファイルの開始アクティビティに追加します

<activity ...
android:theme="@style/AppTheme.Launcher" />

そして、あなたはあなたの通常のテーマコールに戻って移行したいときにsetTheme(R.style.Apptheme)呼び出す前に、super.onCreate()setContentView()

public class MainActivity extends AppCompatActivity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    // Make sure this is before calling super.onCreate
    setTheme(R.style.Theme_MyApp);
    super.onCreate(savedInstanceState);
    // ...
  }
}

これは問題を解決するための推奨される方法であり、これはGoogle マテリアルデザインパターンからのものです。


14

あなたは、設定しようとしているandroid:windowBackground色や描画可能のいずれかに、あなたのランチャーの活動のテーマに属性を?

例えばこれは:

<item name="android:windowBackground">@android:color/black</item>

ランチャーアクティビティテーマに追加すると、起動時に(白色ではなく)黒色が表示されます。これは、ユーザーに何かを見せながら、長い初期化を隠す簡単なトリックであり、Applicationオブジェクトをサブクラス化しても問題なく機能します。

長い初期化タスクを実行するために他の構造体(スレッドも含む)を使用しないでください。そのような構造体のライフサイクルを制御できなくなる可能性があるためです。Applicationオブジェクトは、まさにこのタイプのアクションを実行するための正しい場所です。


14

styles.xmlの下のテーマに次の2行を追加しました

    <item name="android:windowDisablePreview">true</item>
    <item name="android:windowBackground">@null</item>

魅力のように働いた


10

同じ問題がありました。スタイルを更新する必要があります。

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>

アウトアウト:

ここに画像の説明を入力してください

これがお役に立てば幸いです。


2
これは、NativeActivity OpenGLアプリケーションでうまく機能します。これが最も完全で適切な回答であるため、これが回答の上位にない理由はわかりません。Javaでは、XMLファイルの変更が2、3しか行われていません。
Slion

7

ライフサイクルコールバックメソッド内で、ユーザーがアクティビティを離れて再入したときのアクティビティの動作を宣言できます。Androidの設計方法には、すべてのアプリにライフサイクルがあることに注意してください。メソッドにあまりにも負荷をかけるとonCreate()(レイアウトファイルを読み込んで、その中にあるコントロールを初期化するために使用されるメソッドです)、レイアウトファイルの読み込みに時間がかかるため、白い画面がより見えやすくなります。

アクティビティを開始するときは、いくつかの異なる方法を使用することをお勧めします。これはonStart()(アプリが読み込まれると最初に呼び出される)、onActivityCreated()(レイアウトが表示された後に呼び出され、アクティビティの開始時にデータ処理を行う場合に便利です)です。

簡単にするために、以下は公式のアクティビティライフサイクル図です。

ここに画像の説明を入力してください


回答ありがとうございます、とても面白かったです。しかし、あなたは私の質問を誤解していると思います。問題の原因は最初のの初期化ではなくActivity、グローバルApplicationオブジェクトの初期化です。そして私はとは違っているので、私は、そこに懸念のような分離を適用することができると信じていないActivity、それが唯一持っているonCreate()方法を。
YS

なぜアクティビティクラスではなくアプリケーションクラスを拡張するのですか?
Michele La Ferla

あなたが意味するので、さて、私は放棄しなければならないApplication完全にオブジェクトを最初にすべての初期化コードを移動Activity...
YS

これが私が常にアプリを開発してきた方法ですが、これらの変更をすべて行いたくない場合は、他の回答がアプリケーションクラスを使用して問題を回避するのに役立つ場合があります。将来の参考のために、1つのアクティビティクラスをすぐに使用し、次に多くのフラグメントを使用することをお勧めします。これがお役に立てば
幸いです

2

初期化を試みました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) {

            }
        });

2

バックグラウンドプロセス、アプリケーションの初期化、または大きなファイルなどが原因で、この白い画面が表示される理由をすでにご存じのとおり、これを克服するために以下のアイデアを確認してください。

アプリの起動時にこの白い画面を防ぐには、スプラッシュスクリーンが1つの方法です。これは最終的な方法ではなく、使用する必要があります。

あなたがsplash.xmlファイルからスプラッシュ画面を表示する場合、この問題も同じままです、

したがって、スプラッシュ画面のstyle.xmlファイルでontスタイルを作成する必要があり、そこでウィンドウの背景をスプラッシュ画像として設定し、そのテーマをマニフェストファイルからスプラッシュアクティビティに適用する必要があります。したがって、アプリを実行すると、最初にテーマが設定され、これによりユーザーは白い画面ではなく直接スプラッシュ画像を見ることができます。


2

両方のプロパティが機能します

    <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>

2

一度お試しください。

1)ドローアブルファイルsplash_background.xmlを作成する

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:drawable="@color/{your color}" />

    <item>
        <bitmap
            android:layout_width="@dimen/size_250"
            android:layout_height="@dimen/size_100"
            android:gravity="center"
            android:scaleType="fitXY"
            android:src="{your image}"
            android:tint="@color/colorPrimary" />
    </item>

</layer-list>

2)これをstyles.xmlに入れます

     <style name="SplashTheme" parent="Theme.AppCompat.NoActionBar">
         <item name="android:windowBackground">@drawable/background_splash</item>
     </style>

3)AndroidMainfest.xmlで、上記のテーマをLaunch activityに設定します。

       <activity
            android:name=".SplashScreenActivity"
            android:screenOrientation="portrait"
            android:theme="@style/SplashTheme"
            android:windowSoftInputMode="stateVisible|adjustResize">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

0

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>

0
Style :- 
<style name="SplashViewTheme" parent="Theme.AppCompat.NoActionBar">
    <item name="android:windowBackground">@drawable/splash</item>
    <item name="windowActionBar">false</item>
    <item name="windowNoTitle">true</item>
</style>

In Manifest :- 
<activity android:name=".SplashActivity"
        android:theme="@style/SplashViewTheme">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

0

デバッグ中にその白い画面を持っている人は、デバッグしているとロードに時間がかかることに注意してください。リリースAPKをビルドして携帯電話にインストールすると、ロードにかかる時間が大幅に短縮されます。

したがって、debbugバージョンの起動時間は、リリースバージョンの起動時間とは異なります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.