Verwenden des "animierten Kreises" in einer ImageView beim Laden von Inhalten


219

Ich verwende derzeit in meiner Anwendung eine Listenansicht, für deren Anzeige möglicherweise eine Sekunde benötigt wird.

Derzeit verwende ich die Eigenschaft @ id / android: empty der Listenansicht, um einen "Lade" -Text zu erstellen.

 <TextView android:id="@id/android:empty"
           android:layout_width="match_parent"
           android:layout_height="match_parent"
           android:background="#FF0000"
           android:text="Loading..."/>

Jetzt möchte ich das durch den animierten Kreis ersetzen, der in einem Ladedialog anstelle dieses Textes verwendet wird. Ich denke, Sie alle wissen, was ich meine:

Bearbeiten: Ich möchte keinen Dialog. Ich möchte das in meinem Layout zeigen.

http://flexfwd.com/DesktopModules/ATI_Base/resources/images/loading_blue_circle.gif

Vielen Dank für Ihre Hilfe!

Antworten:


443

Fügen Sie einfach diesen XML-Block in Ihre Aktivitätslayoutdatei ein:

<RelativeLayout
    android:id="@+id/loadingPanel"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center" >

    <ProgressBar
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:indeterminate="true" />
</RelativeLayout>

Und wenn Sie mit dem Laden fertig sind, rufen Sie diese eine Zeile auf:

findViewById(R.id.loadingPanel).setVisibility(View.GONE);

Das Ergebnis (und es dreht sich auch):

Geben Sie hier die Bildbeschreibung ein


17
zerschmetterte die +1 Taste
TSR

Ich kann nicht sehen, wie dies das Problem löst, einen animierten Kreis in einer ImageView anzuzeigen.
Gustavo

4
@Gustavo, das ist es, was er will, um eine "unbestimmte Fortschrittsanimation" zu zeigen, also denke ich, dass es das Problem löst. ; -]
Thalis Vilela

143

Sie können dies tun, indem Sie die folgende XML verwenden

<RelativeLayout
    style="@style/GenericProgressBackground"
    android:id="@+id/loadingPanel"
    >
    <ProgressBar
        style="@style/GenericProgressIndicator"/>
</RelativeLayout>

Mit diesem Stil

<style name="GenericProgressBackground" parent="android:Theme">
    <item name="android:layout_width">fill_parent</item>    
    <item name="android:layout_height">fill_parent</item>
    <item name="android:background">#DD111111</item>    
    <item name="android:gravity">center</item>  
</style>
<style name="GenericProgressIndicator" parent="@android:style/Widget.ProgressBar.Small">
    <item name="android:layout_width">wrap_content</item>
    <item name="android:layout_height">wrap_content</item>
    <item name="android:indeterminate">true</item> 
</style>

Um dies zu verwenden, müssen Sie Ihre UI-Elemente ausblenden, indem Sie den Sichtbarkeitswert auf GONE setzen. Wenn die Daten geladen werden, rufen Sie setVisibility(View.VISIBLE)alle Ihre Ansichten auf, um sie wiederherzustellen. Vergessen Sie nicht anzurufen findViewById(R.id.loadingPanel).setVisiblity(View.GONE), um die Ladeanimation auszublenden.

Wenn Sie kein Ladeereignis / keine Ladefunktion haben, aber nur möchten, dass das Ladefeld nach x Sekunden verschwindet, verwenden Sie einen Griff , um das Ausblenden / Anzeigen auszulösen.


4
Gute Antwort. Über die Google-Suche gefunden und auch mein Problem gelöst. Vielen Dank!
Dave

Mit dieser Methode erhalte ich eine NullPointerException in der findViewById(...).setVisibility(View.GONE)Zeile, wenn ich den Bildschirm drehe . Funktioniert wie ein Zauber in einer Ausrichtung, aber eine Idee, warum dies brechen könnte?
Kalina

Ich habe eine Frage. Mein RelativeLayout befindet sich zwischen zwei Schaltflächen innerhalb eines linearen Layouts, auch zwischen den Schaltflächen. Wenn ich dies ausführe, nimmt es den gesamten Bildschirm ein. Irgendwelche Tipps, wie Sie diese Ladeleiste zwischen den beiden Schaltflächen halten können?
Alioo

Wo soll ich den Code findViewById(R.id.loadingPanel).setVisiblity(View.GONE)in die zweite Aktivität einfügen ? Es kann das nicht finden, viewda es setContnetView()in der 2. Fragmentaktivität keine Methode gibt . Vielen Dank!
Alston

10

Dies wird allgemein als unbestimmter Fortschrittsbalken oder unbestimmter Fortschrittsdialog bezeichnet.

Kombinieren Sie dies mit einem Thread und einem Handler , um genau das zu erhalten, was Sie wollen. Es gibt eine Reihe von Beispielen, wie dies über Google oder hier auf SO gemacht werden kann. Ich würde wärmstens empfehlen, sich die Zeit zu nehmen, um zu lernen, wie man diese Kombination von Klassen verwendet, um eine solche Aufgabe auszuführen. Es ist unglaublich nützlich für viele Arten von Anwendungen und gibt Ihnen einen großartigen Einblick in die Zusammenarbeit von Threads und Handlern.

Ich werde Ihnen zeigen, wie das funktioniert:

Das Ladeereignis startet den Dialog:

//maybe in onCreate
showDialog(MY_LOADING_DIALOG);
fooThread = new FooThread(handler);
fooThread.start();

Jetzt macht der Thread die Arbeit:

private class FooThread extends Thread {
    Handler mHandler;

    FooThread(Handler h) {
        mHandler = h;
    }

    public void run() { 
        //Do all my work here....you might need a loop for this

        Message msg = mHandler.obtainMessage();
        Bundle b = new Bundle();                
        b.putInt("state", 1);   
        msg.setData(b);
        mHandler.sendMessage(msg);
    }
}

Holen Sie sich schließlich den Status aus dem Thread zurück, wenn er abgeschlossen ist:

final Handler handler = new Handler() {
    public void handleMessage(Message msg) {
        int state = msg.getData().getInt("state");
        if (state == 1){
            dismissDialog(MY_LOADING_DIALOG);
            removeDialog(MY_LOADING_DIALOG);
        }
    }
};

2
Ihre Antwort scheint wirklich nett zu sein, aber ich möchte sie in mein Layout einfügen ... Die Antwort von Venkatesh scheint meiner Verwendung angemessener zu sein. Ich werde versuchen, Feedback zu senden. Vielen Dank für Ihre Zeit!
Waza_Be

Vielen Dank für diese, es ist eigentlich gut, eine Lösung für XML und programmatische Vorgehensweise zu haben.
Neon Warge

1

Wenn Sie keine andere Ansicht aufblasen möchten, um den Fortschritt anzuzeigen, gehen Sie wie folgt vor:

  1. Erstellen Sie ProgressBar im selben XML-Layout wie die Listenansicht.
  2. Mach es zentriert
  3. Gib ihm einen Ausweis
  4. Fügen Sie es Ihrer Listview-Instanzvariablen hinzu, indem Sie setEmptyView aufrufen

Android sorgt für die Sichtbarkeit des Fortschrittsbalkens.

Zum Beispiel in activity_main.xml:

    <?xml version="1.0" encoding="utf-8"?>
<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:orientation="vertical"
    tools:context="com.fcchyd.linkletandroid.MainActivity">

    <ListView
        android:id="@+id/list_view_xml"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:divider="@color/colorDivider"
        android:dividerHeight="1dp" />

   <ProgressBar
        android:id="@+id/loading_progress_xml"
        style="?android:attr/progress"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true" />

</RelativeLayout>

Und in MainActivity.java:

package com.fcchyd.linkletandroid;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import java.util.ArrayList;
import java.util.List;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

public class MainActivity extends AppCompatActivity {

final String debugLogHeader = "Linklet Debug Message";
Call<Links> call;
List<Link> arraylistLink;
ListView linksListV;

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

    linksListV = (ListView) findViewById(R.id.list_view_xml);
    linksListV.setEmptyView(findViewById(R.id.loading_progress_xml));
    arraylistLink = new ArrayList<>();

    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("https://api.links.linklet.ml")
            .addConverterFactory(GsonConverterFactory
                    .create())
            .build();

    HttpsInterface HttpsInterface = retrofit
            .create(HttpsInterface.class);

    call = HttpsInterface.httpGETpageNumber(1);

    call.enqueue(new Callback<Links>() {
        @Override
        public void onResponse(Call<Links> call, Response<Links> response) {
            try {
                arraylistLink = response.body().getLinks();

                String[] simpletTitlesArray = new String[arraylistLink.size()];
                for (int i = 0; i < simpletTitlesArray.length; i++) {
                    simpletTitlesArray[i] = arraylistLink.get(i).getTitle();
                }
                ArrayAdapter<String> simpleAdapter = new ArrayAdapter<>(MainActivity.this, android.R.layout.simple_list_item_1, simpletTitlesArray);
                linksListV.setAdapter(simpleAdapter);
            } catch (Exception e) {
                Log.e("erro", "" + e);
            }
        }

        @Override
        public void onFailure(Call<Links> call, Throwable t) {

        }
    });


}

}}


ProgressBar muss sich an zweiter Stelle im RelativeLayout befinden, sonst wird es hinter der Ansicht an zweiter Stelle gerendert (eine ImageView in meiner und die ListView in Ihrem Fall)
Dominikus K.

1

Sie können diesen Code aus Firebase-Github-Beispielen verwenden .

Sie müssen keine Layoutdateien bearbeiten. Erstellen Sie einfach eine neue Klasse "BaseActivity".

package com.example;

import android.app.ProgressDialog;
import android.support.annotation.VisibleForTesting;
import android.support.v7.app.AppCompatActivity;


public class BaseActivity extends AppCompatActivity {

    @VisibleForTesting
    public ProgressDialog mProgressDialog;

    public void showProgressDialog() {
        if (mProgressDialog == null) {
            mProgressDialog = new ProgressDialog(this);
            mProgressDialog.setMessage("Loading ...");
            mProgressDialog.setIndeterminate(true);
        }

        mProgressDialog.show();
    }


    public void hideProgressDialog() {
        if (mProgressDialog != null && mProgressDialog.isShowing()) {
            mProgressDialog.dismiss();
        }
    }

    @Override
    public void onStop() {
        super.onStop();
        hideProgressDialog();
    }

}

In Ihrer Aktivität möchten Sie den Fortschrittsdialog verwenden.

public class MyActivity extends BaseActivity

Vor / nach der Funktion, die Zeit braucht

showProgressDialog();
.... my code that take some time
showProgressDialog();

0

Für diejenigen, die sich in Kotlin entwickeln, gibt es eine süße Methode, die von der Anko- Bibliothek bereitgestellt wird und die das Anzeigen ProgressDialogzum Kinderspiel macht!

Basierend auf diesem Link:

val dialog = progressDialog(message = "Please wait a bit…", title = "Fetching data")
dialog.show()
//....
dialog.dismiss()

Daraufhin wird ein Fortschrittsdialog mit dem angezeigten Fortschritt% angezeigt (für den Sie den initParameter auch übergeben müssen, um den Fortschritt zu berechnen).

Es gibt auch die indeterminateProgressDialog()Methode, die die Spinning Circle-Animation auf unbestimmte Zeit bereitstellt, bis sie entlassen wird:

indeterminateProgressDialog("Loading...").show()

Rufen Sie diesen Blog an, der mich zu dieser Lösung geführt hat.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.