【问题标题】:android progressBar does not update progress view/drawableandroid progressBar 不更新进度视图/可绘制
【发布时间】:2011-05-19 21:09:31
【问题描述】:

显示游戏进度的两个条形图。如果用户获得积分或时间已到等,则应该更新进度条:

private TextView tv;
private ProgressBar levelHoldBar;
private ProgressBar levelUpBar;

//...
private void updateViews() {

    // ...
    levelHoldBar.setMax(currentLevel.getThreshold());
    levelHoldBar.setProgress(currentPoints > currentLevel.getThreshold() ? currentLevel.getThreshold() : currentPoints);

    levelUpBar.setMax(nextLevel.getThreshold());
    levelUpBar.setProgress(currentPoints > nextLevel.getThreshold() ? nextLevel.getThreshold() : currentPoints);

    tv.setText(currentPoints+"/"+currentLevel.getThreshold());

    Log.d(TAG, "hold prog/max "+levelHoldBar.getProgress()+"/"+levelHoldBar.getMax());
    Log.d(TAG, "up   prog/max "+levelUpBar.getProgress()+"/"+levelUpBar.getMax());
}

即。输出:

12-03 17:48:33.918: DEBUG/MainActivity(6829): hold prog/max 20/20
12-03 17:48:33.918: DEBUG/MainActivity(6829): up   prog/max 20/50

最后的 Log.d(...) 显示 ALWAYS 正确的值,但 SOMETIMES 进度条的可视条不显示正确的进程。即使“max”和“progress”的获取器返回正确的值,它们也会显示先前设置的进度(在示例中,该条显示 levelHoldBar 的大约 20%(而不是 100%)和大约 2%(而不是 40 %) 用于 levelUp-bar)。我不明白,为什么日志输出是正确的,但绘图是错误的!? TextView (tv) 已正确更新!这里发生了什么?我该如何解决?

【问题讨论】:

  • 好吧,先问愚蠢的问题 - 1) 您正在 UI 线程中进行更新,2) 您在任何地方都没有任何自定义绘图功能?
  • 是的,我在 UI 线程上运行它,我没有任何自定义图纸。它总是使用相同的调用堆栈进行更新,有时条形图会更新,有时它们不会更新。这很奇怪^^
  • 好的。有什么可疑的。当您将活动简化为例如每次按下按钮时将进度条修改为“上一个值 + 1”时会发生什么? ProgressBars 非常简单,所以我们需要从一个简单的设置开始到您当前拥有的内容,然后找出它在哪个点中断。
  • 显示您如何调用 updateViewS()。你几乎可以肯定在某个线程中比赛。
  • 查看其他评论.. 在那里我发布了我如何在 UI 线程上调用 updateViews() ......但问题是 ProgressBar 的意外行为:查看我自己的答案......似乎一个错误。我已经举报了。也许你可以确认一下。 API 7 级

标签: android progress-bar


【解决方案1】:

每个人。 如果存在进度和新进度值相同, 进度条没有更新。 所以你将新值设置为接近值,这是一种简单的方法。

@Override
public synchronized void setProgress(int progress)
{
    if (getProgress() == progress)
    {
        if (progress > 0)   progress -= 1;
        else                progress += 1;
    }

    super.setProgress(progress);
}

【讨论】:

    【解决方案2】:

    我尝试了多种方式,在 ThreadrunOnUiThreadHandler、Runnable 中调用 setProgress。它们都不起作用。

    所以最后,dialog.setIndeterminate(false); 的设置值会起作用。

    一旦你设置了 dialog.setIndeterminate(true);进度根本不会更新

    public static ProgressDialog createProgressDialog(Activity activity, int messageID, boolean cancelable) {
        ProgressDialog dialog = new ProgressDialog(activity, R.style.DialogButtonTint);
        dialog.setMessage(activity.getString(messageID));
        dialog.setIndeterminate(false);
        dialog.setMax(100);
        dialog.setSecondaryProgress(0);
        dialog.setProgress(0);
        dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        dialog.setCancelable(cancelable);
        dialog.show();
        return dialog;
    }
    

    【讨论】:

    • 这个修改对我有用。它确实需要 setIndeterminate(false),如果你设置为 true,它会运行它自己的动画。
    【解决方案3】:

    我尝试了列出的所有解决方案,但均无效。原来...真正的问题是我的代码正忙于运行,基本上阻塞了 UI 线程。因此,立即解决问题的正确解决方案是......将我繁忙的代码放入异步任务中。

    在我的例子中,我将数千条记录从 XML 加载到 SQLite 数据库中。自然我想更新进度条。应该这样做的代码( prg_bar.setProgress(iProgressPercentage) )什么也没做,在加载结束时,UI 终于有机会运行了。噗,进度条从零变成了 100。

    将相同的代码放入异步任务的 onProgressUpdate() 中,包裹在相同的功能代码中,运行良好。这让我非常怀疑“进度条代码中存在错误”的想法,并且将最大值和设置为零或任何这些事情都不仅仅是巧合。

    【讨论】:

      【解决方案4】:

      如果我在每个 setProgress() 之前将 setVisibility() 设置为可见,对我来说是有效的

      setVisibility(View.VISIBLE);
      setProgress(progress);
      

      【讨论】:

        【解决方案5】:

        如果你喜欢完整的进度条

        time_prg_bar.setMax(100);
        time_prg_bar.setProgress(0); <--
        

        如果你的进度条是空的

        time_prg_bar.setMax(100);
        time_prg_bar.setProgress(100); <--
        

        【讨论】:

          【解决方案6】:

          确保将进度条的样式设置为 style="@android:style/Widget.ProgressBar.Horizo​​ntal" 否则会显示 Indeterminate Progress

          (以防万一它会帮助某人)

          【讨论】:

          • 确实有帮助! style="?android:attr/progressBarStyleHorizo​​ntal"
          【解决方案7】:

          这里没有什么对我有用,所以我提出了一些不同的解决方案。我注意到一切正常,直到我尝试更改最大值(使用不同的值调用 setMax)。

          我的代码:

          class FixedSeekBar : SeekBar {
          
              constructor(context: Context) : super(context)
              constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
              constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
          
              companion object {
                  private const val PROGRESS_MAX = 1000000.toDouble()
              }
          
              private var mLastMaxValue: Int = 100
          
              override fun setMax(max: Int) {
                  mLastMaxValue = max
                  super.setMax(PROGRESS_MAX.toInt())
              }
          
              fun setProgressFixed(progress: Int) {
                  setProgress((PROGRESS_MAX / mLastMaxValue * progress).toInt())
              }
          
              fun getProgressFixed(): Int {
                  return (getProgress() / PROGRESS_MAX * mLastMaxValue).toInt()
              }
          
          }
          

          这对我来说非常有效。我可以像往常一样调用 setMax,我只需要将 getProgresssetProgress 替换为 getProgressFixedsetProgressFixed .

          不要覆盖 setProgressgetProgress。它们在内部被调用。

          我的解决方案不计入 setMin。如果需要,请相应地更改代码。

          【讨论】:

            【解决方案8】:

            这对我有用...

            OneFragmen.java

            public class OneFragment extends Fragment{
            
            public OneFragment() {
                // Required empty public constructor
            }
            private Toolbar toolbar;
            private TabLayout tabLayout;
            private ViewPager viewPager;
            
            int progress=0;
            private Handler handler = new Handler();
            TextView txtProgress;
            @Override
            public void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
            }
            
            @Override
            public View onCreateView(
                LayoutInflater inflater, 
                ViewGroup container,
                Bundle savedInstanceState ) {
            
               View view =  inflater.inflate(R.layout.fragment_one, container, false);
                getActivity().setTitle(R.string.app_name);
            
               final ProgressBar spinner = 
                   (ProgressBar) view.findViewById(R.id.outerProgressBar);
                Resources res = getResources();
                Drawable drawable = res.getDrawable(R.drawable.circular);
                txtProgress = (TextView)view.findViewById(R.id.txtProgress);
                spinner.setProgressDrawable(drawable);
                spinner.setSecondaryProgress(100);
                spinner.setMax(100);
                spinner.setProgress(0);
            
                new Thread(new Runnable() {
            
                    @Override
                    public void run() {
                        while (progress < 100) {
                            progress += 1;
                            handler.post(new Runnable() {
                                @Override
                                public void run() {
                                    spinner.setProgress(progress);
                                    txtProgress.setText(progress + "%");
                                }
                            });
                            try {
                                Thread.sleep(28);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }).start();
                return view;
              }
            }
            

            【讨论】:

              【解决方案9】:

              对我来说,调用setMax() 之前 setProgress() 出于某种原因。

              【讨论】:

                【解决方案10】:

                感谢 Stuck 发帖指出存在 Android 错误。我也有一个垂直搜索栏。

                问题出在我更改进度可绘制对象时。可绘制对象将被更新,但条形图将设置为 0 并且尺寸非常小。我可以使用 updateThumb() 调整它的大小,但进度仍为 0。

                为了将进度设置回原始值,我添加了一个 mylayer.setLevel(...);。我通过阅读 ProgressBar.doRefreshProgress(...) 的源代码发现了这一点。你也许可以做到seekBar.getProgressDrawable.setLevel(...)

                LayerDrawable mylayer = //new LayerDrawable()
                seekBar.setProgressDrawable(mylayer);
                seekBar.updateThumb();
                seekBar.setProgress((int) chLevel);
                mylayer.setLevel((int) (chLevel / MAX_LEVEL * 10000));
                

                【讨论】:

                  【解决方案11】:

                  我能够让它与View.post()一起工作:

                  @Override
                  public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
                  
                      // ...
                  
                      mSeekBar.post(new Runnable() {
                          @Override
                          public void run() {
                              mSeekBar.setProgress(percentOfFullVolume);
                          }
                      });
                  }
                  

                  与 SKT 的回答一样,我不清楚为什么这在不可行的情况下应该起作用

                  mSeekBar.setProgress(percentOfFullVolume);
                  

                  不过,Android Lollipop 似乎是这样,包括 Android Lollipop。

                  【讨论】:

                  • 安卓 8.1。同样的错误:)
                  【解决方案12】:

                  创建 updateThumb(); VerticalSeekbar 中的方法

                  public void updateThumb(){
                       onSizeChanged(getWidth(), getHeight(), 0, 0);
                  }
                  

                  设置进度后调用update thumb方法。

                  seekBar.setProgress((int) progress);
                  seekBar.updateThumb();
                  

                  它在verticalseekbar calss中对我有用

                  【讨论】:

                  • 如何在现有类中创建方法?
                  • VerticalSeekbar 类不是 android 的默认 calss,它是由你创建的自定义 cals,只有你想要 calss 代码..
                  【解决方案13】:

                  就我而言,我创建了 VerticalSeekBar,但 Stuck 的解决方案不起作用。几个小时后,我找到了解决方案:

                  @Override
                  public synchronized void setProgress(int progress) {
                      super.setProgress(progress);
                      onSizeChanged(getWidth(), getHeight(), 0, 0);
                  }
                  

                  希望对大家有所帮助。

                  【讨论】:

                  • 谢谢你,拯救了我的一天!研究牛轧糖。
                  【解决方案14】:

                  您可以使用处理程序更新progressbar

                  Handler progressBarHandler = new Handler();
                  
                  ProgressBar bar = (ProgressBar) findViewById(R.id.progressBar1);;
                  
                  progressBarHandler .post(new Runnable() {
                  
                        public void run() {
                            bar.setProgress(progress);
                        }
                  });
                  

                  【讨论】:

                  • 为什么会有帮助,他说他已经从 UI 线程更新
                  • @Ixx 我也有类似的问题。这解决了我的问题。我认为这可能会有所帮助。
                  • 那可能是因为你在onCreate()中调用了它。那么这也有帮助。
                  • 没有。我在 onResume() 中打了这个电话
                  • 如果您在 onResume 和 UI 线程中进行了调用,我不知道为什么需要处理程序。 onCreate 中的 AFAIK 必须发布,因为布局尚未完成。在 onResume() 中,布局应该完成了,不是吗?也许我错过了什么。
                  【解决方案15】:

                  解决方案:这是 ProgressBar 中的一个错误!

                  终于……我想我找到了解决办法……

                  这并不像预期的那样工作:

                  bar.setMax(50);
                  bar.setProgress(20);
                  bar.setMax(20);
                  bar.setProgress(20);
                  

                  如果再次传递相同的值,setProgress(...) 似乎不会触发可绘制对象的更新。但它也不会在 setMax 期间触发。所以缺少更新。似乎是 android ProgressBar 中的错误!这花了我大约 8 个小时。哈哈:D

                  为了解决这个问题,我只是在每次更新之前做一个 bar.setProgress(0) ......这只是一种解决方法,但它对我来说可以按预期工作:

                  bar.setMax(50);
                  bar.setProgress(20);
                  bar.setProgress(0); // <--
                  bar.setMax(20);
                  bar.setProgress(20);
                  

                  【讨论】:

                  • 从那时起它就已经存在了:code.google.com/p/android/issues/detail?id=12945
                  • 进度条的非常糟糕的错误.. 10 小时才能找到这个补丁。
                  • @Stuck 我有一个循环进度条的问题,其中调用 setMax 不起作用,有解决方法吗?虽然它确实适用于水平进度条..
                  • 遗憾的是,即使在 4 年后,这仍然是一个错误。仅设置 bar.setProgress(0) 不起作用。
                  • 2017 年 4 月 9 日问题仍然存在。我在post 操作中调用了setProgress,它现在似乎已经解决了问题。
                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2015-03-29
                  • 1970-01-01
                  • 2012-06-21
                  相关资源
                  最近更新 更多