【问题标题】:Android display Splash-Screen while loadingAndroid在加载时显示启动画面
【发布时间】:2015-10-07 00:59:09
【问题描述】:

我有一个 Android 应用程序,它会显示 3 秒钟的“启动画面”。之后,MainActivity 被加载。

不幸的是,MainActivity 需要额外的约 4 秒才能加载。在第一次启动时甚至更长。但是,当应用程序加载完毕后,一切运行顺利。

现在我该如何实现它,即 MainActivity 在启动画面显示期间被加载?它应该只显示一个图像,直到整个东西完全加载。 我已经阅读了有关 Async-Task 的信息,但我不确定将它放在哪里以及如何正确使用它。有人可以帮帮我吗?

SplashScreen.java

public class SplashScreen extends Activity {
    private static int SPLASH_TIME_OUT = 3000;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_startup);

        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                Intent i = new Intent(SplashScreen.this, MainActivity.class);
                startActivity(i);
                finish();
            }
        }, SPLASH_TIME_OUT);
    }
}

MainActivity.java

public class MainActivity extends Activity implements OnClickListener, MediaController.MediaPlayerControl {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //Some heavy processing
        //starting services
        //starting Google Text to Speech
        //and so on...

    }

}

【问题讨论】:

  • 一种解决方法可能是仅使用MainActivity,最初显示初始屏幕布局,然后隐藏/删除它(例如通过Handler.postDelayed())以显示实际的活动布局。
  • 这个来自 Android 开发者的新提示可能会有所帮助:plus.google.com/+AndroidDevelopers/posts/Z1Wwainpjhd
  • 你用谷歌搜索了吗?有很多例子供你参考。检查这个androidhive.info/2013/07/…
  • 感谢 cmets! @Soham:我的示例代码来自与您的链接完全相同的来源......所以是的,我已经用谷歌搜索了它。然而,我的问题由 TmKVU here 解决了

标签: java android splash-screen


【解决方案1】:

您不应该在启动时创建新线程,而是应该创建一个不必等待资源加载的视图,如本文所述:Splash Screens the Right Way

如文章所述,您应该创建一个 layer-list 可绘制而不是 layout XML 文件:

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

    <!-- Fill the background with a solid color -->
    <item android:drawable="@color/gray"/>

    <!-- Place your bitmap in the center -->
    <item>
        <bitmap
            android:gravity="center"
            android:src="@mipmap/ic_launcher"/>
    </item>

</layer-list>

然后使用可绘制文件作为背景创建一个主题。我使用background 属性而不是文章中建议的windowBackground 属性,因为background 将状态和导航栏考虑在内,从而更好地居中drawable。我还将windowAnimationStyle 设置为null,这样启动画面就不会为MainActivity 的过渡设置动画:

<resources>

    <!-- Base application theme -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
    </style>

    <!-- Splash Screen theme -->
    <style name="SplashTheme" parent="Theme.AppCompat.NoActionBar">
        <item name="android:background">@drawable/background_splash</item>
        <item name="android:windowAnimationStyle">@null</item>
    </style>

</resources>

然后在 SplashActivity 的清单中声明您的主题:

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

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

最后,您在SplashActivity 中要做的就是启动您的MainActivity,启动画面只会在您的应用配置所需的时间内显示:

public class SplashActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Intent intent = new Intent(this, MainActivity.class);
        startActivity(intent);
        finish();
    }
}

【讨论】:

  • 这应该是公认的答案。它实际上回答了 OP 的问题。
  • 不错的方法,但是我们可以在以这种方式创建的初始屏幕中显示进度条吗?
  • @Journey 不,关键是在加载资源之前显示此屏幕。为了显示进度条,必须加载资源。无论如何,应用程序不应该花费那么长时间来加载其资源,只需几秒钟。如果您的应用程序在启动时处理其他一些进程,则处理此问题的一个好方法是拥有一个SplashActivity,它启动一个LoadingActivity,它将处理这些进程。如果你使用相同的windowBackground,两者在视觉上不会有区别,只是现在可以显示一个进度条。
  • 非常感谢,但不要忘记在 SplashTheme 样式中添加 parent="Theme.AppCompat.NoActionBar",没有它将无法工作
  • 如果你得到“Resources $ NotFoundException”错误,试试这个层列表中的第二项:(没有位图标签)&lt;item android:gravity="center" android:drawable="@mipmap/ic_launcher"/&gt;
【解决方案2】:

如果对启动画面的显示时间没有特定限制,您可以通过以下方式使用AsyncTask

public class SplashScreen extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_startup);
        startHeavyProcessing();

    }

    private void startHeavyProcessing(){
       new LongOperation().execute("");
    }

    private class LongOperation extends AsyncTask<String, Void, String> {

        @Override
        protected String doInBackground(String... params) {
            //some heavy processing resulting in a Data String
            for (int i = 0; i < 5; i++) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    Thread.interrupted();
                }
            }
            return "whatever result you have";
        }

        @Override
        protected void onPostExecute(String result) {
            Intent i = new Intent(SplashScreen.this, MainActivity.class);
            i.putExtra("data", result);
            startActivity(i);
            finish();
        }

        @Override
        protected void onPreExecute() {}

        @Override
        protected void onProgressUpdate(Void... values) {}
    }
}

如果结果数据的性质不是字符串,您可以将Parcelable 对象作为额外的活动添加到您的活动中。在onCreate 中,您可以通过以下方式检索数据:

getIntent().getExtras.getString('data');

【讨论】:

    【解决方案3】:

    为了简单起见,您如何将启动活动与主要活动结合起来?这样一来,您就可以两全其美,即第一次准备数据时出现启动画面,以及在之前准备好数据时快速启动。让用户什么都不等不是很好的形式......

    类似:

    public class MainActivity extends Activity implements OnClickListener, MediaController.MediaPlayerControl {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            // Initially shows splash screen, the main UI is not visible
            setContentView(R.layout.activity_main);  
    
            // Start an async task to prepare the data. When it finishes, in
            // onPostExecute() get it to call back dataReady()
            new PrepareDataAsyncTask(this).execute();
    
        }
    
        public void dataReady() {
            // Hide splash screen
            // Show real UI
        }
    
    }
    

    【讨论】:

      【解决方案4】:

      您的初始屏幕代码工作正常,但是当您调用下一个活动时,然后在 onCreate() 中使用 Asynctask 来完成繁重的任务......

      【讨论】:

        【解决方案5】:

        我也遇到过类似的问题。有一个空白的加载屏幕(甚至没有工具栏)。 Mu 罪魁祸首在 MainActivity 的清单中:

         android:launchMode="singleInstance"
        

        【讨论】:

        • 那么launchMode="singleInstance" 是好事还是坏事?
        【解决方案6】:

        就像this article

        1 - 为启动画面创建一个像这样的 XML 布局。我称之为“background_splash.xml”

        <?xml version="1.0" encoding="utf-8"?>
        <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
        
            <item
                android:drawable="@color/cardview_light_background"/>
        
            <item>
                <bitmap
                    android:gravity="center"
                    android:src="@drawable/kiss_com_sub_logo"/>
            </item>
        
        </layer-list>
        

        2 - 然后,转到 styles.xml 并编写如下样式:

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

        3 - 为你的启动写一个活动。我称它为 SplashActivity.kt

        class SplashActivity : AppCompatActivity() {
            override fun onCreate(savedInstanceState: Bundle?) {
                super.onCreate(savedInstanceState)
                val intent = Intent(this, MainActivity::class.java)
                startActivity(intent)
                finish()
            }
        }
        

        4 - 最后,转到您的 AndroidManifest.xml 并添加您的活动启动画面:(注意:不要删除 AndroidManifest 中的任何内容,只需将其添加到 Main 活动之前)。

        <activity
               android:name=".SplashActivity"
               android:label="Kiss"
               android:theme="@style/SplashTheme">
               <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
                    <category android:name="android.intent.category.LAUNCHER"/>
               </intent-filter>
        </activity>
        

        这就完成了。您无需担心应用程序需要启动的时间,启动画面会持续足够的时间。当您的 MainActivity 准备就绪时,它就会显示出来。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-09-29
          • 2018-07-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多