在加载内容时,在ImageView中使用“动画圆圈”

236

我目前在我的应用程序中使用了一个列表视图,需要大约一秒钟才能显示出来。

我目前所做的是使用listview的@id/android:empty属性创建一个“加载中”文本。

 <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

非常感谢您的帮助!

6个回答

508

只需将此 XML 代码块放入您的 Activity 布局文件中:

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

结果(还可以旋转):

输入图像描述


23
按下了+1按钮 - TSR
1
看不出来这如何解决在 ImageView 中显示动画圆的问题。 - Gustavo
5
@Gustavo,他想展示一个“不确定进度动画”,所以我认为这解决了问题。 ;-] - Thalis Vilela

146

您可以使用以下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秒后使加载面板消失,请使用Handle来触发隐藏/显示。

4
好的回答。通过谷歌搜索找到,也解决了我的问题。谢谢! - Dave
使用这种方法,当我旋转屏幕时,在findViewById(...).setVisibility(View.GONE)行上会出现NullPointerException。在一个方向上运作得很好,但是你有什么想法为什么会出问题? - Kalina
我有一个问题。我的RelativeLayout在Linear Layout的两个按钮之间,也在这两个按钮之间。当我运行它时,它会占据整个屏幕。有没有什么提示可以让这个加载条保持在两个按钮之间? - Alioo
那么,我应该把代码 findViewById(R.id.loadingPanel).setVisiblity(View.GONE) 放在第二个活动的哪里呢?由于第二个片段活动中没有 setContnetView() 方法,因此它无法找到视图。谢谢! - Alston

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
你的回答看起来非常好,但我想把它插入到我的布局中... Venkatesh 的答案似乎更适合我的使用。我会尝试并发送反馈。非常感谢你的时间! - Waza_Be
谢谢这个,实际上拥有XML和编程两种方式的解决方案是很好的。 - Neon Warge

4
您可以使用来自 Firebase GitHub 示例的此代码..BaseActivity 无需在布局文件中进行编辑... 只需创建一个新类 "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();
    }

}

在你想要使用进度对话框的Activity中..
public class MyActivity extends BaseActivity

在处理时间的函数之前/之后

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

1
对于使用 Kotlin 开发的人员,Anko 库提供了一个 方便简易的方法 来显示 ProgressDialog!根据该链接:
val dialog = progressDialog(message = "Please wait a bit…", title = "Fetching data")
dialog.show()
//....
dialog.dismiss()

这将显示一个进度对话框,其中显示进度的百分比(您还需要传递init参数来计算进度)。

还有indeterminateProgressDialog()方法,该方法提供旋转圆圈动画,直到被关闭:

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

致敬这个博客,它引导我找到了这个解决方案。

这可能是一个好的答案,但现在该软件包已不再维护:https://github.com/Kotlin/anko/blob/master/GOODBYE.md - rwst

1

如果您不想再创建其他视图来指示进度,则可以按照以下步骤操作:

  1. 在与列表视图相同的XML布局中创建ProgressBar。
  2. 使其居中显示。
  3. 为其分配一个ID。
  4. 通过调用setEmptyView将其附加到您的listview实例变量上。

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

        }
    });


}

}


进度条必须在RelativeLayout的第二个位置,否则它会被渲染在第二个位置上的视图(在我的情况下是ImageView,在你的情况下是ListView)的后面。 - Dominikus K.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接