Bài này tôi sẽ hướng dẫn các bạn cài đặt Splash Screen một cách thật đơn giản, nó hiển thị lúc khởi động và sẽ chạy trong một khoảng thời gian ngắn nào đó.
OK! let's start
1. Create Launcher activity (Đây sẽ là SplashScreen của bạn)
2. Tạo main Activity của bạn (Màn hình chính của game)
3. Cài đặt Splash với một layout chứa 1 progressBar
4. Bắt đầu a Task để load Resource của bạn
5. Gọi lại Plash của bạn mà bạn vừa mới finish();
6. Start yout app
Đầu tiên chúng ta bắt đầu với SplashActivity. Cái này chưa ProgressBar mà biểu diễn ứng dụng của bạn loading.
SplashActivity.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
| package com.blundell.tut.ui; import com.blundell.tut.R; import com.blundell.tut.task.LoadingTask; import com.blundell.tut.task.LoadingTask.LoadingTaskFinishedListener; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.widget.ProgressBar; public class SplashActivity extends Activity implements LoadingTaskFinishedListener { @Override public void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); // Show the splash screen setContentView(R.layout.activity_splash); // Find the progress bar ProgressBar progressBar = (ProgressBar) findViewById(R.id.activity_splash_progress_bar); // Start your loading new LoadingTask(progressBar, this ).execute( "www.google.co.uk" ); // Pass in whatever you need a url is just an example we don't use it in this tutorial } // This is the callback for when your async task has finished @Override public void onTaskFinished() { completeSplash(); } private void completeSplash(){ startApp(); finish(); // Don't forget to finish this Splash Activity so the user can't return to it! } private void startApp() { Intent intent = new Intent(SplashActivity. this , MainActivity. class ); startActivity(intent); } } |
Bạn chú ý. Lớp trên cài đặt giao diện LoadingTaskFinishedListener sử dụng giao diện là 1 cách của việc giao tiếp giữa các lớp. Bạn đang nói "Tôi có khả năng nhận về một thông điệp mà trông giống ...this" Bởi vì ASyncTask có 1 trường mà là 1 đối tượng của giao diện đó nó có thể bất chợt phát ra những thông điệp đó và Activity của bạn sẽ nhận được chúng . Tiếp theo là ASyncTask
LoadingTask.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
| package com.blundell.tut.task; import android.os.AsyncTask; import android.util.Log; import android.widget.ProgressBar; public class LoadingTask extends AsyncTask<String, Integer, Integer> { public interface LoadingTaskFinishedListener { void onTaskFinished(); // If you want to pass something back to the listener add a param to this method } // This is the progress bar you want to update while the task is in progress private final ProgressBar progressBar; // This is the listener that will be told when this task is finished private final LoadingTaskFinishedListener finishedListener; /** * A Loading task that will load some resources that are necessary for the app to start * @param progressBar - the progress bar you want to update while the task is in progress * @param finishedListener - the listener that will be told when this task is finished */ public LoadingTask(ProgressBar progressBar, LoadingTaskFinishedListener finishedListener) { this .progressBar = progressBar; this .finishedListener = finishedListener; } @Override protected Integer doInBackground(String... params) { Log.i( "Tutorial" , "Starting task with url: " +params[ 0 ]); if (resourcesDontAlreadyExist()){ downloadResources(); } // Perhaps you want to return something to your post execute return 1234 ; } private boolean resourcesDontAlreadyExist() { // Here you would query your app's internal state to see if this download had been performed before // Perhaps once checked save this in a shared preference for speed of access next time return true ; // returning true so we show the splash every time } private void downloadResources() { // We are just imitating some process thats takes a bit of time (loading of resources / downloading) int count = 10 ; for ( int i = 0 ; i < count; i++) { // Update the progress bar after every step int progress = ( int ) ((i / ( float ) count) * 100 ); publishProgress(progress); // Do some long loading things try { Thread.sleep( 1000 ); } catch (InterruptedException ignore) {} } } @Override protected void onProgressUpdate(Integer... values) { super .onProgressUpdate(values); progressBar.setProgress(values[ 0 ]); // This is ran on the UI thread so it is ok to update our progress bar ( a UI view ) here } @Override protected void onPostExecute(Integer result) { super .onPostExecute(result); finishedListener.onTaskFinished(); // Tell whoever was listening we have finished } } |
LoadingTask là bộ khung của ASyncTask, chúng ta cài đặt 1 callBack trong constructor. sau đó kiểm tra nếu Resources của ta tải về mà tồn tại,......nếu không. Một khi chúng ta tải về kết thúc chúng ta thông báo lại Listener.
Nhiệm vụ này bắt trước.....kiểu như giả loadding Nhưng ở bài này nó không phải là trọng tâm. Bạn nhận thấy mỗi vòng lặp được hoàn tất chúng sẽ update progressbar. Bạn hãy nhớ rằng 1 progressbar là 1 Android View Object. View Object là 1 phần của UI vì vậy có thể update trên UIThread. Vì vậy chúng ta sử dụng onProgressUpdate() method mà android cung cấp chắc chắn chạy trên UIThead.
Khi updating 1 progressbar bạn gửi nó giá trị từ 0-100 và giá trị này sẽ là progressbar của nó. Trong ví dụ này chúng ta chạy qua 1 vòng lặp đếm tới 10 do đó mỗi vòng lặp sẽ là 10% của progressbar.
VD: In AndEngine
- public class MainGameActivity extends BaseGameActivity {
- // ===========================================================
- // Final Fields
- // ===========================================================
- // ===========================================================
- // Constants
- // ===========================================================
- private static final int CAMERA_WIDTH = 480;
- private static final int CAMERA_HEIGHT = 800;
- // ===========================================================
- // Fields
- // ===========================================================
- protected Camera mCamera;
- // splash scene
- protected Scene mSplashScene;
- private BitmapTextureAtlas mSplashBackgroundTextureAtlas;
- private TextureRegion mSplashBackgroundTextureRegion;
- // menu scene
- protected Scene mMenuScene;
- // ...
- // ===========================================================
- // Methods for/from SuperClass/Interfaces
- // ===========================================================
- @Override
- public Engine onLoadEngine() {
- this.mCamera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);
- return new Engine(new EngineOptions(true, ScreenOrientation.PORTRAIT,new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT),this.mCamera).setNeedsSound(true));
- }
- @Override
- public void onLoadResources() {
- BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("gfx/");
- mSplashBackgroundTextureAtlas = new BitmapTextureAtlas(512, 1024, TextureOptions.NEAREST);
- mSplashBackgroundTextureRegion =BitmapTextureAtlasTextureRegionFactory.createFromAsset(mSplashBackgroundTextureAtlas,this, "splash.jpg", 0, 0);
- mEngine.getTextureManager().loadTextures(mSplashBackgroundTextureAtlas);
- }
- @Override
- public Scene onLoadScene() {
- mSplashScene = new Scene();
- mSplashScene.setBackgroundEnabled(false);
- mSplashScene.attachChild(new Sprite(0, 0, mSplashBackgroundTextureRegion));
- return this.mSplashScene;
- }
- @Override
- public void onLoadComplete() {
- mEngine.registerUpdateHandler(new TimerHandler(0.01f, newITimerCallback() {
- @Override
- public void onTimePassed(final TimerHandler pTimerHandler) {
- mEngine.unregisterUpdateHandler(pTimerHandler);
- loadResources();
- loadScenes();
- mEngine.setScene(mMenuScene);
- }
- }));
- }
- // ===========================================================
- // Methods
- // ===========================================================
- public void loadResources() {
- // menu resources
- // help resources
- // pick level resources
- // game resources
- }
- public void loadScenes() {
- // menu scene
- // help scene
- // pick level scene
- // game scene
- }
- }
ViDu:
The problem is most likely that you are running the splash screen (some sort of Dialog such asProgressDialog I assume) in the same thread as all the work being done. This will keep the view of the splash screen from being updated, which can keep it from even getting displayed to the screen. You need to display the splash screen, kick off an instance of AsyncTask to go download all your data, then hide the splash screen once the task is complete.
So your Activity's onCreate() method would simply create a ProgressDialog and show it. Then create the AsyncTask and start it. I would make the AsyncTask an inner class of your main Activity, so it can store the data it has downloaded to some variable in your Activity and close the ProgressDialog in its onPostExecute() method.
Not sure how to elaborate anymore without just showing the code, so here it is:
public class MyActivity extends Activity {
private ProgressDialog pd = null;
private Object data = null;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Show the ProgressDialog on this thread
this.pd = ProgressDialog.show(this, "Working..", "Downloading Data...", true, false);
// Start a new thread that will download all the data
new DownloadTask().execute("Any parameters my download task needs here");
}
private class DownloadTask extends AsyncTask<String, Void, Object> {
protected Object doInBackground(String... args) {
Log.i("MyApp", "Background thread starting");
// This is where you would do all the work of downloading your data
return "replace this with your data object";
}
protected void onPostExecute(Object result) {
// Pass the result data back to the main activity
MyActivity.this.data = result;
if (MyActivity.this.pd != null) {
MyActivity.this.pd.dismiss();
}
}
}
}
Obviously there are some pieces you need to fill in there, but this code should run and give you a good starting point (forgive me if there is a code error, I don't have access to the Android SDK as I'm typing this currently).
Hoac:
public class SplashScreen extends Activity{
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
// set the content view for your splash screen you defined in an xml file
setContentView(R.layout.splashscreen);
// perform other stuff you need to do
// execute your xml news feed loader
new AsyncLoadXMLFeed().execute();
}
private class AsyncLoadXMLFeed extends AsyncTask<Void, Void, Void>{
@Override
protected void onPreExecute(){
// show your progress dialog
}
@Override
protected Void doInBackground(Void... voids){
// load your xml feed asynchronously
}
@Override
protected void onPostExecute(Void params){
// dismiss your dialog
// launch your News activity
Intent intent = new Intent(SplashScreen.this, News.class);
startActivity(intent);
// close this activity
finish();
}
}
}
Không có nhận xét nào:
Đăng nhận xét