การใช้“ วงกลมเคลื่อนไหว” ใน ImageView ขณะโหลดเนื้อหา


219

ขณะนี้ฉันกำลังใช้ listview ของมุมมองที่ต้องการให้แสดงหนึ่งวินาที

สิ่งที่ฉันทำในปัจจุบันคือการใช้ @ 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
Gustavo

4
@Gustavo นี่คือสิ่งที่เขาต้องการที่จะแสดง "ภาพเคลื่อนไหวความคืบหน้าไม่แน่นอน" ดังนั้นฉันคิดว่ามันแก้ปัญหาได้ ; -]
Thalis Vilela

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>

ในการใช้สิ่งนี้คุณต้องซ่อนองค์ประกอบ UI ของคุณโดยตั้งค่าการเปิดเผยเป็น GONE และเมื่อใดก็ตามที่ข้อมูลถูกโหลดให้เรียกsetVisibility(View.VISIBLE)ใช้มุมมองทั้งหมดของคุณเพื่อเรียกคืน อย่าลืมโทรfindViewById(R.id.loadingPanel).setVisiblity(View.GONE)เพื่อซ่อนภาพเคลื่อนไหวที่กำลังโหลด

หากคุณไม่ได้มีการโหลดเหตุการณ์ / ฟังก์ชั่น แต่เพียงต้องการแผงโหลดจะหายไปหลังจาก x วินาทีใช้มือจับที่จะเรียกการซ่อน / แสดง


4
คำตอบที่ดี พบผ่านการค้นหาของ Google และแก้ไขปัญหาของฉันเช่นกัน ขอบคุณ!
เดฟ

ใช้วิธีนี้ฉันได้รับ NullPointerException ในfindViewById(...).setVisibility(View.GONE)บรรทัดเมื่อฉันหมุนหน้าจอ ทำงานเหมือนมีมนต์เสน่ห์ในทิศทางเดียว แต่ความคิดใด ๆ ที่ทำให้สิ่งนี้แตก
Kalina

ฉันมีคำถาม. My RelativeLayout อยู่ระหว่างสองปุ่มภายใน Linear Layout และระหว่างปุ่ม เมื่อฉันรันสิ่งนี้มันจะเต็มหน้าจอ มีเคล็ดลับใด ๆ ในการคงแถบโหลดนี้ไว้ระหว่างปุ่มทั้งสอง
Alioo

ฉันควรใส่รหัสfindViewById(R.id.loadingPanel).setVisiblity(View.GONE)ในกิจกรรมที่สองที่ไหน ไม่พบviewเนื่องจากไม่มีsetContnetView()วิธีในกิจกรรมส่วนที่ 2 ขอบคุณ!
Alston

10

โดยทั่วไปจะเรียกว่าแถบความคืบหน้าไม่ จำกัด หรือกล่องโต้ตอบความคืบหน้าไม่แน่นอน

รวมสิ่งนี้กับThreadและHandlerเพื่อให้ได้สิ่งที่คุณต้องการ มีตัวอย่างจำนวนมากเกี่ยวกับวิธีการทำเช่นนี้ผ่านทาง Google หรือที่นี่ใน SO ฉันขอแนะนำให้ใช้เวลาในการเรียนรู้วิธีการใช้ชุดค่าผสมของชั้นเรียนนี้เพื่อทำงานแบบนี้ มันมีประโยชน์อย่างเหลือเชื่อในแอพพลิเคชั่นหลายประเภทและจะให้ข้อมูลเชิงลึกที่ยอดเยี่ยมเกี่ยวกับวิธีที่เธรดและตัวจัดการสามารถทำงานร่วมกันได้

ฉันจะให้คุณเริ่มต้นกับวิธีการทำงาน:

เหตุการณ์การโหลดเริ่มต้นกล่องโต้ตอบ:

//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
คำตอบของคุณดูเหมือนจะดีจริงๆ แต่ฉันต้องการที่จะแทรกเข้าไปในรูปแบบของฉัน ... คำตอบของ Venkatesh ดูเหมือนจะเหมาะสมกับการใช้งานของฉันฉันจะลองและส่งข้อเสนอแนะ ขอบคุณมากสำหรับเวลาของคุณ!
Waza_Be

ขอบคุณสำหรับสิ่งนี้จริง ๆ แล้วมันดีที่มีวิธีแก้ปัญหาสำหรับทั้ง XML และวิธีการเขียนโปรแกรม
Neon Warge

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

        }
    });


}

}


ProgressBar จะต้องอยู่ในจุดที่สองภายใน RelativeLayout มิฉะนั้นจะแสดงผลหลังมุมมองในจุดที่สอง (ImageView ในของฉันและ ListView ในกรณีของคุณ)
Dominikus K.

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

สำหรับคนที่พัฒนาใน Kotlin มีวิธีการอันแสนหวานที่จัดทำโดยห้องสมุดAnkoที่ทำให้กระบวนการแสดงผลProgressDialogเป็นเรื่องง่าย!

ตามลิงค์นั้น:

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

สิ่งนี้จะแสดงกล่องโต้ตอบความคืบหน้าโดยมี% ความคืบหน้าปรากฏขึ้น (ซึ่งคุณต้องผ่านinitพารามิเตอร์ด้วยเพื่อคำนวณความคืบหน้า)

นอกจากนี้ยังมีindeterminateProgressDialog()วิธีการซึ่งให้ภาพเคลื่อนไหวการหมุนวนไปเรื่อย ๆ จนกว่าจะถูกไล่ออก:

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

ส่งเสียงไปที่บล็อกซึ่งนำฉันไปสู่โซลูชันนี้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.