Android SplashScreen

80

Tworzę aplikację, która w zasadzie pobiera dużo danych na początku samej aplikacji i wyświetla je w ListActivity. Planuję pokazać ekran powitalny do momentu załadowania danych.

Do tej pory wszystkie moje próby były daremne. Wypróbowałem anddev.org wspomniałem o metodach, ale moim problemem jest to, że główna aktywność powinna się rozpocząć, ale ekran powitalny powinien być widoczny, dopóki nie zapełnię mojego ListActivity. Krótko mówiąc, muszę wykonać następujące kroki:

  1. Rozpocznij moją główną działalność.
  2. Pokaż ekran powitalny.
  3. Kontynuuj proces w tle.
  4. Zamknij ekran powitalny po zakończeniu przetwarzania i wyświetl główną listę.

Mam nadzieję, że rozumiesz, jak to jest ....

JaVadid
źródło
Czy ktoś może wyjaśnić, że nawet pasek postępu się nie ładuje, nawet jeśli spróbuję go utworzyć i uruchomić w funkcji OnCreate mojej listy głównej ... i odrzucić po zakończeniu mojego procesu ... nawet to nie działa ... i znaczy, czy jest jakaś domyślna metodologia, której muszę przestrzegać ... jak uruchomienie paska postępu w OnStart () czy coś takiego?
JaVadid
Czy spróbowałeś, co mówi akceptowana odpowiedź na stackoverflow.com/questions/2222890/… ? EDYCJA: Ok, zaakceptowana odpowiedź jest taka sama ...
noloman

Odpowiedzi:

89

Problem jest najprawdopodobniej uruchamiany na ekranie powitalnym ( zakładam, że jakiś dialog taki jak ProgressDialog ) w tym samym wątku, co cała wykonywana praca. Dzięki temu widok ekranu powitalnego nie będzie aktualizowany, co może uniemożliwić nawet wyświetlenie go na ekranie. Musisz wyświetlić ekran powitalny, uruchomić wystąpienie AsyncTask, aby pobrać wszystkie swoje dane, a następnie ukryć ekran powitalny po zakończeniu zadania.

Zatem metoda onCreate () Twojego działania po prostu utworzy ProgressDialog i wyświetli go. Następnie utwórz AsyncTask i uruchom go. Uczyniłbym AsyncTask klasą wewnętrzną twojego głównego działania, aby mógł przechowywać dane, które pobrał w jakiejś zmiennej w twoim działaniu i zamknąć ProgressDialog w swojej metodzie onPostExecute ().

Nie jestem pewien, jak rozwinąć więcej bez pokazywania kodu, więc oto jest:

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();
             }
         }
    }    
}

Oczywiście jest kilka elementów, które musisz tam wypełnić, ale ten kod powinien działać i dać ci dobry punkt wyjścia (wybacz mi, jeśli jest błąd kodu, nie mam dostępu do Android SDK, gdy to piszę w tej chwili).

Więcej dobrych lektur na temat AsyncTasks w systemie Android można znaleźć tutaj i tutaj .

Mark B.
źródło
Co masz na myśli mówiąc „zamień na obiekt danych”? Mam dwie funkcje, które chcę załadować do zadania asynchronicznego, tak jak powiedziałeś, ale nie wiem, co mam zwrócić. Próbowałem zwrócić wartość null, ale aplikacja ulega awarii.
Nick
AsyncTask <String, Void, Object> gdzie Object reprezentuje typ danych, który chcesz zwrócić. Zobacz sekcję „Typy ogólne AsyncTask” tutaj: developer.android.com/reference/android/os/AsyncTask.html
Mark B
Wiem, że to jest stare, ale próbowałem to zaimplementować i ProgressDialog(w moim przypadku zwykły dialog, który ładuje układ) nigdy nie jest wyświetlany. Widzę to tylko wtedy, gdy skomentuję .dismiss()w onPostExecute. Pierwszy ekran, który widzę, wciąż jest MyActivitytematem. Potem idzie prosto do R.layout.main.
Kevin_TA
@Kevin_TA, jeśli .dismiss () powoduje, że nie jest wyświetlany, oznacza to, że AsyncTask natychmiast się kończy. Metoda, którą opisałem, służy do wyświetlania ekranu powitalnego, który wyświetla się podczas uruchamiania niektórych długotrwałych zadań startowych.
Mark B
@mbaird to nie kończy się natychmiast. Rzeczywiście mam proces w tle, który trwa 2-3 sekundy. Z jakiegoś powodu jednak nic w interfejsie użytkownika nie jest aktualizowane, dopóki nie zakończy się Async, co zniweczy cel.
Kevin_TA
61

tylko w celach informacyjnych jest to najlepszy sposób, w jaki znalazłem ekran powitalny: http://android-developers.blogspot.de/2009/03/window-backgrounds-ui-speed.html

Szukałem tego od dłuższego czasu, z dokumentacji androida ... jeśli chcesz uniknąć tych czarnych ekranów, musisz utworzyć motyw z windowBackground, więc:

<resources>
    <style name="Theme.Shelves" parent="android:Theme">
        <item name="android:windowBackground">@drawable/background_shelf</item>
        <item name="android:windowNoTitle">true</item>
    </style>
</resources>

I ustaw ten motyw jako motyw swojej głównej aktywności ... TADA, ekran powitalny od pierwszej sekundy.

Jeśli chcesz mieć złożone tło, a nie tylko obraz, który zostanie rozciągnięty w celu wypełnienia, możesz użyć Drawables, oto przykład listy warstw, która utrzyma logo wyśrodkowane na czarnym tle:

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

    <item android:drawable="@color/black">
    </item>
    <item>
        <bitmap
            android:gravity="center"
            android:src="@drawable/logo"
            android:tileMode="disabled" >
        </bitmap>
    </item>
</layer-list>
Raanan
źródło
1
ten link jest martwy, ale zawartość strony i kod źródłowy są dostępne na archive.org: web.archive.org/web/20101113015720/http://developer.android.com/…
Spoonface
Czy istnieje sposób na użycie pliku layout.xml zamiast pliku do rysowania dla systemu Android: windowBackground? Kiedy próbuję to zrobić, dochodzi do awarii, ale zastanawiam się, czy istnieje obejście.
Kevin_TA
@Kevin_TA no, nie ma. ALE możesz używać Drawables, więc jeśli chcesz mieć Logo na środku ekranu, powinieneś użyć listy warstw, którą można rysować i użyć grawitacji, aby ustawić swoje obrazy. Zaktualizuję odpowiedź przykładem.
Raanan
1
Rozwiązanie @Ranaan Theme działa dla mnie, ale jak mam połączyć listę warstw z motywem?
deko
2
@deko item name = "android: windowBackground" może być ustalonym kolorem lub obrazem lub plikiem XML do rysowania, takim jak lista warstw umieszczona w folderze res / drawable. Możesz przeczytać o Drawables tutaj: developer.android.com/guide/topics/resources/…
Raanan
1

Przykładowy ekran powitalny:

public class MainActivity extends Activity {
    private ImageView splashImageView;
    boolean splashloading = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        splashImageView = new ImageView(this);
        splashImageView.setScaleType(ScaleType.FIT_XY);
        splashImageView.setImageResource(R.drawable.ic_launcher);
        setContentView(splashImageView);
        splashloading = true;
        Handler h = new Handler();
        h.postDelayed(new Runnable() {
            public void run() {
                splashloading = false;
                setContentView(R.layout.activity_main);
            }

        }, 3000);

    }

}
kablu
źródło
1
  1. Rozpocznij moją główną działalność.
  2. Pokaż ekran powitalny.
  3. Kontynuuj proces w tle.
  4. Zamknij ekran powitalny po zakończeniu przetwarzania i wyświetl główną listę.

Próbowałem w ten sposób, ale problem jest; pokaże główne działanie przed rozpoczęciem działania na ekranie powitalnym.

Zrobiłem to w ten sposób:

  1. Uruchom ekran powitalny
  2. Po zakończeniu procesu rozpocznij „główne działanie”
  3. Nie zapomnij obsługiwać przycisku Wstecz, więc powinien zamknąć aplikację, zostanie naciśnięty w głównym działaniu. W przeciwnym razie powróci do ekranu powitalnego (pętla)

Mój problem polega na tym, jak wyłączyć opcję „pokaż menu aktywności ekranu powitalnego”, naciskając przycisk menu.

Edytować:

Wyłącz menu pokazu:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // getMenuInflater().inflate(R.menu.activity_main, menu);
    return false;
}

@Override
public boolean onMenuItemSelected(int featureId, MenuItem item) {       
    // return super.onMenuItemSelected(featureId, item);
    return false;
}
Gabe
źródło