7

我们都知道有很多关于如何在 Android 上做启动画面的教程。但我们也知道那些是伪闪屏。我搜索了很多,我总是看到Thread.sleep(x)。这不是很好的编码,这只是为了让应用程序美观并看起来像一个专业的应用程序,这不是我想要的!
这些闪屏的另一个问题是它们不能解决我的问题,因为它们只在活动开始显示它并显示内容视图。

我有一个应用程序,它在初始化时会做很多事情,当应用程序启动时,用户会看到几秒钟的黑屏,足够的时间来烦人。所以这就是为什么我想显示一个编码良好的启动屏幕,它可以删除在设置内容视图之前出现的黑屏。

我尝试了一些东西。我将初始屏幕 (a RelativeLayout) 包含在 中设置的布局中MainActivity,但据我所知,Android 仅在加载所有内容后才显示内容,所以如果我试图从内容视图中显示一些视图我有等到一切都完成。不过,我会发送我的代码,它可以以某种方式提供帮助......

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    new SplashTask().execute();
}

private class SplashTask extends AsyncTask<Void, Void, Void> {

    @Override
    protected void onPreExecute() {
        initializeViews();
        mSplashScreen.setVisibility(View.VISIBLE);
    }

    @Override
    protected Void doInBackground(Void... params) {
        return null;
    }

    @Override
    protected void onPostExecute(Void params) {
        Standard.Initiate(MainActivity.this);
        verifyListStats();
        loadListAdapters();
        setOnClickListeners();
        mSplashScreen.setVisibility(View.GONE); 
    }

}

我试图加载一些资源,doInBackground(...)但是因为我做了一些onResume()需要这些资源的操作,所以我做不到(或者至少我认为我做不到)。

任何想法?我听说有一个类似于 iOS 启动图像的内置机制,也许这可以成为一种方式。

4

8 回答 8

5

当一个活动启动时,Android 会启动一个 Zygote,一个什么都不做的空活动,并在上面设置你的活动主题,然后启动它。一旦您的活动准备好显示,它会将显示的活动交换为您的活动。有关 Zygote 的更多信息,您可以阅读Cyril Motier 的这篇文章

所以要回答你的问题,你可以这样做:

  1. 创建一个小主题,其中自定义窗口背景显示您的启动信息(您可以使用 9-patch 来居中未缩放的内容);
  2. 在您的清单中,将此启动主题用于您的活动;
  3. 在您的活动的 onCreate() 方法中,调用 setTheme(R.id.yourActivityTheme) (在 setContentView() 之前调用它);
  4. 请享用...

这样,您的“启动画面”(即:带有启动主题的合子)将一直可见,直到您的活动准备好显示。

于 2013-08-28T10:30:07.550 回答
3

编辑:这是一个很棒的启动屏幕教程,您希望启动屏幕出现一段时间,或者完成一些处理。它还给出了几种方法的优缺点。

http://blogactivity.wordpress.com/2012/02/24/writing-splash-screens-the-right-way/

于 2013-08-22T22:00:18.700 回答
2

创建一个 SplashScreen 活动并将其声明为您的应用程序中的默认值,即将其添加到您的 AndroidManifest.xml

  <activity
        android:name="package.SplashScreen"
        android:icon="@drawable/icon"
        android:label="@string/app_name"
        android:noHistory="true">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

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

在您的 SplashActivity onCreate 中启动一个新的 AsyncTask:

public class SplashScreen extends Activity {

   public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.splash_image);

      new InitAsyncTask().execute();
   }

   private class InitAsyncTask extends AsyncTask<?, ?, ?> {

      protected ? doInBackground(?... params) {
         // PERFORM YOUR INITIALIZATION HERE
      }

      protected void onPostExecute(? result) {
          // Initialization is completed, close SplashScreen 
          // and launch your MainActivity:
          SplashScreen.this.finish();
          startActivity(new Intent(MainActivity.class, SplashScreen.this);

     }
   }
}
于 2013-08-22T22:30:48.843 回答
0

下面是我在所有项目中使用的启动画面活动。请检查它是否对您有帮助。

public class SplashActivity extends Activity {

    private SharedPreferences myPrefs;
    private SharedPreferences.Editor prefsEditor;
    private boolean login;
    private boolean connectivityState;
    private String connectedNetworkType;
    private ConnectivityManager connectivityManager;
    private CheckInternet checkInternet;
    private File file = new File(API.file_dir);
    public static Location loc;
    Configuration newConfig;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.splash_layout);



        //----------------------
        myPrefs = getSharedPreferences("myPrefs", MODE_WORLD_READABLE);
        boolean login = myPrefs.getBoolean("login", false); 

            checkForInternetAndNextFlow();
    }


    // Check for the Internet Connection
    private void checkForInternetAndNextFlow() {

        connectivityManager = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
        checkInternet = new CheckInternet(getApplicationContext());
        connectivityState = checkInternet.isConnected(connectivityManager);

        if (connectivityState) {
            connectedNetworkType = checkInternet.getNetworkType();
            // Toast.makeText(getApplicationContext(), "Connected via : " +
            // connectedNetworkType, Toast.LENGTH_LONG).show();

            // check for the login or not from preference
            myPrefs = this.getSharedPreferences("myPrefs", MODE_WORLD_READABLE);
            login = myPrefs.getBoolean("login", false);

            System.out.println("Loging value is:" + login);
            Thread t = new Thread() {
                public void run() {
                    try {
                        Thread.sleep(1500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } finally {
                        if (login) {
                            Intent i = new Intent(SplashActivity.this,MainTabActivity.class);
                            startActivity(i);
                        } else {
                            Intent i = new Intent(SplashActivity.this,LoginActivity.class);
                            startActivity(i);
                        }
                    }
                }
            };
            t.start();

        } else {
            // Toast.makeText(getApplicationContext(), "NOT connected",
            // Toast.LENGTH_LONG).show();
            final Dialog dialog = new Dialog(SplashActivity.this,R.style.CustomDialogTheme);
            dialog.getWindow();
            dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
            dialog.setContentView(R.layout.internet_dialog);
            dialog.setCancelable(false);

            Button retryBtn = (Button) dialog.findViewById(R.id.retryBtn);
            Button cancel = (Button) dialog.findViewById(R.id.cancelBtn);

            retryBtn.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View arg0) {
                    dialog.dismiss();
                    checkForInternetAndNextFlow();
                }
            });

            cancel.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View arg0) {
                    dialog.dismiss();
                    finish();
                }
            });
            dialog.show();
        }

    }


}

希望它会帮助你。享受编码... :)

于 2013-08-28T08:47:21.660 回答
0

我通过创建一个全屏启动对话框来完成此操作,然后在完成加载时将其关闭

splashDialog = new Dialog(getActivity(), android.R.style.Theme_Black_NoTitleBar_Fullscreen);
        splashDialog.setContentView(R.layout.yourSplashLayout);
于 2013-08-13T21:08:06.637 回答
0

我的一个非授权项目需要一个启动画面,即使它不是必需的。也许它对您的项目有用,因为它基于对话而不是活动。如果启动屏幕被轻按或手势,它将被关闭,以及在动画完成后(定时淡出)。可以对类进行修改,以便在允许点击或手势关闭图像之前检查某种“就绪状态布尔值”。

类文件:AppIntro.java

import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.AnimationUtils;

public class AppIntro extends Dialog {
    protected int mLayoutRes = 0;
    protected int mAnimRes = 0;
    protected Animation mIntroAnim = null;
    protected View mLayout = null;

    public AppIntro(Context aContext, int aLayoutRes, int aAnimRes) {
        super(aContext);
        mLayoutRes = aLayoutRes;
        mAnimRes = aAnimRes;
    }

    @Override
    protected void onCreate(Bundle aSavedState) {
        super.onCreate(aSavedState);
        mLayout = LayoutInflater.from(getContext()).inflate(mLayoutRes,null);
        mLayout.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                AppIntro.this.dismiss();
            }
        });
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(mLayout);
        mIntroAnim = AnimationUtils.loadAnimation(getContext(),mAnimRes);
        mIntroAnim.setAnimationListener(new AnimationListener() {

            @Override
            public void onAnimationStart(Animation animation) {
                //nothing to do
            }

            @Override
            public void onAnimationRepeat(Animation animation) {
                //nothing to do
            }

            @Override
            public void onAnimationEnd(Animation animation) {
                AppIntro.this.dismiss();
            }
        });
    }

    @Override
    public boolean onGenericMotionEvent(MotionEvent event) {
        dismiss();
        return true;
    }

    @Override
    public void show() {
        super.show();
        mLayout.startAnimation(mIntroAnim);
    }

}

接下来,我们在文件“res/anim/intro_anim.xml”中定义动画淡出(将持续时间更改为加载应用程序所需的时间)。4200 = 4.2 秒。

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" 
    >
    <alpha 
        android:fromAlpha="1.0" android:toAlpha="0.0" 
        android:interpolator="@android:anim/accelerate_interpolator" 
        android:duration="4200" 
        android:repeatCount="0" >
    </alpha>
</set>

最后,我们在“layout/intro.xml”中定义我们的初始屏幕布局(使用您想要的任何图像)。我的特殊启动屏幕显示了一个带有图像的应用程序标题以及来自各种资金来源的 3 个徽标。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/layout_intro"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <TextView
        android:id="@+id/intro_Text_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:gravity="center"
        android:text="@string/title_intro"
        android:textAppearance="?android:attr/textAppearanceLarge" />

    <ImageView
        android:id="@+id/intro_Image_myproject"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/intro_Text_title"
        android:layout_centerHorizontal="true"
        android:src="@drawable/intro_image" />

    <FrameLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/intro_Image_myproject" 
        android:layout_alignRight="@id/intro_Image_myproject" 
        android:layout_alignLeft="@id/intro_Image_myproject">

        <ImageView
            android:id="@+id/intro_Image_logo1"
            android:layout_width="80dp"
            android:layout_height="50dp"
            android:scaleType="fitXY"
            android:src="@drawable/logo1" 
            android:layout_gravity="left|center_vertical"/>

        <ImageView
            android:id="@+id/intro_Image_logo2"
            android:layout_width="150dp"
            android:layout_height="wrap_content"
            android:src="@drawable/logo2" 
            android:layout_gravity="center" 
            android:scaleType="centerInside"/>

        <ImageView
            android:id="@+id/intro_Image_logo3"
            android:layout_width="70dp"
            android:layout_height="70dp"
            android:scaleType="fitXY"
            android:src="@drawable/logo3" 
            android:layout_gravity="right|center_vertical"/>

    </FrameLayout>

</RelativeLayout>

用于弹出对话框的代码:

@Override
protected void onCreate(Bundle aSavedState) {
    super.onCreate(aSavedState);
    if (aSavedState==null) {
        //only show splash screen at app start, not on rotate screen
        new AppIntro(this,R.layout.intro,R.anim.intro_anim).show();
    }
    setContentView(R.layout.main);
    //...rest of onCreate() 
}

我的应用程序在启动画面的同时显示了我的主视图,所以不能保证这个对话框会在你调用 .show() 时立即显示。

于 2013-08-27T18:47:20.393 回答
0

我也在寻找同样的东西。最后我实现了这个,它满足了我的要求。

笔记 :

  • 在创建第二个活动时完成所有繁重的工作。onStart()因此,当所有工作都完成后,调用后自动启动的活动。
  • onCreate()如果您希望某些代码在应用程序生命周期中只运行一次,您可以进行一些检查。
  • 不要在 ApplicationClass onCreate() 方法中做繁重的工作,因为它在您的应用程序启动时执行。所以在这个执行过程中会出现黑屏。

这是启动屏幕 xml:

<RelativeLayout 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="@drawable/splash_screen"
  tools:context=".SplashScreenActivity">
</RelativeLayout>

这是活动课

公共类 SplashScreenActivity 扩展 Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_splash_screen);
    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            Intent mainIntent = new Intent(SplashScreenActivity.this,
                    MyLauncherActivity.class);
            SplashScreenActivity.this.startActivity(mainIntent);
                         // SplashScreenActivity.this.finish(); No need to finish it as "noHistory" tag is true in the manifest
        }
    }, 1500);

}

@Override
public void onBackPressed() {
}
}

清单中的条目:

 <activity
        android:name="com.wokomoco.test.activities.SplashScreenActivity"
        android:label="@string/app_name"
        android:noHistory="true"
        android:screenOrientation="portrait" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

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

希望这会帮助你。享受编码!

于 2013-08-27T09:54:23.543 回答
0

打开初始屏幕的最佳方法是您可以为此创建一个新活动,然后在该活动中您可以设置一个计时器来打开一个新活动,这将是您的主要活动。我认为使用它可以摆脱您的开始时黑屏。在清单中将启动活动作为您的默认启动活动。这是示例:-

SplashActivity.java

public class SplashActivity extends Activity {

private Timer timer;

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

@Override
protected void onResume() {

    timer = new Timer();
            timer.schedule(new TimerTask() {
                @Override
                public void run() {
                    Intent intialScreenIntent = new Intent(SplashActivity.this, MainActivity.class);
                    startActivity(intialScreenIntent);
                }
            }, 2000l);
            super.onResume();       
}


@Override
public void onBackPressed() {
    try {
        timer.cancel();
        timer = null;
    } catch (Exception e) {
    }
    super.onBackPressed();
}}
于 2013-08-25T04:12:26.553 回答