- ProgressDialog — Диалог с индикатором прогресса
- Выполнение задачи в другом потоке
- Заметки о ProgressDialog или как правильно показать прогресс выполнения
- Проблема или Решение №0
- Решение №1. Вообще ничего не показывать
- Решение №2. Использовать ProgressBar
- Решение №3. Использовать ProgressBar внутри Notification Area
- Решение №4. Использовать ProgressBar внутри Title Bar’а приложения
- Решение №5. Использовать все решения
- Вместо заключения
- ziginsider
- Полный список
ProgressDialog — Диалог с индикатором прогресса
ProgressDialog представляет собой диалоговое окно с индикатором прогресса. В диалоговое окно также можно добавлять дополнительные элементы управления, например, кнопки для отмены задачи.
Для создания диалогового окна с индикатором прогресса необходимо инициализировать объект ProgressDialog через вызов конструктора класса ProgressDialog(Context), передав ему в качестве параметра контекст текущей деятельности. Далее нужно установить нужные свойства диалогового окна: стиль, сообщения и т.д.
У индикатора прогресса можно установить два стиля — горизонтальный и в виде вращающейся окружности. Давайте перейдём к примеру. Добавим в проект две кнопки для вызова диалоговых окон с индикаторами прогресса двух стилей и напишем следующий код:
Запустив проект, вы увидите два разных индикатора прогресса. Причём первый горизонтальный индикатор прогресса будет совсем скучный — никакой анимации и никаких изменений. Второй индикатор чуть поживее, так как можно увидеть анимацию окружности. Он применяется в том случае, когда процент выполнения не важен. А для горизонтального индикатора необходимо самостоятельно позаботиться об анимации и выводе процентов выполнения задачи. Мы решим данную задачу в следующем примере.
Выполнение задачи в другом потоке
Настоятельно рекомендуется длительные задачи выносить в другой поток и сообщать о прогрессе его выполнения назад в основной поток деятельности через объект Handler. Для демонстрации я взял кусок кода из официальной страницы разработчиков Android. Добавим к проекту кнопку.
Запустив проект, вы увидите, что полоска индикатора прогресса закрашивается и по достижении отметки 100% закрывает диалоговое окно, и мы возвращаемся в основное окно программы.
По умолчанию, окно диалога выводится по центру экрана. Можете определить другую позицию.
Источник
Заметки о ProgressDialog или как правильно показать прогресс выполнения
В данном посте я хочу поговорить о таком элементе UI Android как ProgressDialog и вообще о теме отображения прогресса в приложении, возможных реализациях и проблемах.
Под катом вас ждет некоторые мысли по теме + совсем немного кода. Наверно, тема, о которой я буду говорить, многим может показаться очевидной, но глядя на одни и те же «решения» в приложениях из Меркета, все видимо не так однозначно. Плюс, мне будет интересно услышать ваши соображения или best practice по теме.
Проблема или Решение №0
ProgressDialog — базовый элемент Android, является крайне популярным средством при необходимости отображения прогресса выполнения задачи. Кошерный пример реализации ProgressDialog + AsyncTask можно взять у хабрапользователя mike114 вот здесь.
Все было бы хорошо, но имеется один существенный недостаток: ProgressDialog модальный. Т.е. во время его работы пользователь не в состоянии взаимодействовать с UI. Да, иногда это обоснованно, особенно когда попросту нет альтернативных вариантов действия, например, при первоначальном логоне, но во многих ситуациях это не оправдано, т.к. заставляет пользователя ждать окончания операции, хотя он мог бы заняться чем-то более полезным.
Примеров множество, вот здесь хабрапользователь bugrimov использует ProgressDialog для отображения прогресса пока грузится контент с сервера. При этом, если по каким-то причинам, это происходит не так быстро, пользователь будет обязан ждать, пока ему что-то не вернется, хотя вместо этого он мог бы запустить несколько параллельных задач и пока грузятся одни читать уже загруженные.
Примечание: ProgressDialog коварный элемент, т.к. он настолько привычен и, как следствие, понятен пользователям Android, что они, скорее всего, простят вам его необоснованное использование.
Решение №1. Вообще ничего не показывать
Плюсы:
- В результате такого решения пользователь никак не блокируется и волен делать что ему вздумается. Здесь хабрапользователь rude подобным образом загружает в фоне картинки для списка.
Минусы:
- Пользователь все время находится в неведении, он не знает выполняется еще что-то или нет, а это может раздражать в достаточной степени.
- Для этого и всех последующих решений без ProgressDialog’а, заключается в усложняющейся логике работы, т.к. теперь во время выполнения задачи пользователь может сделать куда больше действий чем при блокирующем ProgressDialog, то нужно будет это учитывать дополнительно, например, обрабатывать повторный запуск задачи до завершения выполнения такой же предыдущей.
В некоторых ситуациях это может быть нормальным решением, например, если вы пишите свой ICQ-подобный клиент, то нет смысла показывать прогресс для загрузки статуса собеседника, это операция может быть прозрачной для пользователя.
Т.е. вывод, который можно сделать: не стоит доходить до идиотизма при отображении прогрессов, если информации о процессе выполнения операции пользователю не нужна, отображение прогресса можно опустить.
Решение №2. Использовать ProgressBar
ProgressBar — базовый компонент Android, позволяющий отображать прогресс выполнения прямо на View.
Для того чтобы получить что-нибудь аля:
Достаточно создать обычный xml ресурс и определить в нем ProgressBar:
Далее этот прогресс бар можно использовать, как все прочие компоненты внутри layout’ов:
Такое решение используется в Android Market, если во время установки/обновления перейти в список установленных приложений, то можно увидеть прогрессы выполнения текущих тасков.
Еще часто подобный подход применяют при загрузке множества однотипных элементов, сначала отображают пустые формы с ProgressBar’ом внутри, а далее по ходу загрузки наполняют их содержимым.
Плюсы:
- Опять же в том, что не блокирует пользователя.
- А также, в сравнении с первым решением, показывает прогресс, т.е. пользователь в курсе того, что что-то происходит.
Минусы:
- Занимает место на экране, а на мобильных устройствах каждый «клочок» полезной поверхности ценен на вес золота. Его конечно можно скрывать когда прогресса нет, но тогда будет нарушаться логичность UI, в котором каждый элемент занимает свое место.
- Еще один минус в позиционности, т.к. данный прогресс привязан к экрану, то не всегда очевидно, что делать если переходишь на другой экран, т.е. показывать что-то пользователю или нет, а главное где.
- И еще минус в том, что положение прогресс бара подсознательно ассоциируется с элементом рядом с котором он расположен, т.е. нужно продумывать интерфейс еще внимательней, чтобы в итоге не было ложных предположений о том, что сейчас обновляется какой-то конкретный элемент, хотя на самом деле обновляется весь экран.
- Общий минус всех не ProgressDialog решений: усложнение логики работы (см. Решение №1).
Решение №3. Использовать ProgressBar внутри Notification Area
Такое решение также используется в Android Market, когда пользователь запускает установку приложения, отдельный прогресс добавляется в Notification area, позволяя пользователю перейти туда в независимости от текущего положения.
Чтобы добавить ProgressBar в Notification Area необходимо для начала создать XML ресурс, например, такой:
Далее нужно добавить новый layout в Notification Area:
Для работы с созданным прогресс баром можно использовать следующий код:
В итоге выглядеть ячейка в Notification Area будет вот так:
Плюсы:
- Опять не блокируем пользователя.
- Как и в решении №2 прогресс показывается и пользователь в курсе что что-то происходит.
- Данное решение не привязана к окнам программы, т.е. на него можно перейти из любого окна при этом сами окна изменять не требуется.
- Не требуется дополнительное место в окне для отображения прогресса.
Минусы:
- После завершения отображения нотификации в Notification Area (не завершении ее самой, а только сообщения о то, что она появилась) не виден прогресс, т.е. пользователь не знает происходит что-то или нет. Это значит, что ему придется периодически заглядывать туда, что может быть не очень удобно.
- Данное решение не является интуитивно понятным в достаточной степени.
- Общий минус всех не ProgressDialog решений: усложнение логики работы (см. Решение №1).
Решение №4. Использовать ProgressBar внутри Title Bar’а приложения
Данное решение применяется во многих продуктах, например, в gReader.
Для реализации необходимо создать layout с содержимым, в моем случае это только ProgressBar:
И в методе onCreate кастомезировать имеющийся title bar нашим layout’ом:
В итоге это должно выглядеть вот так:
Данный пример рассчитан на задние произвольного пользовательского layout’а, т.е. в title bar пойдет все содержимое определенное в этом layout’е, т.е. не только ProgressBar, если же вам нужен только он, то для этого существует более простая возможность:
Плюсы:
- Опять не блокируем пользователя.
- В отличии от решения №3 прогресс всегда заметен.
- Как в решениях №2 и №3 прогресс показывается и пользователь в курсе что что-то происходит.
- Не требуется дополнительное место в окне для отображения прогресса.
Минусы:
- Прогресс привязан к окну, и если потребуется его показывать между разными окнами это нужно будет предусмотреть отдельно.
- Title bar уступает по высоте Notification area и поэтому в него можно вместить меньше информации, иначе она станет плохо различимой.
- Подобное решение подходит только для title’ов со стандартным набором стилей. Т.е. на Activity внутри TabHost его приделать не получится.
- Общий минус всех не ProgressDialog решений: усложнение логики работы (см. Решение №1).
Решение №5. Использовать все решения
По моему мнению, это самое лучшее решение!
Вы не обязаны использовать только что-то одно, все зависит от решаемой задачи, как банально это и звучит. Иногда лучше всего будет ничего не показывать, иногда ProgressDialog, иногда вариации ProgressBar’а, а иногда еще что-то. Повторюсь, все зависит от задачи.
Вместо заключения
Если вы принимаете какое-то решение, то не исходите из соображений простоты разработки и не ограничивайтесь известными вам решениями, учитесь. Подумайте о пользователях, о том как им было бы удобнее и понятнее, а они это обязательно оценят.
Если вы используете решения отличные от приведенных здесь, пожалуйста, расскажите о них, я думаю многим Android-разработчикам будут интересны подобные примеры.
Источник
ziginsider
10 декабря 2017
Вольный перевод статьи Ben Daniel A. “Farewell ProgressDialog, Long Live ProgressBar”.
Если вы такойже как я, то вы использовали progress dialog почти в каждой части ваших приложений. И поэтому вы должны знать, что класс ProgressDialog объявлен как deprecated в API 26. Теперь, прежде чем вы начнете использовать аннотацию @SuppressWarnings(«deprecation») , остановитесь и подумайте над этим. Что послужило главной причиной того, что команда Android UX приняла решение отказаться от ProgressDialog? Понятно, что они провели исследования и решили, что блокировка интерфейса (включая back button), когда используется ProgressDialog и выполняется длительная операция, это не самый оптимальный вариант для большинста приложений. Пользователи могут изменить свои намерения в любой момент использования вашего приложения, и они не должны быть вынуждены ждать, когда ProgressDialog завершит работу, чтобы использовать свое устройство.
Некоторое время назад я заметил подобное изменение дизайна в Android-приложении Twitter. В процессе отправки твита нет progress dialog. Они решили оптимизировать способ показа статуса отправки твита: поместили его в нотификации. Пользователь может продолжать работу с приложением, пока твит отправляется. Если отправка успешна, нотификация с progress bar пропадает. Твит, отправка которого не завершилась, остается в уведомлениях, позволяя пользователю отправить его повторно.
Мне нравится такой подход, он прост для понимания. Однако, что русскому хорошо, то немцу смерть. И это и есть причина, по которой такая штука как ProgreesBar должна была появиться. ProgressBar не блокирует интерфейс, но обеспечивает ту же обратную связь, что и ProgressDialog. Существует множество способов обеспечить обратную связь progress bar на экране и фоновой задачи.
Вы можете выбрать круговой индикатор рядом с View, которая вызвала эту операцию. Например, если у нас есть окно входа, то рядом с кнопкой входа должен появляться progress bar, который сообщает о том, что работает операция входа. Обратите внимание, что для избегания ситуации, когда кнопка входа нажимается много раз, вы можете сделать ее неактивной во время операции входа Если вход не был успешен, сообщите об этом и активируйте кнопку. Подобное можно сделать, используя RxJava и Android’s Observable.
Вы можете создать progress bar в верхней части вашего экрана, это легко реализовать, если у вас одна Activity и несколько Fragment. Макет Activity будет содержать progress bar и Fragment должны сообщать о выполнении операции, чтобы Activity получала сигнал об изменении progress bar (такая логика может быть реализована также с помощью RxJava).
Пожалуйста, не ограничивайтесь только этими двумя способами, есть другие крутые альтернативы использования диалога progress, как мы могли видеть на примере приложения Twitter. Теперь, когда Android принял смелое решение о том, чтобы объявить класс ProgressDialog deprecated, я надеюсь, что эксперты UX придумают множество способов показывать progress bar, позволяя пользователь в то же время взаимодействовать со своим экраном.
Бывает и так, что когда работает progress bar, мы должны сделать неактивным остальной интерфейс. Для этого можно испольовать такой трюк:
Когда вы закончите, вы можете отменить это, используя:
Источник
Полный список
— работаем с ProgressDialog
ProgressDialog позволяет показать пользователю, что идет какая-либо операция и надо подождать. Он бывает двух видов: просто вращающийся круг и полоса-индикатор, которая показывает процент выполнения. Сделаем приложение, которое будет показывать оба вида.
Project name: P0671_ProgressDialog
Build Target: Android 2.3.3
Application name: ProgressDialog
Package name: ru.startandroid.develop.p0671progressdialog
Create Activity: MainActivity
В strings.xml пропишем тексты:
Две кнопки: одна покажет диалог с крутящимся кругом (ProgressDialog по умолчанию), другая — с горизонтальной полосой индикатором
Для первого диалога все почти как обычно. Сначала настраиваем заголовок и сообщение. Затем добавляем кнопку. Здесь немного по-другому, чем с AlertDialog.Builder. Мы используем метод setButton. На вход передаем тип кнопки, текст и обработчик. Тип кнопки определяется константами: BUTTON_POSITIVE, BUTTON_NEGATIVE, BUTTON_NEUTRAL. В обработчике я ничего не пишу, мне он не нужен сейчас. Далее показываем диалог методом show.
Для второго диалога указываем, что он будет индикатором. Это делается с помощью метода setProgressStyle. Далее задаем заголовок и сообщение. Кнопку не добавляем, но если вдруг нужна будет, то это делается полностью аналогично первому диалогу. Метод setMax устанавливает максимальное значение заполнения индикатора. Значение 2148 я выбрал случайно. Метод setIndeterminate включает анимацию индикатора, имитирующую ожидание. Метод show показывает диалог.
Далее снова приходится использовать незнакомый нам Handler. Понимать его действие сейчас необязательно, позже мы его еще будем проходить. Сейчас я просто распишу на словах, что он делает. Handler ждет 2 секунды (просто имитация, например, подключения к серверу), выключает анимацию ожидания (setIndeterminate), затем каджые 100 миллисекунд увеличивает значение основного (incrementProgressBy) и дополнительного (incrementSecondaryProgressBy) индикатора, пока основной индикатор (getProgress) не достигнет максимума (getMax, в нашем случае = 2148). После этого диалог закрываем (dismiss).
Пример дополнительного индикатора вы могли видеть на YouTube. Когда смотрите видео, там снизу по мере воспроизведения заполняется основной индикатор, а правее его заполняется еще один, затемненный, который показывает, сколько видео закэшировалось. Разумеется, если он вам не нужен, вы просто его не заполняете. Будет отображаться только основной.
Все сохраним и запустим.
Вызовем первый диалог
Бесконечно крутящийся круг показывает, что процесс идет. Но сколько осталось – непонятно. Не всегда можно спрогнозировать оставшееся время или показать процент выполнения задачи.
Закроем первый диалог и откроем второй. Он две секунды повисит с анимацией ожидания
А затем начнет заполнять индикатор (основной и дополнительный).
Когда основной индикатор заполнится, диалог закроется.
Думаю, по диалогам тему можно закрывать. Мы рассмотрели их достаточно подробно. То, что пока непонятен Handler – это ничего страшного, через несколько уроков возьмемся и за него. Если вдруг чего осталось непонятным, велкам на форум, будем разбираться )
На следующем уроке:
— знакомимся с Parcel
Присоединяйтесь к нам в Telegram:
— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.
— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование
— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня
— новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме
Источник