不推荐使用ProgressDialog。可以使用什么替代方法?


Answers:


196

是的,API level 26已弃用。相反,您可以使用progressBar

以编程方式创建它:

首先获取根布局的参考

RelativeLayout layout = findViewById(R.id.display);  //specify here Root layout Id

要么

RelativeLayout layout = findViewById(this);

然后添加进度条

progressBar = new ProgressBar(youractivity.this, null, android.R.attr.progressBarStyleLarge);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(100, 100);
params.addRule(RelativeLayout.CENTER_IN_PARENT);
layout.addView(progressBar, params);

显示进度条

progressBar.setVisibility(View.VISIBLE);

隐藏进度条

progressBar.setVisibility(View.GONE);

要禁用用户交互,您只需要添加以下代码

getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
                           WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);

要恢复用户交互,您只需添加以下代码

getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);

仅供以后参考,请将更改android.R.attr.progressBarStyleSmallandroid.R.attr.progressBarStyleHorizontal

以下代码仅适用于 API level 21

progressBar.setProgressTintList(ColorStateList.valueOf(Color.RED));

要通过xml创建它:

<ProgressBar
        android:id="@+id/progressbar"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:indeterminate="true"
        android:max="100"
        android:backgroundTint="@color/white"
        android:layout_below="@+id/framelauout"
        android:indeterminateTint="#1a09d6"
        android:layout_marginTop="-7dp"/>

在您的活动中

progressBar = (ProgressBar) findViewById(R.id.progressbar);

显示/隐藏进度条是一样的

 progressBar.setVisibility(View.VISIBLE); // To show the ProgressBar 
 progressBar.setVisibility(View.INVISIBLE); // To hide the ProgressBar

这是看起来像的示例图像:

有关更多详细信息:
1.参考一
2.参考二


就像您一直在使用此工具一样,您就像是终于弃用了进度对话框,所以我可以向全世界展示我的潜力:D,开个玩笑,非常感谢您的详细回答。
穆罕默德·哈伊尔

1
但是如何设置setMessage()呢?
reverie_ss


请将xml代码更新为“ @android:color / white”
musterjunk

要获取水平条,请使用: ProgressBar progressBar = new ProgressBar(youractivity.this,null,android.R.attr.progressBarStyleHorizo​​ntal); progressBar.setIndeterminate(true);
taranjeetsapra

43

您可以将AlertDialog用作ProgressDialog以下参考代码ProgressDialog。每当显示进度对话框时,都需要调用此函数。

码:

    public void setProgressDialog() {

    int llPadding = 30;
    LinearLayout ll = new LinearLayout(this);
    ll.setOrientation(LinearLayout.HORIZONTAL);
    ll.setPadding(llPadding, llPadding, llPadding, llPadding);
    ll.setGravity(Gravity.CENTER);
    LinearLayout.LayoutParams llParam = new LinearLayout.LayoutParams(
            LinearLayout.LayoutParams.WRAP_CONTENT,
            LinearLayout.LayoutParams.WRAP_CONTENT);
    llParam.gravity = Gravity.CENTER;
    ll.setLayoutParams(llParam);

    ProgressBar progressBar = new ProgressBar(this);
    progressBar.setIndeterminate(true);
    progressBar.setPadding(0, 0, llPadding, 0);
    progressBar.setLayoutParams(llParam);

    llParam = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
            ViewGroup.LayoutParams.WRAP_CONTENT);
    llParam.gravity = Gravity.CENTER;
    TextView tvText = new TextView(this);
    tvText.setText("Loading ...");
    tvText.setTextColor(Color.parseColor("#000000"));
    tvText.setTextSize(20);
    tvText.setLayoutParams(llParam);

    ll.addView(progressBar);
    ll.addView(tvText);

    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setCancelable(true);
    builder.setView(ll);

    AlertDialog dialog = builder.create();
    dialog.show();
    Window window = dialog.getWindow();
    if (window != null) {
        WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
        layoutParams.copyFrom(dialog.getWindow().getAttributes());
        layoutParams.width = LinearLayout.LayoutParams.WRAP_CONTENT;
        layoutParams.height = LinearLayout.LayoutParams.WRAP_CONTENT;
        dialog.getWindow().setAttributes(layoutParams);
    }
}

输出:

在此处输入图片说明


如何解散呢?
Jay Dangar '18

1
创建一段类似于BaseActivity的基类,然后在添加了这段代码之后,还添加了一个方法关闭对话框,但是为此,您需要全局定义“ AlertDialog dialog”对象
Kishan Donga

然后只需在隐藏对话框方法中调用dialog.dismiss()方法即可。
Kishan Donga

1
一切都很好,但是在屏幕对话框上的任何地方点击都会被关闭。服务调用正在进行中,suer可以将其关闭并使用ui播放,这不是很好。
Vivek Kumar

您可以将其设置为不可取消,但是旋转设备或使用拆分屏幕将始终被关闭,并且用户可以与尚未准备就绪的UI进行交互。也许AlertDialog不应该在这里使用。
猫猫2012年

30

此类已在API级别26中弃用。ProgressDialog是一个模式对话框,可防止用户与应用程序进行交互。而不是使用此类,您应该使用进度指示器(例如ProgressBar),该指示器可以嵌入应用程序的UI中。或者,您可以使用通知来通知用户任务的进度。链接

Android O由于Google新的UI标准而已弃用


1
使用“ API级别26中不推荐使用该类”代替日期。他们不希望您再使用它。是的,这是因为有了新的UI标准,但是它们适用于每个API级别...
creativecreatoror

28
“由于Google新的UI标准,Android O弃用了它”-请链接新的UI标准
Ajay S

22
否决它的原因是因为它阻止了用户输入?有时候,我想知道Google工程师正在打哪种粉末。使用阻止对话框比必须隐藏/禁用输入控件然后启用进度条要容易得多。Google的愚蠢思想。
TheRealChx101 '18

@ TheRealChx101 Android UI的设计旨在使用户感到虚假的自由感,但要付出代价高昂的解决方法,以防止由此导致的致命错误。请等到您获得许可以及运营商已向Google支付的费用后,说您可以访问和不能访问。
被遗弃的购物车

3
我猜想他们对防止滥用模式对话框更感兴趣:有时候,它们在用户根本不需要等待但可以继续做其他事情的情况下,使用户等待操作结束,因此让他们不必要地等待会降低用户体验。尽管如此,在很多情况下,用户别无选择,只能等待操作完成,因此我同意在这种情况下应该使用不建议使用的标准方法,而不是强迫每个开发人员自行实现。
弗朗·马佐亚

25

您可以简单地为进度栏设计一个xml接口,并将其作为视图传递给AlertDialog,然后随时显示或关闭该对话框。

progress.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:padding="13dp"
    android:layout_centerHorizontal="true"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <ProgressBar
        android:id="@+id/loader"
        android:layout_marginEnd="5dp"
        android:layout_width="45dp"
        android:layout_height="45dp" />
    <TextView
        android:layout_width="wrap_content"
        android:text="Loading..."
        android:textAppearance="?android:textAppearanceSmall"
        android:layout_gravity="center_vertical"
        android:id="@+id/loading_msg"
        android:layout_toEndOf="@+id/loader"
        android:layout_height="wrap_content" />

</LinearLayout>

显示进度对话框的代码。只需复制此代码并将其粘贴到您的片段中即可。

  AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
       private void setDialog(boolean show){
            builder.setView(R.layout.progress);
            Dialog dialog = builder.create();
            if (show)dialog.show();
            else dialog.dismiss();
        }

然后,只要您想显示progressdialog并调用true作为参数来显示它,或者调用false来关闭对话框,就只要调用该方法即可。


2
@Alok Rajasukumaran似乎您正在使用活动,只需将其替换为this,使它看起来像这样AlertDialog.Builder builder = new AlertDialog.Builder(this);。请确保您复制的是正确的代码。
DevMike01

1
layout_toEndOf可以删除,因为不能删除LinearLayout
Mark

21

ProgressBar非常简单易用,我打算使它与简单进度对话框相同。第一步是您可以为要显示的对话框设置xml布局,可以说我们将此布局命名为

layout_loading_dialog.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:padding="20dp">
    <ProgressBar
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1" />

    <TextView
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="4"
        android:gravity="center"
        android:text="Please wait! This may take a moment." />
</LinearLayout>

下一步是创建AlertDialog,它将使用ProgressBar显示此布局

AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setCancelable(false); // if you want user to wait for some process to finish,
builder.setView(R.layout.layout_loading_dialog);
AlertDialog dialog = builder.create();

现在剩下的就是在这样的单击事件中显示和隐藏此对话框

dialog.show(); // to show this dialog
dialog.dismiss(); // to hide this dialog

就是这样,它应该可以工作,如您所见,实现ProgressBar而不是ProgressDialog非常简单容易。现在您可以在Handler或ASyncTask中显示/关闭此对话框,具体取决于您的需要


请更改progress_dialog.show();builder.show();。谢谢。
Matheus Miranda '18

2
我已经将名称更改为show()/ 上的正确AlertDialog对象dismiss(),但是我没有放,builder.show()因为要关闭它,我们必须这样做dialog.dismiss(),这对于喜欢保持其代码简单易懂的人来说是一种困惑。因为builder.show()返回 AlertDialog对象,所以我们必须像AlertDialog dialog = builder.show();do 那样保存该引用dialog.dismiss(),它更容易builder.create()在某个AlertDialog对象中返回,然后使用该对象显示和隐藏对话框
Syed Naeem

如果调用线程不是主UI线程,则可以使用“ runOnUiThread(new Runnable(){@Override public void run(){dialog.show/dismiss();}});”。(当我们用于从WebView调用时应该有用-shouldoverride方法。)
SHS

15

是的,不赞成使用ProgressDialog,但不建议使用Dialog。

您可以将自己的XML文件(包含进度条和加载文本)填充到对话框对象中,然后使用show()dismiss()函数将其显示或隐藏。这是一个示例(科特琳):

ProgressDialog类

class ProgressDialog {
companion object {
    fun progressDialog(context: Context): Dialog{
        val dialog = Dialog(context)
        val inflate = LayoutInflater.from(context).inflate(R.layout.progress_dialog, null)
        dialog.setContentView(inflate)
        dialog.setCancelable(false)
        dialog.window!!.setBackgroundDrawable(
                ColorDrawable(Color.TRANSPARENT))
        return dialog
    }
  }
}

XML格式

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:background="#fff"
android:padding="13dp"
android:layout_height="wrap_content">
<ProgressBar
    android:id="@+id/progressBar"
    style="?android:attr/progressBarStyle"
    android:layout_width="100dp"
    android:layout_margin="7dp"
    android:layout_height="100dp"
    android:layout_above="@+id/no_jobs_pickups"/>
<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerVertical="true"
    android:layout_margin="7dp"
    android:layout_toEndOf="@+id/progressBar"
    android:text="Loading..." />
</RelativeLayout>

在您的代码中var dialog = ProgressDialog.progressDialog(context)

显示: dialog.show()

隐藏: dialog.dismiss()


11

好吧,如果您真的想违背他们的意愿,仍然可以使用Sweet Alert Dialog或自己创建一个。

progress_dialog_layout

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TableRow
        android:layout_centerInParent="true"
        android:layout_width="match_parent"
        android:layout_height="64dp" >

        <ProgressBar
            android:id="@+id/progressBar2"
            style="?android:attr/progressBarStyle"
            android:layout_width="wrap_content"
            android:layout_height="match_parent" />

        <TextView
            android:gravity="center|left"
            android:id="@+id/textView9"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:textColor="@color/black"
            android:textSize="18sp"
            android:text="Downloading data. Please wait.." />
    </TableRow>
</RelativeLayout>

Java代码:

AlertDialog b;
AlertDialog.Builder dialogBuilder;

public void ShowProgressDialog() {
dialogBuilder = new AlertDialog.Builder(DataDownloadActivity.this);
LayoutInflater inflater = (LayoutInflater) getSystemService( Context.LAYOUT_INFLATER_SERVICE );
            View dialogView = inflater.inflate(R.layout.progress_dialog_layout, null);
            dialogBuilder.setView(dialogView);
            dialogBuilder.setCancelable(false);
            b = dialogBuilder.create();
            b.show();
        }

        public void HideProgressDialog(){

            b.dismiss();
        }

2
我曾在生产环境中使用SweetAlertDialog经历过糟糕的经历,请谨慎操作,因为它会在窗口之间泄漏。
杰里米(Jeremy)

对我来说HideProgress什么都不做。
Saeed Neamati

1
为什么只使用库来显示进度对话框?
Khemraj


6

您不需要导入任何自定义库。

我更喜欢使用现代字体,AlertDialog因此这是Kishan Donga在此页面上发布的出色答案的Kotlin版本。

Kotlin代码:

fun setProgressDialog(context:Context, message:String):AlertDialog {
    val llPadding = 30
    val ll = LinearLayout(context)
    ll.orientation = LinearLayout.HORIZONTAL
    ll.setPadding(llPadding, llPadding, llPadding, llPadding)
    ll.gravity = Gravity.CENTER
    var llParam = LinearLayout.LayoutParams(
                  LinearLayout.LayoutParams.WRAP_CONTENT,
                  LinearLayout.LayoutParams.WRAP_CONTENT)
    llParam.gravity = Gravity.CENTER
    ll.layoutParams = llParam

    val progressBar = ProgressBar(context)
    progressBar.isIndeterminate = true
    progressBar.setPadding(0, 0, llPadding, 0)
    progressBar.layoutParams = llParam

    llParam = LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
                        ViewGroup.LayoutParams.WRAP_CONTENT)
    llParam.gravity = Gravity.CENTER
    val tvText = TextView(context)
    tvText.text = message
    tvText.setTextColor(Color.parseColor("#000000"))
    tvText.textSize = 20.toFloat()
    tvText.layoutParams = llParam

    ll.addView(progressBar)
    ll.addView(tvText)

    val builder = AlertDialog.Builder(context)
    builder.setCancelable(true)
    builder.setView(ll)

    val dialog = builder.create()
    val window = dialog.window
    if (window != null) {
        val layoutParams = WindowManager.LayoutParams()
        layoutParams.copyFrom(dialog.window?.attributes)
        layoutParams.width = LinearLayout.LayoutParams.WRAP_CONTENT
        layoutParams.height = LinearLayout.LayoutParams.WRAP_CONTENT
                dialog.window?.attributes = layoutParams
    }
    return dialog
}

用法:

val dialog = setProgressDialog(this, "Loading..")
dialog.show()

输出:

在此处输入图片说明


如何在片段中使用?片段中的上下文是什么?
roghayeh hosseini

通常,在您的片段中可以获取当前视图,因此上下文应为:view!!.context
Alessandro Ornano,

4

文档页面中所述,替代方法 ProgressBarProgressDialog可以通过将ProgressBar放进来复制外观AlertDialog

您仍然可以使用它,但是Android不想使用它,这就是不建议使用的原因。因此,您应该考虑以其他方式解决问题,例如将a嵌入ProgressBar到您的中Layout


@PeterHaddad它在我的项目的api 28中“正常”工作,与较低的api相同。正如弃用所暗示的那样,它不再受支持并且将来可能无法使用。
DMonkey

3

ProgressDialog 已在API级别26中弃用。

"Deprecated" 指正在被更新的功能或元素替换的功能或元素。

ProgressDialog是一个模式对话框,可防止用户与应用程序进行交互。而不是使用此类,您应该使用进度指示器(如)ProgressBar,可以将其嵌入到应用的用户界面中。

优点

我个人会说这ProgressBar两个方面都有优势。ProgressBar是指示操作进度的用户界面元素。以不间断的方式向用户显示进度条。在应用程序的用户界面中显示进度栏。


2

我使用来自https://github.com/Q115/DelayedProgressDialog的 DelayedProgressDialog。它与ProgressDialog相同,并在必要时增加了延迟。

使用它类似于Android O之前的ProgressDialog:

DelayedProgressDialog progressDialog = new DelayedProgressDialog();
progressDialog.show(getSupportFragmentManager(), "tag");

2

你可以使用这个我写的。它仅提供基本功能。如果您需要功能全面的ProgressDialog,请使用此轻量级

摇篮设置

将以下依赖项添加到module / build.gradle:

compile 'com.lmntrx.android.library.livin.missme:missme:0.1.5'

如何使用它?

用法类似于原始的ProgressDialog

ProgressDialog progressDialog = new 
progressDialog(YourActivity.this);
progressDialog.setMessage("Please wait");
progressDialog.setCancelable(false);
progressDialog.show();
progressDialog.dismiss();

注意:您必须覆盖活动的onBackPressed()

Java8实现:

@Override
public void onBackPressed() {
    progressDialog.onBackPressed(
            () -> {
                super.onBackPressed();
                return null;
            }
    );
}

Kotlin实施:

override fun onBackPressed() {
   progressDialog.onBackPressed { super.onBackPressed() }
}


1

它可能对其他人有帮助。

许多流行的应用程序使用不同的方法来显示诸如网络请求,文件加载等之类的进度。“加载”微调器不会显示已加载或剩余要加载多少内容。从UI / UX的角度来看,存在一段不确定的时期,这很糟糕。许多流行的应用程序(Facebook,Linkedin等)已通过首先显示裸露的UI显示解决了此问题。然后,已加载的内容将逐渐显示在屏幕上。

我 为我的应用程序使用了微光来解决此问题。

有一篇很好的文章,这将对其他人有益


0

在进度对话框中,用户无法执行任何类型的工作。在进度对话框期间,所有后台进程均已停止。因此,建议使用用户进度条而不是进度对话框。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.