如何在Android中制作真正的启动画面?我不想要定时器或延迟。只是在您的应用程序加载之前显示的启动画面。
如何在Android中制作真正的启动画面?我不想要定时器或延迟。只是在您的应用程序加载之前显示的启动画面。
就像是
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.splash);
handler = new Handler();
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
//Do some heavy stuff
return null;
}
@Override
public void onPostExecute(Void result){
handler.post(new Runnable(){
@Override
public void run(){
setContentView(R.layout.main);
}
});
}
}.execute();
}
带有代码的解决方案出现在过去六周似乎在许多测试设备上完美运行。
但是,在进入完整的启动画面之前,应该考虑一些预备知识。
首先,如果您可以通过立即调出应用程序的主视图来避免需要启动画面,让用户立即访问您的应用程序,这是您最好的选择。
您通常可以通过立即调出主显示器的图形,然后创建工作线程来执行任何耗时的初始化任务(例如加载应用程序始终使用的表)来实现此目的。
但是,它可能是 图像 你的主要观点 他们自己 设置和显示需要很长时间,并且您希望在初始化期间看到其他内容。
现在,如果您的主要活动具有简单(例如,默认),浅色或黑色,非透明背景,那么将立即提供至少确认 某物 在用户启动您的应用时发生。我个人发现作为原始“启动”显示工作的背景主题包括以下内容(要添加到清单文件中主要活动的活动标记):
android:theme="@style/Theme.Light.NoTitleBar"
android:theme="@style/Theme.Black.NoTitleBar"
在这方面我会注意到,如果你的活动背景需要任何类型的位图,动画或超出默认主题的其他可绘制(或如上所示的简单的浅色或黑色主题),我的经验是活动背景将是 不 显示,直到您的主视图仍然显示,所以只是将您的活动背景更改为自己 是 你的飞溅显示器(根据我的经验)没有比主屏幕提供的更快速的响应。
虽然上面这些简单的主题可以作为原始的“泼溅”使用,但也许您认为简单的浅色或黑色活动背景太过于提示您的应用已启动的提示,并且您希望显示应用的名称或徽标。用户在等。或者,也许是您的活动背景 必须 是 透明,因为你希望能够用自己的应用程序的视图覆盖其他应用程序(当然,这样的透明背景在启动时是不可见的,因此不会提示用户您的应用程序已经启动)。
如果在考虑了上面提到的所有替代方案之后,你仍然认为你需要一个闪屏,这是我个人发现的一种非常好的方法。
对于这种方法,您需要定义一个扩展LinearLayout的新类。你需要自己的课程的原因是因为你需要得到你的启动画面实际显示的肯定确认,这样你就可以立即继续显示你的主视图,而不需要只有一些计时器 猜测 你的启动画面出现多长时间。在这方面我会注意到,如果在显示启动视图后过快地开始显示主视图,则永远不会看到启动视图;使用这种方法避免了这种可能性。
以下是此类的示例:
public class SplashView extends LinearLayout {
public interface SplashEvents {
//This event is signaled after the splash and all of its child views,
// if any, have been drawn.
// As currently implemented, it will trigger BEFORE any scrollbars are drawn.
// We are assuming that there will BE no scrollbars on a SplashView.
public void onSplashDrawComplete();
}
private SplashEvents splashEventHandler = null;
public void setSplashEventHandler(SplashEvents splashEventHandler) {
this.splashEventHandler = splashEventHandler;
}
private void fireSplashDrawCompleteEvent() {
if(this.splashEventHandler != null) {
this.splashEventHandler.onSplashDrawComplete();
}
}
public SplashView(Context context) {
super(context);
//This is set by default for a LinearLayout, but just making sure!
this.setWillNotDraw(true);
//If the cache is not enabled, then I think that helps to ensure that
// dispatchDraw override WILL
// get called. Because if caching were enabled, then the
//drawing might not occur.
this.setDrawingCacheEnabled(false);
setGravity(Gravity.CENTER);
//This splices in your XML definition (see below) to the SplashView layout
LayoutInflater.from(context).inflate(R.layout.splashscreen, this, true);
}
@Override
protected void dispatchDraw(Canvas canvas) {
//Draw any child views
super.dispatchDraw(canvas);
//Signal client objects (in this case, your main activity) that
// we have finished initializing and drawing the view.
fireSplashDrawCompleteEvent();
}
}
因为我们从视图中加载XML,所以我们需要使用a在XML中定义它 <merge>
标记为“拼接”在XML定义的元素中作为SplashView类的子元素。这是一个示例(放在应用程序的res / layout文件夹中),您可以根据自己的需要进行定制:
<merge xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center_horizontal"
>
<TextView android:id="@+id/tvHeading"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center"
android:textSize="30dp"
android:textStyle="bold"
android:text="Loading..."
android:layout_weight="1.0"
android:textColor="#00ff00"
android:background="#AA000000"
/>
</merge>
请注意,TextView定义为半透明的黑色背景,因此它会导致启动器显示变暗,文本“Loading ...”以绿色叠加在顶部。
剩下的就是在主活动的onCreate()方法中编辑以下内容(及以上):
private Handler uiThreadHandler = new Handler();
@Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Create an instance of the splash view, and perform a setContentView()
SplashView splashView = new SplashView(this);
//Doing this allows you to access the "this" pointer of the main
// activity inside the Runnable below.
final main mainThis = this;
// Set an event handler on the SplashView object, so that as soon
// as it completes drawing we are
// informed. In response to that cue, we will *then* put up the main view,
// replacing the content view of the main activity with that main view.
splashView.setSplashEventHandler(new SplashView.SplashEvents() {
@Override
public void onSplashDrawComplete() {
//Post the runnable that will put up the main view
uiThreadHandler.post(new Runnable() {
@Override
public void run() {
//This method is where you will have moved
// the entire initialization of your app's
// main display, which normally would have been
// in your onCreate() method prior to adding the
// splash display.
launchMainView(mainThis, savedInstanceState);
}
});
}
});
//This will cause your splash view to draw. When it finishes, it will trigger the code above.
this.setContentView(splashView);
//At this point, do *not* move directly on to performing a setContentView() on your main view.
// If you do, you will never see the splash view at all.
// You simply wait for the splash view to signal you that it has completed drawing itself, and
// *then* call launchMainView(), which will itself call setContentView() again, passing it
// your main view.
}
//Here is a stripped-down version of launchMainView(). You will typically have some additional
// initializations here - whatever might have been present originally in your onCreate() method.
public void launchMainView(main mainThis, Bundle savedInstanceState) {
myRootView = new MyRootView(mainThis);
setContentView(myRootView);
}
上述方法对我来说非常有效。我使用它仅针对API级别8,并且已经在运行Android 2.2.1,2.3.3和4.0.1(ICS)的各种设备(包括手机和平板电脑)上测试了该代码。
上述方法的潜在责任是,对于某些情况的组合,可能会出现飞溅视图 不 表示它已完成,因此飞溅将“卡在”主显示屏上,没有主视图可以替换它。这从来没有发生在我身上,但是我想在这里征求关于上面SplashView中的dispatchDraw()重写的意见。 不 被叫。我对触发dispatchDraw()的代码进行了视觉检查,并且在我看来我在SplashView构造函数中完成的初始化时,它看起来好像总会被调用。
如果有人有更好的方法来覆盖同样的目的,我会很感激听到它。令我感到惊讶的是,当一个视图完成显示时,我无法找到专门用于触发的任何覆盖,因此,如果存在并且我以某种方式错过了它,请在下面发表评论。评论肯定了这种方法 将 工作也很受欢迎!
它不那么难;你只需创建一个你将用作启动画面的视图(一个布局简单且不需要大量测量的视图),使用setContentView将其设置为活动的内容;
然后使用复杂的布局再次调用活动上的setContentView,这需要一段时间来构建。在使用复杂布局第二次调用setContent之前,甚至可以使用Asynctask来加载数据。这取决于您是否受到数据加载或视图构建的约束。
public class MyLocationListener extends Activity {
public Handler myHandler = new Handler(){
public void handlerMessage(Message msg){
set you contentView here after splash screen
}
}
public MyLocationListener(Context context){
this.context = context;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splashscreen);
// don't set Content View here instead start a thread here to do the task yiou want to do.
// Now post message from new thread to UI Thread using handlers.
}
}
制作启动画面的最佳方法是:
我到达了这个很好的解决方案:
import android.app.Activity; import android.content.Intent; import android.os.AsyncTask; import android.os.Bundle; import android.view.WindowManager; import br.eti.fml.android.sigame.R;
import java.util.concurrent.atomic.AtomicBoolean;
public class LauncherActivity extends Activity {
private AsyncTask goingToNextScreen;
private AtomicBoolean alreadyShown = new AtomicBoolean(false);
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.launcher);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
//noinspection unchecked
goingToNextScreen = new AsyncTask() {
@Override
protected Object doInBackground(Object... objects) {
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
// ignores
}
return null;
}
@Override
protected void onPostExecute(Object o) {
goNext();
}
}.execute();
}
@Override
public void onBackPressed() {
if (goingToNextScreen != null) {
goingToNextScreen.cancel(true);
goNext();
}
}
private void goNext() {
if (alreadyShown.compareAndSet(false, true)) {
startActivity(new Intent(LauncherActivity.this, HomeActivity.class));
overridePendingTransition(0, 0);
finish();
overridePendingTransition(0, 0);
}
} }
有时,使用splash,应用程序需要几毫秒或秒来加载Activity的内容。
如果你只想要像往常一样的“backgorund图像”启动画面。我认为最好的方法是使用主题。
以SherlockActionBar为例:
<style name="SplashTheme" parent="Theme.Sherlock.NoActionBar">
...
<item name="android:windowBackground">@drawable/splash</item>
...
</style>
splash可以是.9文件来填充屏幕。
并且清单中的活动必须是这样的
<activity
android:name=".SplashActivity"
...
android:theme="@style/SplashTheme"
...>
...
</activity>
那么你的代码中不需要setContent(View)行。并且主题将比内容加载更快。
这允许您从应用程序加载开始时拥有启动画面。没有黑色的窗户或动作栏或类似的东西。
// Splash代码的代码
public class SplashScreen extends Activity {
static int SPLASH_TIMEOUT = 5000;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash_layout);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
startActivity(new Intent(SplashScreen.this, MainActivity.class));
finish();
}
}, SPLASH_TIMEOUT);
}
}
这里 SPLASH_TIMEOUT 将定义您自己的活动应该如何显示,所以根据您的需要更改此值。
// MainActivity.class的代码
public class MainActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}