Sử dụng vòng tròn hoạt hình trên mạng Cameron trong ImageView trong khi tải nội dung


219

Tôi hiện đang sử dụng trong ứng dụng của mình một listview cần có thể hiển thị một giây.

Những gì tôi hiện đang làm là sử dụng tài sản @ id / android: trống của listview để tạo văn bản "đang tải".

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

Bây giờ, tôi muốn thay thế nó bằng vòng tròn hoạt hình được sử dụng trong hộp thoại tải thay vì văn bản này, tôi đoán tất cả các bạn đều hiểu ý tôi là gì:

Chỉnh sửa: Tôi không muốn một hộp thoại. Tôi muốn thể hiện điều đó trong bố cục của tôi.

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

Cảm ơn rất nhiều vì sự giúp đỡ của bạn!

Câu trả lời:


443

Chỉ cần đặt khối xml này vào tệp bố cục hoạt động của bạn:

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

Và khi bạn tải xong, hãy gọi một dòng này:

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

Kết quả (và nó cũng quay):

nhập mô tả hình ảnh ở đây


17
đập vỡ nút +1
TSR

Không thể thấy cách này giải quyết vấn đề hiển thị vòng tròn hoạt hình trong ImageView.
Gustavo

4
@Gustavo, đây là những gì anh ấy muốn, để hiển thị một "hoạt hình tiến bộ không xác định", vì vậy tôi nghĩ rằng nó giải quyết vấn đề. ; -]
Thalis Vilela

143

Bạn có thể làm điều này bằng cách sử dụng xml sau

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

Với phong cách này

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

Để sử dụng điều này, bạn phải ẩn các thành phần UI của mình bằng cách đặt giá trị hiển thị thành Gone và bất cứ khi nào dữ liệu được tải, hãy gọi setVisibility(View.VISIBLE)tất cả các chế độ xem của bạn để khôi phục chúng. Đừng quên gọi findViewById(R.id.loadingPanel).setVisiblity(View.GONE)để ẩn hình ảnh động đang tải.

Nếu bạn không có sự kiện / chức năng tải mà chỉ muốn bảng điều khiển tải biến mất sau x giây, hãy sử dụng Tay cầm để kích hoạt ẩn / hiển thị.


4
Câu trả lời chính xác. Tìm thấy thông qua tìm kiếm của Google và cũng đã giải quyết vấn đề của tôi. Cảm ơn!
Dave

Sử dụng phương pháp này, tôi nhận được một NullPulumException trên findViewById(...).setVisibility(View.GONE)dòng khi tôi xoay màn hình. Hoạt động như một nét duyên dáng trong một định hướng, nhưng có ý tưởng nào tại sao điều này có thể bị phá vỡ?
Kalina

Tôi có một câu hỏi. RelativeLayout của tôi nằm giữa hai nút bên trong Bố cục tuyến tính giữa các nút. Khi tôi chạy nó sẽ chiếm toàn bộ màn hình. Bất kỳ lời khuyên về việc giữ thanh tải này giữa hai nút?
Alioo

Chà, tôi nên đặt mã findViewById(R.id.loadingPanel).setVisiblity(View.GONE)ở đâu trong hoạt động thứ hai? Nó không thể tìm thấy viewvì không cósetContnetView() phương pháp trong hoạt động phân đoạn thứ hai. Cảm ơn!
Alston

10

Điều này thường được gọi là Thanh tiến trình không xác định hoặc Hộp thoại tiến trình không xác định.

Kết hợp điều này với một chủ đề và một Handler để có được chính xác những gì bạn muốn. Có một số ví dụ về cách thực hiện việc này thông qua Google hoặc ngay tại đây trên SO. Tôi đặc biệt khuyên bạn nên dành thời gian để tìm hiểu cách sử dụng kết hợp các lớp này để thực hiện một nhiệm vụ như thế này. Nó cực kỳ hữu ích trên nhiều loại ứng dụng và sẽ cung cấp cho bạn cái nhìn sâu sắc về cách Chủ đề và Trình xử lý có thể làm việc cùng nhau.

Tôi sẽ giúp bạn bắt đầu về cách thức hoạt động của nó:

Sự kiện tải bắt đầu hộp thoại:

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

Bây giờ các chủ đề thực hiện công việc:

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

Cuối cùng lấy lại trạng thái từ luồng khi hoàn thành:

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
Câu trả lời của bạn có vẻ rất hay, nhưng tôi muốn chèn nó vào trong bố cục của mình ... Câu trả lời của Venkatesh có vẻ phù hợp hơn với cách sử dụng của tôi. Tôi sẽ thử và gửi phản hồi. Cảm ơn rất nhiều vì thời gian của bạn!
Waza_Be

Cảm ơn vì điều này, thực sự tốt khi có giải pháp cho cả XML và cách làm việc theo chương trình.
Chiến tranh neon

1

Nếu bạn không muốn thổi phồng một góc nhìn khác chỉ để chỉ ra sự tiến bộ thì hãy làm như sau:

  1. Tạo ProgressBar trong cùng bố cục XML của chế độ xem danh sách.
  2. Làm cho nó tập trung
  3. Cho nó một id
  4. Đính kèm nó vào biến đối tượng listview của bạn bằng cách gọi setEmptyView

Android sẽ chăm sóc khả năng hiển thị của thanh tiến trình.

Ví dụ activity_main.xml: trong :

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

Và trong 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 phải ở vị trí thứ hai trong RelativeLayout, nếu không, nó sẽ được hiển thị sau View ở vị trí thứ hai (một ImageView trong tôi và ListView trong trường hợp của bạn)
Dominikus K.

1

Bạn có thể sử dụng mã này từ các mẫu github firebase ..

Bạn không cần chỉnh sửa trong các tệp bố cục ... chỉ cần tạo một lớp mới "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();
    }

}

Trong Hoạt động của bạn mà bạn muốn sử dụng hộp thoại tiến trình ..

public class MyActivity extends BaseActivity

Trước / Sau chức năng mất thời gian

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

0

Đối với những người đang phát triển ở Kotlin, có một phương pháp ngọt ngào được cung cấp bởi thư viện Anko giúp cho quá trình hiển thị trở ProgressDialognên dễ dàng!

Dựa trên liên kết đó:

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

Điều này sẽ hiển thị Hộp thoại Tiến trình với% tiến trình được hiển thị (bạn cũng phải truyền inittham số để tính tiến trình).

Ngoài ra còn có indeterminateProgressDialog()phương thức cung cấp hoạt hình Vòng tròn quay vô thời hạn cho đến khi bị loại bỏ:

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

Hét lên blog này dẫn tôi đến giải pháp này.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.