Menggunakan "lingkaran animasi" di ImageView saat memuat barang

219

Saat ini saya menggunakan listview dalam aplikasi saya yang mungkin perlu satu detik untuk ditampilkan.

Apa yang saya lakukan saat ini adalah menggunakan properti @ id / android: kosong dari tampilan daftar untuk membuat teks "memuat".

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

Sekarang, saya ingin menggantinya dengan lingkaran animasi yang digunakan dalam dialog pemuatan alih-alih teks ini, saya kira Anda semua tahu apa yang saya maksud:

Sunting: Saya tidak ingin dialog. Saya ingin menunjukkan itu di dalam tata letak saya.

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

Terima kasih banyak atas bantuan Anda!

Waza_Be
sumber

Jawaban:

443

Sederhananya blok xml ini di file tata letak aktivitas Anda:

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

Dan ketika Anda selesai memuat, panggil satu baris ini:

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

Hasilnya (dan itu berputar juga):

masukkan deskripsi gambar di sini

pengguna1032613
sumber
17
menghancurkan tombol +1
TSR
Tidak dapat melihat bagaimana ini menyelesaikan masalah menampilkan lingkaran animasi di ImageView.
Gustavo
4
@ Gustavo, inilah yang dia inginkan, untuk menunjukkan "progres animasi tak tentu", jadi saya pikir ini menyelesaikan masalah. ; -]
Thalis Vilela
143

Anda dapat melakukan ini dengan menggunakan xml berikut

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

Dengan gaya ini

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

Untuk menggunakan ini, Anda harus menyembunyikan elemen UI Anda dengan menetapkan nilai visibilitas ke GONE dan kapan pun data dimuat, panggil setVisibility(View.VISIBLE)semua tampilan Anda untuk memulihkannya. Jangan lupa meneleponfindViewById(R.id.loadingPanel).setVisiblity(View.GONE) untuk menyembunyikan animasi pemuatan.

Jika Anda tidak memiliki acara / fungsi pemuatan tetapi hanya ingin panel memuat menghilang setelah x detik gunakan Handle untuk memicu persembunyian / tampilan.

Kurru
sumber
4
Jawaban yang bagus Ditemukan melalui pencarian Google, dan menyelesaikan masalah saya juga. Terima kasih!
Dave
Dengan menggunakan metode ini, saya mendapatkan NullPointerException di findViewById(...).setVisibility(View.GONE)telepon ketika saya memutar layar. Berfungsi seperti pesona dalam satu orientasi, tetapi apakah Anda tahu mengapa ini mungkin melanggar?
Kalina
Saya punya pertanyaan. RelativeLayout saya adalah antara dua tombol di dalam Layout Linear juga di antara tombol-tombol. Ketika saya menjalankan ini, dibutuhkan seluruh layar. Adakah tips untuk menjaga bilah pemuatan ini di antara dua tombol?
Alioo
Nah, di mana saya harus meletakkan kode findViewById(R.id.loadingPanel).setVisiblity(View.GONE)di aktivitas kedua? Tidak dapat menemukan viewkarena tidak ada setContnetView()metode dalam aktivitas fragmen ke-2. Terima kasih!
Alston
10

Ini umumnya disebut sebagai Progress Bar tak tentu atau Dialog Kemajuan tak tentu.

Gabungkan ini dengan Thread dan Handler untuk mendapatkan apa yang Anda inginkan. Ada sejumlah contoh tentang cara melakukan ini melalui Google atau di sini di SO. Saya akan sangat menyarankan meluangkan waktu untuk belajar bagaimana menggunakan kombinasi kelas ini untuk melakukan tugas seperti ini. Ini sangat berguna di berbagai jenis aplikasi dan akan memberi Anda wawasan tentang bagaimana Thread dan Penangan dapat bekerja bersama.

Saya akan membantu Anda memulai cara kerjanya:

Acara pemuatan memulai dialog:

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

Sekarang utasnya berfungsi:

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

Akhirnya kembalikan status dari utas setelah selesai:

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);
        }
    }
};
pengguna432209
sumber
2
Jawaban Anda sepertinya sangat bagus, tetapi saya ingin memasukkannya ke dalam tata letak saya ... Jawaban Venkatesh tampaknya lebih sesuai untuk saya gunakan. Saya akan mencoba dan mengirim umpan balik. Terima kasih banyak atas waktu Anda!
Waza_Be
Terima kasih untuk yang ini, sebenarnya baik untuk memiliki solusi untuk XML dan cara pemrograman dalam melakukan sesuatu.
Neon Warge
1

Jika Anda tidak ingin mengembang tampilan lain hanya untuk menunjukkan kemajuan maka lakukan hal berikut:

  1. Buat ProgressBar di tata letak XML yang sama dari tampilan daftar.
  2. Jadikan itu terpusat
  3. Berikan id
  4. Lampirkan ke variabel instance listview Anda dengan memanggil setEmptyView

Android akan menjaga visibilitas bilah kemajuan.

Misalnya, di 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>

Dan di 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) {

        }
    });


}

}

Md_Zubair Ahmed
sumber
ProgressBar harus berada di tempat kedua dalam RelativeLayout, jika tidak maka akan ditampilkan di belakang Tampilan di tempat kedua (sebuah ImageView dalam saya dan ListView dalam kasus Anda)
Dominikus K.
1

Anda dapat menggunakan kode ini dari sampel firebase github ..

Anda tidak perlu mengedit dalam file tata letak ... cukup buat kelas baru "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();
    }

}

Dalam Aktivitas Anda bahwa Anda ingin menggunakan dialog kemajuan ..

public class MyActivity extends BaseActivity

Sebelum / Setelah fungsi yang membutuhkan waktu

showProgressDialog();
.... my code that take some time
showProgressDialog();
khateeb
sumber
0

Untuk yang berkembang di Kotlin, ada metode manis yang disediakan oleh perpustakaan Anko yang membuat proses menampilkan ProgressDialogmenjadi mudah!

Berdasarkan tautan itu:

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

Ini akan menampilkan Dialog Kemajuan dengan% kemajuan ditampilkan (yang Anda harus melewati initparameter juga untuk menghitung kemajuan).

Ada juga indeterminateProgressDialog()metode, yang menyediakan animasi Spinning Circle tanpa batas waktu sampai diberhentikan:

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

Berteriaklah ke blog ini yang mengarahkan saya ke solusi ini.

DarkCygnus
sumber