Android SplashScreen

80

Ich entwickle eine Anwendung, die zu Beginn der Anwendung selbst im Grunde genommen viele Daten herunterlädt und in der ListActivity anzeigt. Ich habe vor, einen Begrüßungsbildschirm anzuzeigen, bis die Daten geladen sind.

Bis jetzt waren alle meine Versuche erfolglos. Ich habe versucht, die von anddev.org erwähnten Methoden zu verwenden, aber mein Problem ist, dass die Hauptaktivität gestartet werden sollte, der Begrüßungsbildschirm jedoch sichtbar sein sollte, bis ich meine ListActivity auffülle. Kurz gesagt, ich muss die folgenden Schritte ausführen:

  1. Starten Sie meine Hauptaktivität.
  2. Zeigen Sie den Begrüßungsbildschirm an.
  3. Führen Sie den Prozess im Hintergrund weiter aus.
  4. Verlassen Sie den Begrüßungsbildschirm, wenn die Verarbeitung abgeschlossen ist, und zeigen Sie die Hauptliste an.

Hoffe du verstehst wie es ist ....

JaVadid
quelle
Kann jemand erklären, dass selbst ein Fortschrittsbalken nicht geladen wird, selbst wenn ich versuche, ihn in der OnCreate-Funktion meiner Hauptliste zu erstellen und zu starten ... und ihn nach Abschluss meines Prozesses zu schließen ... auch wenn dies nicht funktioniert ... i Mittel gibt es eine Standardmethode, die ich befolgen muss ... wie das Starten des Fortschrittsbalkens in OnStart () oder so?
JaVadid
Haben Sie versucht, was die akzeptierte Antwort in stackoverflow.com/questions/2222890/… sagt? EDIT: Ok, die akzeptierte Antwort ist irgendwie die gleiche ..
Noloman

Antworten:

89

Das Problem ist höchstwahrscheinlich, dass Sie den Begrüßungsbildschirm (eine Art Dialog wie ProgressDialog, nehme ich an) im selben Thread wie die gesamte ausgeführte Arbeit ausführen. Dadurch wird verhindert, dass die Ansicht des Begrüßungsbildschirms aktualisiert wird, sodass er nicht einmal auf dem Bildschirm angezeigt wird. Sie müssen den Begrüßungsbildschirm anzeigen, eine Instanz von AsyncTask starten , um alle Ihre Daten herunterzuladen, und den Begrüßungsbildschirm ausblenden, sobald die Aufgabe abgeschlossen ist.

Die onCreate () -Methode Ihrer Aktivität erstellt also einfach einen ProgressDialog und zeigt ihn an. Erstellen Sie dann die AsyncTask und starten Sie sie. Ich würde die AsyncTask zu einer inneren Klasse Ihrer Hauptaktivität machen, damit sie die heruntergeladenen Daten in einer Variablen in Ihrer Aktivität speichern und den ProgressDialog in der onPostExecute () -Methode schließen kann.

Ich bin mir nicht sicher, wie ich weiter arbeiten soll, ohne nur den Code zu zeigen. Hier ist es also:

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

Natürlich gibt es einige Teile, die Sie dort ausfüllen müssen, aber dieser Code sollte ausgeführt werden und Ihnen einen guten Ausgangspunkt bieten (verzeihen Sie mir, wenn ein Codefehler auftritt, habe ich während der Eingabe keinen Zugriff auf das Android SDK zur Zeit).

Weitere gute Informationen zum Thema AsyncTasks in Android finden Sie hier und hier .

Mark B.
quelle
Was meinst du mit Rückgabe "durch Datenobjekt ersetzen"? Ich habe meine zwei Funktionen, die ich in die Asynctask laden möchte, wie Sie gesagt haben, aber ich weiß nicht, was ich zurückgeben soll. Ich habe versucht, null zurückzugeben, aber die App stürzt ab.
Nick
AsyncTask <String, Void, Object> wobei Object den Datentyp darstellt, den Sie zurückgeben möchten. Siehe den Abschnitt "AsyncTask's generische Typen" hier: developer.android.com/reference/android/os/AsyncTask.html
Mark B
Das ist alt, ich weiß, aber ich habe versucht, dies zu implementieren, und das ProgressDialog(in meinem Fall ein regulärer Dialog, der ein Layout lädt) wird nie angezeigt. Ich sehe es nur, wenn ich das .dismiss()in der kommentiere onPostExecute. Der erste Bildschirm, den ich sehe, ist immer noch das MyActivityThema. Danach geht es direkt zu R.layout.main.
Kevin_TA
@Kevin_TA Wenn .dismiss () dazu führt, dass es nicht angezeigt wird, wird Ihre AsyncTask sofort beendet. Die von mir beschriebene Methode dient zum Anzeigen eines Begrüßungsbildschirms, der angezeigt wird, während eine lange laufende Startaufgabe ausgeführt wird.
Mark B
@mbaird es endet nicht sofort. Ich habe in der Tat einen Hintergrundprozess, der 2-3 Sekunden dauert. Aus irgendeinem Grund wird jedoch nichts auf der Benutzeroberfläche aktualisiert, bis die Asynchronisierung abgeschlossen ist, wodurch der Zweck zunichte gemacht wird.
Kevin_TA
61

Nur als Referenz ist dies der beste Weg, um einen Begrüßungsbildschirm zu erstellen: http://android-developers.blogspot.de/2009/03/window-backgrounds-ui-speed.html

Ich habe eine ganze Weile danach gesucht, aus Androids-Dokumenten. Wenn Sie diese schwarzen Bildschirme vermeiden möchten, müssen Sie ein Thema mit windowBackground erstellen, also:

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

Und legen Sie dieses Thema als Thema für Ihre Hauptaktivität fest ... TADA, Begrüßungsbildschirm von der ersten Sekunde an.

Wenn Sie einen komplexen Hintergrund und nicht nur ein Bild wünschen, das zum Füllen gedehnt wird, können Sie Drawables verwenden. Hier ist ein Beispiel für eine Ebenenliste, in der das Logo mit einem schwarzen Hintergrund zentriert bleibt:

<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
quelle
1
Dieser Link ist tot, aber der Seiteninhalt und der Quellcode sind auf archive.org verfügbar: web.archive.org/web/20101113015720/http://developer.android.com/…
Spoonface
Gibt es eine Möglichkeit, eine layout.xml anstelle einer für Android zu zeichnenden Datei zu verwenden: windowBackground? Ich bekomme einen Absturz, wenn ich das versuche, aber ich frage mich, ob es eine Problemumgehung gibt.
Kevin_TA
@ Kevin_TA nein gibt es nicht. ABER Sie können Drawables verwenden. Wenn Sie also ein Logo in der Mitte des Bildschirms haben möchten, sollten Sie eine Drawable-Ebenenliste verwenden und die Schwerkraft verwenden, um Ihre Bilder zu positionieren. Ich werde die Antwort mit einem Beispiel aktualisieren.
Raanan
1
Die @ Ranaan Theme-Lösung funktioniert für mich, aber wie soll ich die Layer-Liste mit dem Theme verbinden?
Deko
2
@deko item name = "android: windowBackground" kann entweder eine feste Farbe oder ein Bild oder eine XML-Zeichenliste sein, die wie eine Ebenenliste in Ihrem res / drawable-Ordner abgelegt werden kann. Sie können über Drawables hier lesen: developer.android.com/guide/topics/resources/…
Raanan
1

Beispiel für einen Begrüßungsbildschirm:

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
quelle
1
  1. Starten Sie meine Hauptaktivität.
  2. Zeigen Sie den Begrüßungsbildschirm an.
  3. Führen Sie den Prozess im Hintergrund weiter aus.
  4. Verlassen Sie den Begrüßungsbildschirm, wenn die Verarbeitung abgeschlossen ist, und zeigen Sie die Hauptliste an.

Ich habe es auf diese Weise versucht, aber das Problem ist; Es wird die Hauptaktivität angezeigt, bevor die Begrüßungsbildschirmaktivität gestartet wird.

Ich habe es so gemacht:

  1. Starten Sie den Begrüßungsbildschirm
  2. Wenn der Vorgang abgeschlossen ist, starten Sie die "Hauptaktivität".
  3. Vergessen Sie nicht, die Zurück-Taste zu betätigen, damit sie geschlossen wird. Die App wird in der Hauptaktivität gedrückt. Andernfalls kehren Sie zum Begrüßungsbildschirm zurück (Schleife)

Mein Problem ist, wie man "Menü der Begrüßungsbildschirmaktivität anzeigen" durch Drücken der Menütaste deaktiviert.

Bearbeiten:

Show-Menü deaktivieren:

@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
quelle