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
문제를 직접 발견하고 애플리케이션 컨텍스트에서 많은 init을 수행하고 활동로드를 차단하고이를 비 동기화하여 일부 스레드가 끝날 때까지로드 활동이 표시되도록합니다.
AxelH

이것이 도움 될 수 있습니다
Max

1
이상적으로는 애플리케이션이 처리를 오프로드하고 긴 작업에 기본 스레드를 사용하지 않습니다. 이것은 잘 받아 들여지는 관행입니다. 앱이로드되기 전에 작업을 수행해야하는 경우 최소한 UI와 스레드를 공유하지 않아야합니다.
Beshoy Hanna 2016

1
모든 초기화 코드를 Application클래스에서 옮긴 후에도 여전히 문제가 될 수 있습니다 . 이는 Android가 앱을 "콜드 스타트"하는 방식의 최신 버전 때문입니다. Google은 실제로 올해 Google I / O에서 출시 시간을 해결했으며 내가 기억하는대로 N으로 수정 될 것입니다. 그동안 Google이 '브랜드 출시 화면'이라고 부르는 것을 살펴 봐야합니다. 생성 방법에 대한 예는 다음과 같습니다. antonioleiva.com/branded-launch-screen- 처음에는 더 이상 흰색 화면이 없습니다 ;-) 그리고 스플래시 화면을 사용하지 마십시오. 사용자에게 짜증이납니다.
Darwind

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

<?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
그것은 여전히 didnt한다 도움 말에 흰색 화면과 애니메이션
Mehvish 알리

이것은 간단한 구현입니다. 문제를 일으키는 코드의 다른 부분이있을 수 있습니다. 또 다른 질문을여십시오 그리고 위원장 : 당신을 도울가
이반 Milisavljevic

1
나는 테마 사이에 애니메이션을 적용하고 드로어 블은 없지만 배경색 만 동일하게 테마를 변경 한 다음 onWindowFocusChanged ()에서 콘텐츠를 표시하고 애니메이션을 적용하여 전환 사이에 흰색으로 표시하여이 문제를 해결했습니다. 테마의 애니메이션은 많이 도움이
Mehvish 알리에게

93

이 줄을 앱 테마에 추가하세요

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

자세한 정보 : https://developer.android.com/topic/performance/vitals/launch-time#themed


25
2 초 동안 응용 프로그램을 중단 한 다음 응용 프로그램을 시작합니다. 나에게는 유용하지 않습니다!
Faakhir

4
지금 창살은 #FFFFFF 색상을 보여주는 것이 아니라, 지금 # 000000 보여주는
Midhilaj

@ Faakhir 그래서 어떤 해결책을 찾았습니까? 이 흰색 화면을 제거하고 시작 시간에 지연이없는 솔루션을 찾고 있습니다.
Rupam Das

33

이 두 줄을 매니페스트 앱 테마 (예 : res / styles / AppTheme)에 복사하여 붙여 넣으십시오. 그러면 매력처럼 작동합니다 ..

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


20

이 문제를 해결하는 권장 방법이 답변에 없습니다. 그래서 여기에 내 대답을 추가하고 있습니다. 시작시 흰색 화면 문제는 앱을 시작할 때 시스템 프로세스가 그리는 초기 빈 화면 때문에 발생합니다. 이 문제를 해결하는 일반적인 방법은 styles.xml파일 에 추가하여이 초기 화면을 끄는 것 입니다.

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

그러나 안드로이드 문서에 따르면 이것은 더 긴 시작 시간을 초래할 수 있습니다. Google에 따라이 초기 흰색 화면을 피하는 권장 방법은 활동의 windowBackground테마 속성 을 사용 하고 시작 활동에 대한 간단한 사용자 정의 드로어 블을 제공하는 것입니다.

이렇게 :

드로어 블 레이아웃 파일, 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>

이 테마를 Manifest 파일의 시작 활동에 추가하십시오.

<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 Material Design 패턴 에서 가져온 것 입니다.


14

android:windowBackground런처 활동 테마의 속성을 색상 또는 드로어 블로 설정해 보셨습니까 ?

예를 들면 다음과 같습니다.

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

런처 활동 테마에 추가하면 시작시 흰색이 아닌 검은 색으로 표시됩니다. 이것은 긴 초기화를 숨기고 사용자에게 무언가를 보여주는 쉬운 트릭 이며 Application 개체를 하위 클래스로 분류하더라도 제대로 작동 합니다.

긴 초기화 작업을 수행하는 데 다른 구성 (스레드 포함)을 사용하지 마십시오. 이러한 구성의 수명주기를 제어 할 수 없게 될 수 있습니다. Application 개체는 이러한 유형의 작업을 정확하게 수행하기위한 올바른 위치입니다.


14

styles.xml 아래의 테마에 다음 두 줄을 추가했습니다.

    <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 파일 변경 만 포함하지 않았습니다.
Slion

7

수명주기 콜백 메서드 내에서 사용자가 활동을 떠났다가 다시 들어갈 때 활동이 어떻게 작동하는지 선언 할 수 있습니다. Android가 설계된 방식에는 각 앱마다 수명주기가 있습니다. onCreate()메서드 에 너무 많은로드를 가하면 (레이아웃 파일을로드하고 그 안에있는 컨트롤을 초기화하는 데 사용되는 방법) 레이아웃 파일을로드하는 데 시간이 더 오래 걸리므로 흰색 화면이 더 잘 보입니다.

활동을 시작할 때 여러 가지 방법을 사용하는 것이 좋습니다. 하는 이러한 onStart()(응용 프로그램이로드되면 제일 먼저로 호출되는)onActivityCreated() (당신이 활동을 시작하기에 모든 데이터 처리를 만드는 경우 레이아웃을 표시 한 후 호출하고 유용한되는).

더 쉽게하기 위해 다음은 공식 활동 라이프 사이클 다이어그램입니다.

여기에 이미지 설명 입력


답변 감사합니다. 매우 흥미로 웠습니다. 그러나 나는 당신이 내 질문을 오해했다고 믿습니다. 문제는 첫 번째의 초기화가 Activity아니라 전역 Application개체 의 초기화로 인해 발생 합니다. 그리고 나는 거기에 그러한 우려의 분리를 적용 할 수 있다고 믿지 않습니다. 왜냐하면 Activity그것은 단지 onCreate()방법 이 있기 때문 입니다.
YS

활동 클래스가 아닌 애플리케이션 클래스를 확장하는 이유는 무엇입니까?
Michele La Ferla

좋아, 그래서 내가 Application객체를 모두 버리고 모든 초기화 코드를 첫 번째 코드로 옮겨야 한다는 뜻입니다 Activity...
YS

이것이 내가 항상 내 앱을 개발 한 방법이지만 모든 변경을 원하지 않는 경우 다른 답변이 응용 프로그램 클래스를 사용하여 문제를 해결하는 데 도움이 될 수 있습니다. 나중에 참조 할 수 있도록 즉시 하나의 활동 클래스를 사용한 다음 여러 조각을 사용하는 것이 좋습니다. 희망이 :) 도움이
미셸 라 Ferla

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

백그라운드 프로세스 또는 응용 프로그램 초기화 또는 대용량 파일로 인해이 흰색 화면이있는 이유를 이미 알고 있으므로 아래 아이디어를 확인하여 극복하십시오.

앱 시작시이 흰색 화면을 방지하려면 한 가지 방법은 스플래시 화면입니다. 이것은 최종 방법이 아니므로 사용해야합니다.

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