Використання "анімованого кола" у ImageView під час завантаження матеріалів


219

Наразі я використовую у своїй програмі перегляд списку, який потребує відображення, можливо, одну секунду.

Наразі я використовую @ id / android: порожнє властивість listview, щоб створити текст "завантаження".

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

Тепер я хотів би замінити це на анімоване коло, яке використовується в діалоговому вікні завантаження замість цього тексту, я думаю, ви всі знаєте, що я маю на увазі:

Редагувати: я не хочу діалогового вікна. Я хочу показати це всередині моєї верстки.

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

Дякую за допомогу!

Відповіді:


443

Просто помістіть цей блок xml у файл макета вашої діяльності:

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

І коли ви закінчите завантажувати, зателефонуйте в цей рядок:

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

Результат (і він також крутиться):

введіть тут опис зображення


17
розтрощив кнопку +1
TSR

Не вдається побачити, як це вирішує проблему відображення анімованого кола в ImageView.
Густаво

4
@ Густаво, це те, що він хоче, щоб показати "невизначену анімацію прогресу", тому я думаю, що це вирішує проблему. ; -]
Таліс Вілела

143

Це можна зробити за допомогою наступного xml

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

З цим стилем

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

Щоб скористатися цією функцією, потрібно приховати елементи інтерфейсу користувача, встановивши значення видимості GONE, і кожного разу, коли дані завантажуються, зателефонуйте setVisibility(View.VISIBLE)до всіх своїх поглядів, щоб відновити їх. Не забудьте зателефонувати, findViewById(R.id.loadingPanel).setVisiblity(View.GONE)щоб приховати анімацію завантаження.

Якщо у вас немає події / функції завантаження, але ви просто хочете, щоб панель завантаження зникала через х секунд, використовуйте ручку, щоб запустити приховування / показ.


4
Чудова відповідь. Знайдено за допомогою пошуку в Google і вирішило і мою проблему. Дякую!
Дейв

Використовуючи цей метод, я отримую NullPointerException на findViewById(...).setVisibility(View.GONE)лінії, коли повертаю екран. Працює як шарм в одній орієнтації, але будь-яка ідея, чому це може зламатись?
Калина

У мене є питання. Мій відносний макет розташований між двома кнопками всередині лінійного макета, також між кнопками. Коли я запускаю це, він займає весь екран. Якісь поради щодо збереження цієї панелі завантаження між двома кнопками?
Аліо

Ну де я повинен поставити код findViewById(R.id.loadingPanel).setVisiblity(View.GONE)у другій діяльності? Він не може знайти, viewоскільки setContnetView()в діяльності 2-го фрагмента немає методу. Дякую!
Альстон

10

Зазвичай це називається невизначеною смугою прогресу або невизначеним діалогом прогресу.

Поєднайте це з ниткою та обробкою щоб отримати саме те, що ви хочете. Існує ряд прикладів того, як це зробити через Google або прямо тут, так Я б дуже рекомендував витратити час, щоб навчитися використовувати цю комбінацію класів для виконання такого завдання. Це неймовірно корисно для багатьох типів застосунків і дасть вам прекрасне розуміння того, як нитки та обробники можуть працювати разом.

Я розпочну з вас, як це працює:

Подія завантаження починає діалогове вікно:

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

Тепер нитка виконує роботу:

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

Нарешті поверніть стан з потоку, коли воно закінчиться:

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
Ваша відповідь здається дуже приємною, але я хотів би вставити це всередину моєї верстки ... Відповідь Венкатеша здається більш придатною для мого використання. Я спробую надіслати відгук. Дякую за ваш час!
Waza_Be

Дякую за це, насправді добре мати рішення як для XML, так і для програмного способу ведення справ.
Неонова війна

1

Якщо ви хочете не надувати інший вигляд просто для позначення прогресу, виконайте наступне:

  1. Створіть ProgressBar у тому самому макеті XML у списку списку.
  2. Зробіть це по центру
  3. Дайте ідентифікатор
  4. Приєднайте його до змінної екземпляра listview, викликаючи setEmptyView

Android подбає про видимість панелі прогресу.

Наприклад, у 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>

І в 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) {

        }
    });


}

}


ПрогресBar повинен бути на другому місці в межах RelativeLayout, інакше він відображається позаду Погляду на другому місці (ImageView у моєму та ListView у вашому випадку)
Домінікус К.

1

Ви можете використовувати цей код із зразків github Firebase .

Вам не потрібно редагувати файли макета ... просто створіть новий клас "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();
    }

}

У своїй діяльності ви бажаєте використовувати діалогове вікно виконання ..

public class MyActivity extends BaseActivity

До / Після функції, яка потребує часу

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

0

Для тих, хто розвивається в Котліні, існує солодкий метод, який надає бібліотека Анко, який робить процес ProgressDialogвітру вітерцем!

На основі цього посилання:

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

Це покаже діалог прогресу з відображеним% прогресу (для якого вам потрібно передати initпараметр також для обчислення прогресу).

Існує також indeterminateProgressDialog()метод, який забезпечує анімацію Spinning Circle на невизначений термін до звільнення:

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

Крикніть на цей блог, який привів мене до цього рішення.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.