Android在ProgressDialog工作时更改drawable的方法

7

我有一个ProgressDialog,当Activity创建时(在OnCreate方法内部)启动。

private void initDialog() {
    mProgressDialog = new ProgressDialog(this);
    mProgressDialog.setIndeterminate(true);
    mProgressDialog.setTitle("Please wait.");
    mProgressDialog.setMessage("Connecting to LinkedIn.");
    mProgressDialog.setCancelable(false);
    mProgressDialog.show();
}

2500毫秒后,我想将圆形动画更改为我的自定义图像(如下所示),以模拟从服务器检索到数据并完成的情况。因此,我需要向用户显示进程已完成。为了达到这个目标,我选择了以下方法:

  1. 我显示对话框
  2. 当我检索到数据时,我更改ProgressDialog的可绘制对象

但是,我遇到了一个问题。当我第一次设置可绘制对象时

private void initDialog() {
    mProgressDialog = new ProgressDialog(this);
    mProgressDialog.setIndeterminate(true);
    mProgressDialog.setTitle("Please wait.");
    mProgressDialog.setMessage("Connecting to LinkedIn.");
    mProgressDialog.setCancelable(false);
    //This
    mProgressDialog.setIndeterminateDrawable(getResources().getDrawable(R.drawable.ok));
    mProgressDialog.show();
}

ProgressDialog的图标变换后看起来没问题。但是当ProgressBar启动(工作/圆形动画播放)时,我试图重置一个图标。

mProgressDialog.setIndeterminateDrawable(getResources().getDrawable(R.drawable.ok));

我遇到了意料之外的结果:圆形动画消失了,并且没有将图像设置为当前进度的可绘制对象。没有图像!空白区域代替我的图像。
    authButton.postDelayed(new Runnable() {
        @Override
        public void run() {
            mProgressDialog.setIndeterminateDrawable(getResources().getDrawable(R.drawable.ok)); //doesn't work as expected!
        }
    }, 2500);

我的问题是 - 如何在ProgressDialog工作期间运行时更改drawable?
需要将enter image description here更改为enter image description here

1
有趣的问题 :) - user2558337
2个回答

7

终于找到了解决方案

ProgressDialog 包含一个 ProgressBar,用于显示我们的可绘制图像。

View view = inflater.inflate(a.getResourceId(com.android.internal.R.styleable.AlertDialog_horizontalProgressLayout, R.layout.alert_dialog_progress), null);
mProgress = (ProgressBar) view.findViewById(R.id.progress); // THIS
mProgressNumber = (TextView) view.findViewById(R.id.progress_number);
mProgressPercent = (TextView) view.findViewById(R.id.progress_percent);
setView(view);

当我们尝试再次设置ProgressDialog的可绘制对象时,ProgressDialog确实会设置一个新的可绘制对象。但是这个可绘制对象没有边界(用于显示此视图的坐标)。因此,我们必须强制设置它。我选择了一种复制方式 - 只需从ProgressDialog当前的可绘制对象中复制边界。您可以使用另一种方法。

初始化对话框:

private void initDialog() {
    mProgressDialog = new ProgressDialog(this);
    mProgressDialog.setIndeterminate(true);
    mProgressDialog.setTitle("Please wait.");
    mProgressDialog.setMessage("Connecting to LinkedIn.");
    mProgressDialog.setCancelable(false);
}

展示

    mProgressDialog.show();

更改可绘制对象

private void changeToDone(int resId) {
    //Getting a progressBar from dialog
    ProgressBar bar = (ProgressBar) mProgressDialog.findViewById(android.R.id.progress);
    //Getting a DONE(new) drawable from resources
    Drawable drawable = getResources().getDrawable(resId);
    //Getting a drawable from progress dialog
    Drawable indeterminateDrawable = bar.getIndeterminateDrawable();
    //Obtain a bounds of current drawable
    Rect bounds = indeterminateDrawable.getBounds();
    //Set bounds to DONE(new) drawable
    drawable.setBounds(bounds);
    //Set a new drawable
    bar.setIndeterminateDrawable(drawable);

    mProgressDialog.setTitle("Done.");
    mProgressDialog.setMessage("Connected.");
}

注意:

解决方案未在特定情况下进行测试,例如

  • 我们在 ActionBar / TitleBar 中有一个进度条。
  • 另一种情况是当我们已经在屏幕窗口上有一个 android.R.progress 时。在这种情况下,我认为我的解决方案会产生意外的行为。

在ProgressBar类中,bar.getIndeterminateDrawable方法不存在,虽然在2020年的Android Studio 3.7中,我只能设置一个任意的边界。但是ProgressBar非常好用 - Google不应该将其弃用。在iOS中,我不得不使用一个库,但是在Android中,ProgressBar很好用。 - coolcool1994

2
private void initDialog(boolean is) {
    mProgressDialog = new ProgressDialog(this);
    mProgressDialog.setIndeterminate(true);
    mProgressDialog.setTitle("Please wait.");
    mProgressDialog.setMessage("Connecting to LinkedIn.");
    mProgressDialog.setCancelable(false);
    if(is) // take global variable
    mProgressDialog.setIndeterminateDrawable(getResources().getDrawable(R.drawable.ic_launcher));
    mProgressDialog.show();
    if(!is)
    new Handler().postDelayed(new Runnable() {

        @Override
        public void run() {
            mProgressDialog.cancel();
            mProgressDialog = null;
            initDialog(true);   
        }
    }, 2500);

首次调用使用 initDialog(false);

据我所知,不确定的可绘制对象无法真正替换,因此这种解决方法可以避免创建自定义进度条。


是的,它可以工作。但是因为我们显示了一个新的ProgressDialog实例,所以它会闪烁。 - Sergey Shustikov
是的,我遇到了同样的情况,有两个选择,要么使用这个,要么创建一个自定义的ProgressBar。 - Satty

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