android progressBar не обновляет отображение прогресса / рисование

две полосы, которые показывают ход игры. Если пользователь получает очки или время истекло и т. Д., Индикаторы прогресса должны быть обновлены:

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 (...) в конце показывает ВСЕГДА правильные значения, но ИНОГДА визуальные полосы на индикаторах выполнения не показывают правильные результаты. Они показывают прогресс, который был установлен ранее, даже если геттеры для «max» и «progress» возвращают правильные значения (в этом примере полоса показывает около 20% (вместо 100%) для levelHoldBar и около 2% (вместо 40). %) для levelUp-бара). Я не могу понять, почему вывод журнала правильный, а чертежи неправильные !? TextView (tv) обновляется правильно! Что тут происходит? Как я могу это исправить?


person Stuck    schedule 03.12.2010    source источник
comment
Хорошо, сначала глупые вопросы - 1) вы обновляете поток пользовательского интерфейса и 2) у вас нет никаких пользовательских функций рисования для чего-либо?   -  person EboMike    schedule 03.12.2010
comment
да, я запускаю его в потоке пользовательского интерфейса, и у меня нет никаких пользовательских рисунков. Он всегда использует один и тот же стек вызовов для обновления, и иногда полосы обновляются, а иногда нет .. это странно ^^   -  person Stuck    schedule 03.12.2010
comment
Хорошо. Что-то подозрительно. Что произойдет, если вы упростите свою деятельность, например, изменив индикатор выполнения на предыдущее значение + 1 при каждом нажатии кнопки? ProgressBars очень просты, поэтому нам нужно перейти от простой настройки к тому, что у вас есть в настоящее время, и выяснить, в какой момент он ломается.   -  person EboMike    schedule 04.12.2010
comment
Покажите, как вы вызываете updateViewS (). Вы почти наверняка участвуете в какой-то теме.   -  person Falmarri    schedule 04.12.2010
comment
См. Другой комментарий .. там я опубликовал, как я вызываю updateViews () в потоке пользовательского интерфейса ... но проблема заключается в неожиданном поведении ProgressBar: см. Мой собственный ответ ... похоже на ошибку. Я сообщил об этом. Может ты сможешь это подтвердить. API уровня 7   -  person Stuck    schedule 04.12.2010
comment
code.google.com/p/android/issues/detail?id= 12945. Отлично. Я подписался на это.   -  person EboMike    schedule 04.12.2010
comment
У меня проблема с SeekBar, не могли бы вы мне помочь ... вот мой вопрос stackoverflow.com/questions/54692981/   -  person VikaS GuttE    schedule 23.02.2019


Ответы (15)


РЕШЕНИЕ: ошибка в ProgressBar!

наконец ... Думаю, я нашел решение ...

это не работает так, как можно было бы ожидать:

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

SetProgress (...), похоже, не запускает обновление на чертеже, если то же значение передается снова. Но и во время setMax он не срабатывает. Значит обновление отсутствует. Похоже на ошибку в Android ProgressBar! Это заняло у меня около 8 часов .. lol: D

Чтобы решить эту проблему, я просто делаю bar.setProgress (0) перед каждым обновлением ... это всего лишь обходной путь, но он работает для меня, как и ожидалось:

bar.setMax(50);
bar.setProgress(20);
bar.setProgress(0); // <--
bar.setMax(20);
bar.setProgress(20);
person Stuck    schedule 04.12.2010
comment
С тех пор это уже есть: code.google.com/p/android/ issues / detail? id = 12945 - person Stuck; 10.07.2011
comment
Вы уверены, что второй setMax равен 20? Или должно быть 50? - person taxeeta; 26.07.2013
comment
это очень плохая ошибка для индикатора выполнения .. 10 часов, чтобы найти это исправленным. - person Ketan Mehta; 30.10.2013
comment
@ Застрял у меня проблема с круглым индикатором выполнения, когда вызов setMax не работает, есть ли решение? Хотя он работает с горизонтальной полосой выполнения .. - person Rat-a-tat-a-tat Ratatouille; 31.03.2014
comment
@ Rat-a-tat-a-tatRatatouille Я думаю, было бы лучше задать для него новый вопрос. - person Stuck; 01.04.2014
comment
К сожалению, это все еще ошибка даже через 4 года. Установка только bar.setProgress (0) не работает. - person TheOnlyAnil; 07.03.2015
comment
09.04.2017 Проблема все еще существует. Я вызвал setProgress в действии post, и, похоже, на данный момент проблема решена. - person Abluescarab; 09.04.2017
comment
@ Rat-a-tat-a-tatRatatouille @ Застрял исправление, опубликованное вами @Stuck не помогло для кругового просмотра прогресса :(. Однако я смог исправить, используя android:useLevel="true" в shape внутри набора для рисования для android:progressDrawable. - person gipsey; 13.03.2018
comment
У меня проблема с SeekBar, не могли бы вы мне помочь ... вот мой вопрос stackoverflow.com/questions/54692981/ - person VikaS GuttE; 23.02.2019
comment
Какое решение !! этот ответ просто спас меня и мое время, спасибо !! - person Riddhi; 02.04.2019
comment
Для меня сработало использование API с логическим флагом анимации, равным true - например. bar.setMax(20, true); Надеюсь, это кому-то поможет. - person anshajkhare; 24.11.2020

Мне удалось заставить это работать с 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 включительно.

person david.mihola    schedule 25.11.2014
comment
Android 8.1. Тот же баг :) - person tim4dev; 29.06.2018

Вы можете использовать обработчик для обновления progressbar

Handler progressBarHandler = new Handler();

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

progressBarHandler .post(new Runnable() {

      public void run() {
          bar.setProgress(progress);
      }
});
person SKT    schedule 12.06.2012
comment
Почему это может помочь, он говорит, что обновляет уже из потока пользовательского интерфейса - person User; 27.11.2012
comment
@Ixx У меня тоже была такая же проблема. Это решило мою проблему. Я подумал, что здесь может помочь. - person SKT; 28.11.2012
comment
Тогда это, вероятно, потому, что вы вызываете его в onCreate (). Тогда это тоже помогает. - person User; 28.11.2012
comment
Нет. Я позвонил в onResume () - person SKT; 28.11.2012
comment
Если вы сделали вызов в onResume и в потоке пользовательского интерфейса, я не знаю, зачем нужен обработчик. AFAIK в onCreate необходимо опубликовать, потому что макет не закончен. В onResume () макет должен быть закончен, не так ли? Может я что-то упускаю. - person User; 28.11.2012
comment
Я пробовал progressbar.post (), runOnUiThread, ничего не работало, кроме этого: / - person A. N; 19.02.2018

Для меня звонок setMax() раньше setProgress() по какой-то причине работал.

person Farbod Salamat-Zadeh    schedule 30.06.2015

В моем случае я создаю VerticalSeekBar, и решение Stuck не работает. Спустя несколько часов я нашел решение:

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

Надеюсь, что это кому-нибудь поможет.

person nlt    schedule 22.08.2013
comment
Спасибо, спасли мне день! Работаем над Nougat. - person Hermandroid; 01.02.2017

Создать updateThumb (); метод в VerticalSeekbar

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

А затем вызовите метод обновления большого пальца после установки прогресса.

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

его работа для меня в вертикальной панели поиска

person saravanan    schedule 21.11.2013
comment
Как создать метод внутри существующего класса? - person Daniel; 27.02.2014
comment
Класс VerticalSeekbar не является классом по умолчанию для Android, это настраиваемый класс, который должен быть создан вами, только вам нужен код calss .. - person saravanan; 28.02.2014

Убедитесь, что для стиля progressBar установлено значение style = "@ android: style / Widget.ProgressBar.Horizontal", иначе будет отображаться "Неопределенный прогресс".

(На всякий случай кому то поможет)

person Humayoun    schedule 21.02.2018
comment
Это действительно помогло! style =? android: attr / progressBarStyleHorizontal - person Pat Lee; 29.09.2020

Я пробовал разными способами, вызывая setProgress в Thread, runOnUiThread, Handler, Runnable. Все они не работают.

Итак, наконец, установите значение 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;
}
person Tuan Nguyen    schedule 05.10.2018

Спасибо, застрял, за сообщение об ошибке 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));
person DanFredell    schedule 26.01.2015

Я перепробовал все перечисленные решения, они не сработали. Оказывается ... настоящая проблема заключалась в том, что мой код был занят, по сути блокируя поток пользовательского интерфейса. Итак, правильным решением, которое мгновенно устранило проблему, было ... поместить мой загруженный код в асинхронную задачу.

В моем случае я загружал несколько тысяч записей из XML в базу данных SQLite. Естественно я хотел обновить индикатор выполнения. Код, который должен был это сделать (prg_bar.setProgress (iProgressPercentage)), ничего не сделал, и в конце загрузки пользовательский интерфейс наконец получил возможность запуститься. Уф, индикатор выполнения переходит от нуля до 100.

Тот же код, помещенный в onProgressUpdate () асинхронной задачи, обернутый вокруг того же функционального кода, работал отлично. Это заставляет меня очень скептически относиться к идее «что есть ошибка в штрих-коде выполнения» и что установка максимума и нуля или любой из этих вещей когда-либо были чем-то большим, чем случайная работа.

person Anders8    schedule 27.06.2018

Это сработало для меня ...

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;
  }
}
person Mohammad Tahir    schedule 20.10.2016

Здесь у меня ничего не работало, поэтому я пришел с немного другим решением. Я заметил, что все работает хорошо, пока я не попытаюсь изменить максимальное значение (вызов 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 как обычно, и мне просто нужно заменить getProgress и setProgress на getProgressFixed и setProgressFixed .

Не переопределяйте setProgress и getProgress. Они называются внутренне.

Мое решение не учитывается с помощью setMin. Если вам это нужно, измените код соответствующим образом.

person Václav Hodek    schedule 19.10.2017

если тебе нравится полная шкала прогресса

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

если ваша полоса прогресса пуста

time_prg_bar.setMax(100);
time_prg_bar.setProgress(100); <--
person Mr_Moradi    schedule 06.06.2018

все. в случае существующего прогресса и нового значения прогресса такая же, индикатор выполнения не обновляется. поэтому вы устанавливаете новое значение как ближайшее значение, это простой способ.

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

    super.setProgress(progress);
}
person egotron    schedule 15.01.2019

Для меня сработало, если я установил setVisibility () на видимый перед каждым setProgress ()

setVisibility(View.VISIBLE);
setProgress(progress);
person Staņislavs Petkevičs    schedule 19.06.2018