android progressBar不会更新进度视图/ drawable

时间:2010-12-03 17:12:30

标签: android progress-bar

两个显示游戏进度的栏。如果用户获得积分或时间等,则应更新progressBars:

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(...)显示始终正确的值,但 SOMETIMES progressBars的可视栏不显示正确的progesses。它们显示先前设定的进度,即使“最大”和“进度”的吸气剂返回正确的值(在示例中,条形图显示levelHoldBar约20%(而不是100%)和约2%(而不是40%) %)为levelUp-bar)。我无法弄清楚,为什么日志输出是正确的但是drawables是错误的!? TextView(tv)正确更新!这里发生了什么?我该如何解决这个问题?

15 个答案:

答案 0 :(得分:42)

解决方案:这是ProgressBar中的Bug!

终于......我想我找到了解决方案......

这不像预期的那样有效:

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

如果再次传递相同的值,则setProgress(...)似乎不会触发drawable上的更新。但它也不会在setMax期间触发。因此缺少更新。看起来像android ProgressBar中的Bug!这花了我大约8个小时..大声笑:D

要解决这个问题,我只是在每次更新之前做一个bar.setProgress(0)...这只是一种解决方法,但它对我有用:

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

答案 1 :(得分:19)

我能够将其与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。

答案 2 :(得分:13)

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

Handler progressBarHandler = new Handler();

ProgressBar bar = (ProgressBar) findViewById(R.id.progressBar1);;

progressBarHandler .post(new Runnable() {

      public void run() {
          bar.setProgress(progress);
      }
});

答案 3 :(得分:9)

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

答案 4 :(得分:7)

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

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

希望能帮助任何人。

答案 5 :(得分:3)

创建updateThumb(); VerticalSeekbar中的方法

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

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

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

在verticalseekbar calss中为我工作

答案 6 :(得分:2)

确保将progressBar的样式设置为 风格=“@安卓风格/ Widget.ProgressBar.Horizo​​ntal” 否则它将显示Indeterminate Progress

(以防它会帮助某人)

答案 7 :(得分:2)

我通过以下方式尝试了很多方法:在 Thread runOnUiThread Handler,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;
}

答案 8 :(得分:1)

感谢Stuck的帖子说明有一个Android错误。我也有一个垂直搜索栏。

问题出在我改变进度的时候。 drawable将被更新,但条形将设置为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));

答案 9 :(得分:1)

我尝试了列出的所有解决方案,但它们均无效。事实证明……真正的问题是我的代码忙于运行,实际上阻塞了UI线程。因此,可以立即解决问题的正确解决方案是...将繁忙的代码放在异步任务中。

就我而言,我正在将数千条记录从XML加载到SQLite数据库中。自然,我想更新进度条。应该执行此操作的代码(prg_bar.setProgress(iProgressPercentage))没有任何作用,并且在加载结束时,UI终于有机会运行。 of,进度条从零到100。

将相同的代码放入异步任务的onProgressUpdate()中,并包装相同的功能代码,即可完美地工作。这使我对“进度条中存在错误”的想法表示怀疑,并且将max和max设置为零,或者其中的任何事情都不是偶然的解决方法。

答案 10 :(得分:0)

这对我有用......

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

答案 11 :(得分:0)

这里没有什么对我有用,所以我找到了一个不同的解决方案。我注意到一切都运行良好,直到我尝试更改最大值(使用不同的值调用 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 ,我只需要用 getProgressFixed setProgressFixed替换 getProgress setProgress

请勿覆盖 setProgress getProgress 。它们在内部被称为。

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

答案 12 :(得分:0)

如果你喜欢完整的进度条

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

如果您的进度条为空

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

答案 13 :(得分:0)

每个人。 如果存在进度并且新进度值相同, 进度栏未更新。 因此您可以将新值设置为接近值,这很容易。

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

    super.setProgress(progress);
}

答案 14 :(得分:-1)

对于我来说,如果我在每个setProgress()之前将setVisibility()设置为可见,则对我来说工作

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