- ProgressBar — Индикатор прогресса
- Основы
- Стилизация
- Индикатор с текстом
- Анимация ObjectAnimator
- Дополнительное чтение
- ProgressBar (Horizontal) — горизонтальный индикатор прогресса
- Основы
- Отдельный поток
- Пунктирный ProgressBar
- Режим Indeterminate
- Настройка через XML
- Вертикальный индикатор прогресса
- verticalprogressbar.xml
- verticalprogressbar2.xml
- Круговые индикаторы прогресса
- Индикатор с текстом
- Программное создание индикатора
- Анимация ObjectAnimator
- Дополнительное чтение
- Заметки о ProgressDialog или как правильно показать прогресс выполнения
- Проблема или Решение №0
- Решение №1. Вообще ничего не показывать
- Решение №2. Использовать ProgressBar
- Решение №3. Использовать ProgressBar внутри Notification Area
- Решение №4. Использовать ProgressBar внутри Title Bar’а приложения
- Решение №5. Использовать все решения
- Вместо заключения
ProgressBar — Индикатор прогресса
Основы
Компонент ProgressBar (Индикатор прогресса) применяется в тех случаях, когда пользователю нужно показать, что программа не зависла, а выполняет продолжительную работу.
Находится в категории Widgets.
Студия предлагает несколько видов индикаторов: ProgressBar и ProgressBar (Horizontal). В свою очередь компонент имеет несколько модификаций и их отличия заложены в стилях, если посмотреть XML-описание компонентов. Стили постоянно меняются, поэтому проще выбрать атрибут style и посмотреть предлагаемые варианты из выпадающего списка на текущий момент.
Методы для работы с ProgressBar:
- setProgress() — устанавливает заданное значение индикатора прогресса;
- getProgress() — возвращает текущее значение индикатора прогресса;
- incrementProgressBy() — устанавливает величину дискретизации приращения значения индикатора;
- setMax() — устанавливает максимальное значение величины прогресса.
Круговые индикаторы Normal, Small и Large можно просто разместить на экране, и они будут бесконечно выводить анимацию вращения без единой строчки кода.
Как правило, «бесконечный» индикатор выводят в нужный момент, а когда задача выполнена, то его скрывают. Видимость можно установить через XML и программно.
В коде используется метод setVisibility()
Сейчас проекты в студии используют Material Design, поэтому цвет индикатора будет соответствовать ресурсу colorAccent.
Можно переопределить цвет, если вы хотите отказаться от этой связи с colorAccent, задав свой стиль.
Подключаем через тему.
Другая настройка связана с Tint — оттенками цвета (Android 5.0).
Стилизация
Если вам не нравится внешний вид стандартных индикаторов, то можете придумать свой. Есть два варианта для реализации этой цели. В первом случае можно подготовить готовый png-файл (spin_custom.png) и поместить его в ресурс, например, в папку res/drawable.
Затем в этой же папке создаём xml-файл spinner_png.xml с таким содержанием:
Теперь в разметке активности можно определять ProgressBar так:
Если запустить проект, то увидим такой индикатор:
В реальности индикатор выглядит немного корявым, подёргиваясь на экране. Кроме того, изображение можно улучшить, уменьшив количество цветов и сократив размер файла.
Второй вариант выглядит предпочтительней. На этот раз мы обойдёмся без графических файлов, а будем использовать только XML-разметку. В этой же папке поместим файл spinner_ring.xml следующего содержания:
Теперь в разметке активности пропишем строки:
Получим следующий результат:
Индикатор с текстом
К сожалению, индикатор не выводит текст во время работы, что не очень удобно. Можно создать свой ProgressBar из TextView или создать свой компонент на основе ProgressBar. Другой простой способ — наложить текстовый блок прямо на индикатор, используя RelativeLayout. Пример для пояснения.
Код, чтобы увидеть работу индикатора. При каждом щелчке кнопки значение индикаторов увеличиваются на 10 процентов.
Индикаторы прогресса также можно использовать в заголовках приложения у старых устройств, а также в ActionBar и ToolBar у новых устройств.
Компонент постоянно дорабатывается. Например, в Android 8 появились новые методы isAnimating(), getMin(), setMin().
Анимация ObjectAnimator
Можно подключить готовую анимацию для визуализации компонента.
Дополнительное чтение
Material ProgressBar — статья про создание собственного индикатора в стиле Material Design
Indeterminate — серия статей на тему создания индикаторов прогресса, ссылка на первую часть.
Источник
ProgressBar (Horizontal) — горизонтальный индикатор прогресса
Основы
Компонент ProgressBar (Horizontal) (Индикатор прогресса) применяется в тех случаях, когда пользователю нужно показать, что программа не зависла, а выполняет продолжительную работу.
Находится в категории Widgets.
Студия предлагает несколько видов индикаторов: ProgressBar и ProgressBar (Horizontal). В свою очередь компонент имеет несколько модификаций и их отличия заложены в стилях, если посмотреть XML-описание компонентов. Стили постоянно меняются, поэтому проще выбрать атрибут style и посмотреть предлагаемые варианты из выпадающего списка на текущий момент.
Методы для работы с ProgressBar:
- setProgress() — устанавливает заданное значение индикатора прогресса;
- getProgress() — возвращает текущее значение индикатора прогресса;
- incrementProgressBy() — устанавливает величину дискретизации приращения значения индикатора;
- setMax() — устанавливает максимальное значение величины прогресса.
Горизонтальный индикатор обычно используют, чтобы показать индикатор в действии. При длительной операции пользователь видит, что полоска индикатора постоянно увеличивается.
Нужно задать верхнюю границу диапазона max и начальное значение progress и затем программно работать с этими данными.
Атрибут android:secondaryProgress=»50″ создаёт эффект буфера, когда рисуется ещё одна полоска, опережающая основной цвет. Ей можно управлять через метод setSecondaryProgress().
Отдельный поток
Выполнение длительных операций предпочтительнее производить в отдельном потоке. Android имеет специальный класс Handler для создания фоновых потоков и их взаимодействия с пользовательским интерфейсом. Либо используется AsyncTask и другие способы выполнения в другом потоке.
Запустим индикатор через кнопку.
Будем усыплять поток на небольшой промежуток времени.
Часто нужно выводить не круглое число 100, а что-то другое (размер файла). Тогда нужно сделать небольшие вычисления, чтобы выводились данные в процентах.
Допустим размер файла 365 Мб. Запускаем и смотрим — вся жизнь пробежала перед глазами, ну или год.
Пунктирный ProgressBar
Изменим обычную линию на пунктир. Создадим файл res/drawable/dash_progressbar.xml.
Подключим через атрибут progressDrawable.
Режим Indeterminate
Существует режим неопределённости (indeterminate), когда индикатор работает постоянно. Для этого нужно установить соответствующие атрибуты.
При запуске индикатор прогресса без всякого кода будет выводить бесконечную анимацию.
Переключение между режимами программно — метод setIndeterminate(boolean indeterminate).
Аккуратнее с атрибутом indeterminateOnly, если он будет установлен, то анимацию программно уже не приостановить. В этом случае просто не используйте атрибут. Несмотря на анимацию, индикатор по прежнему меняет свои показания. Если брать предыдущий пример с процентами и установить атрибуты, указанные выше (кроме indeterminateOnly), то программно можно остановить анимацию следующим образом.
Также часто используют изменение видимости — когда индикатор не нужен, его просто прячут.
Настройка через XML
Индикатор прогресса работает в стиле Material Design на Lollipop-устройствах и выше. На старых устройствах выводится другой цвет.
Можно задать свои настройки для цвета.
Для тонкой настройки компонента под себя следует использовать файл в ресурсах с использованием LayerDrawable. Файл ресурсов должен использовать системный идентификатор @android:id/background для фона, а также идентификатор @android:id/progress для самого индикатора. Также можно использовать ещё один необязательный идентификатор @android:id/secondaryProgress для дополнительного индикатора. Пример ниже.
Вертикальный индикатор прогресса
По умолчанию используется горизонтальный индикатор. Можно создать собственный индикатор с вертикальной ориентацией.
Рассмотрим пример с обычной вертикальной линией. Создадим файл res/drawable/vert_progressbar.xml.
Задействуем атрибут android:progressDrawable. Есть определённая сложность размещения компонента на экране. Хотя мы хотим видеть вертикальный индикатор, студия воспринимает его по-прежнему горизонтальным и в режиме дизайна отображает его соответствующим образом. Попробуем следующий вариант.
Код можно взять из примера с процентами. Там всё без изменений.
Вариант не слишком удобный, так как не интуитивен при визуальном размещении.
Другой вариант вертикального индикатора, который гораздо лучше справляется со своей задачей. Кроме того, индикатор будет не виде линии, а полноценным жирным прямоугольником. В папке res/drawable подготовим два файла:
verticalprogressbar.xml
verticalprogressbar2.xml
Разница между двумя файлами только в цвете, которым закрашивается индикатор во время работы. Я создал второй файл только для демонстрации программного изменения индикатора — когда значение индикатора достигнет отметки 50, то цвет поменяется на зелёный.
Код можно вставить после строчки из предыдущего примера:
Также можно использовать атрибут XML.
Круговые индикаторы прогресса
Несмотря на то, что компонент называется горизонтальным индикатором прогресса, мы уже изменили его на вертикальный. Но это не предел, мы можем сделать индикатор круговым.
Сначала покажу неудачный пример, который попался в интернете. Создадим файл res/drawable/circular_progressbar.xml.
Снова используем атрибут android:progressDrawable. Чтобы пример работал должным образом, нужно следить за размерами индикатора — ширина и высота должны быть одинаковыми. Если забыть об этом, то получим следующее.
Попробуем установить одинаковые размеры, а также добавить пунктир и градиент.
Для примера с обратным отсчётом я использовал индикатор с двумя drawable-ресурсами, используя shape с другими параметрами.
Индикатор с текстом
К сожалению, индикатор не выводит текст во время работы, что не очень удобно. Можно создать свой ProgressBar из TextView или создать свой компонент на основе ProgressBar. Другой простой способ — наложить текстовый блок прямо на индикатор, используя RelativeLayout. Пример для пояснения.
Код, чтобы увидеть работу индикатора. При каждом щелчке кнопки значение индикаторов увеличиваются на 10 процентов.
Программное создание индикатора
Данный способ уже устарел, так как через XML намного удобнее. Для общего развития.
Индикаторы прогресса также можно использовать в заголовках приложения у старых устройств, а также в ActionBar и ToolBar у новых устройств.
Компонент постоянно дорабатывается. Например, в Android 8 появились новые методы isAnimating(), getMin(), setMin().
Анимация ObjectAnimator
Можно подключить готовую анимацию для визуализации компонента.
Дополнительное чтение
Material ProgressBar — статья про создание собственного индикатора в стиле Material Design
Indeterminate — серия статей на тему создания индикаторов прогресса, ссылка на первую часть.
Источник
Заметки о 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-разработчикам будут интересны подобные примеры.
Источник