Освой Android играючи
/* Моя кошка замечательно разбирается в программировании. Стоит мне объяснить проблему ей - и все становится ясно. */
John Robbins, Debugging Applications, Microsoft Press, 2000
Основы
Стилизация
Индикатор с текстом
Программное создание индикатора
Компонент ProgressBar (Индикатор прогресса) применяется в тех случаях, когда пользователю нужно показать, что программа не зависла, а выполняет продолжительную работу.
Находится в категории Widgets.
Студия предлагает несколько видов индикаторов: ProgressBar и ProgressBar (Horizontal). В свою очередь компонент имеет несколько модификаций и их отличия заложены в стилях, если посмотреть XML-описание компонентов. Стили постоянно меняются, поэтому проще выбрать атрибут style и посмотреть предлагаемые варианты из выпадающего списка на текущий момент.
Методы для работы с ProgressBar:
Круговые индикаторы Normal, Small и Large можно просто разместить на экране, и они будут бесконечно выводить анимацию вращения без единой строчки кода.
Как правило, "бесконечный" индикатор выводят в нужный момент, а когда задача выполнена, то его скрывают. Видимость можно установить через XML и программно.
<ProgressBar
android:id="@+id/progressBar"
android:visibility="invisible"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
В коде используется метод setVisibility()
ProgressBar progressBar = (ProgressBar) findViewById(R.id.progressBar);
progressBar.setVisibility(ProgressBar.VISIBLE);
// запускаем длительную операцию
progressBar.setVisibility(ProgressBar.INVISIBLE);
Сейчас проекты в студии используют Material Design, поэтому цвет индикатора будет соответствовать ресурсу colorAccent.
Можно переопределить цвет, если вы хотите отказаться от этой связи с colorAccent, задав свой стиль.
<style name="CircularProgress" parent="Theme.AppCompat.Light">
<item name="colorAccent">@android:color/holo_green_light</item>
</style>
Подключаем через тему.
<ProgressBar
...
android:theme="@style/CircularProgress" />
Другая настройка связана с Tint - оттенками цвета (Android 5.0).
<ProgressBar
android:indeterminateTintMode="src_in"
android:indeterminateTint="@color/my_color"/>
Если вам не нравится внешний вид стандартных индикаторов, то можете придумать свой. Есть два варианта для реализации этой цели. В первом случае можно подготовить готовый png-файл (spin_custom.png) и поместить его в ресурс, например, в папку res/drawable.
Затем в этой же папке создаём xml-файл spinner_png.xml с таким содержанием:
<?xml version="1.0" encoding="utf-8"?>
<animated-rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/spin_custom"
android:pivotX="50%"
android:pivotY="50%" />
Теперь в разметке активности можно определять ProgressBar так:
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminateDrawable="@drawable/spinner_png"
android:indeterminateOnly="true" />
Если запустить проект, то увидим такой индикатор:
В реальности индикатор выглядит немного корявым, подёргиваясь на экране. Кроме того, изображение можно улучшить, уменьшив количество цветов и сократив размер файла.
Второй вариант выглядит предпочтительней. На этот раз мы обойдёмся без графических файлов, а будем использовать только XML-разметку. В этой же папке поместим файл spinner_ring.xml следующего содержания:
<?xml version="1.0" encoding="utf-8"?>
<animated-rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:pivotX="50%"
android:pivotY="50%" >
<shape
android:innerRadiusRatio="4"
android:shape="ring"
android:thicknessRatio="5.333"
android:useLevel="false" >
<size
android:height="18dip"
android:width="18dip" />
<gradient
android:centerColor="#886688cc"
android:centerY="0.50"
android:endColor="#ff6688cc"
android:startColor="#006688cc"
android:type="sweep"
android:useLevel="false" />
</shape>
</animated-rotate>
Теперь в разметке активности пропишем строки:
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dip"
android:indeterminateDrawable="@drawable/spinner_ring"
android:indeterminateOnly="true" />
Получим следующий результат:
К сожалению, индикатор не выводит текст во время работы, что не очень удобно. Можно создать свой ProgressBar из TextView или создать свой компонент на основе ProgressBar. Другой простой способ - наложить текстовый блок прямо на индикатор, используя RelativeLayout. Пример для пояснения.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<RelativeLayout
android:id="@+id/rl_progress_bar_set"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/btn_start"
android:visibility="visible" >
<ProgressBar
android:id="@+id/pb_horizontal"
style="@android:style/Widget.ProgressBar.Horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:max="100" />
<TextView
android:id="@+id/tv_progress_horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignBottom="@id/pb_horizontal"
android:background="@android:color/transparent"
android:gravity="center" />
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@id/pb_horizontal"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="10dp" >
<ProgressBar
style="@android:style/Widget.ProgressBar.Large"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:background="@android:color/background_dark" />
<TextView
android:id="@+id/tv_progress_circle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:background="@android:color/transparent"
android:gravity="center"
android:textColor="@android:color/white" />
</RelativeLayout>
</RelativeLayout>
<Button
android:id="@+id/btn_start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="15dp"
android:onClick="onClick"
android:text="Поехали"
android:textSize="25dp" />
</RelativeLayout>
Код, чтобы увидеть работу индикатора. При каждом щелчке кнопки значение индикаторов увеличиваются на 10 процентов.
package ru.alexanderklimov.test;
import ...
public class MainActivity extends Activity {
private int progress = 0;
private ProgressBar pbHorizontal;
private TextView tvProgressHorizontal;
private TextView tvProgressCircle;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pbHorizontal = (ProgressBar) findViewById(R.id.pb_horizontal);
tvProgressHorizontal = (TextView) findViewById(R.id.tv_progress_horizontal);
tvProgressCircle = (TextView)findViewById(R.id.tv_progress_circle);
}
public void onClick(View v) {
progress = progress + 10;
postProgress(progress);
}
private void postProgress(int progress) {
String strProgress = String.valueOf(progress) + " %";
pbHorizontal.setProgress(progress);
if (progress == 0) {
pbHorizontal.setSecondaryProgress(0);
} else {
pbHorizontal.setSecondaryProgress(progress + 5);
}
tvProgressHorizontal.setText(strProgress);
tvProgressCircle.setText(strProgress);
}
}
Индикаторы прогресса также можно использовать в заголовках приложения у старых устройств, а также в ActionBar и ToolBar у новых устройств.
Компонент постоянно дорабатывается. Например, в Android 8 появились новые методы isAnimating(), getMin(), setMin().
Можно подключить готовую анимацию для визуализации компонента.
private static final TimeInterpolator GAUGE_ANIMATION_INTERPOLATOR = new DecelerateInterpolator(2);
private static final int MAX_LEVEL = 100;
private static final long GAUGE_ANIMATION_DURATION = 5000;
private ProgressBar mProgressBar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mProgressBar = findViewById(R.id.progressBar);
}
// По щелчку кнопки
public void onClick(View view) {
ObjectAnimator animator = ObjectAnimator.ofInt(mProgressBar, "progress", 0, MAX_LEVEL);
animator.setInterpolator(GAUGE_ANIMATION_INTERPOLATOR);
animator.setDuration(GAUGE_ANIMATION_DURATION);
animator.start();
}
Меняем стандартный индикатор через drawable - простой и быстрый способ.
Material ProgressBar - статья про создание собственного индикатора в стиле Material Design
Indeterminate - серия статей на тему создания индикаторов прогресса, ссылка на первую часть.
How to create your own progressBar in Android. – Medium
Make an android custom view, publish and open source.
skydoves/ProgressView: A polished and flexible ProgressView, fully customizable with animations.
GitHub - nipun-birla/BoxLoaderView
GitHub - VladimirWrites/Lemniscate: An easy way to make your progress view nice and sleek.
yuriy-budiyev/circular-progress-bar: Circular progress bar
JustZak/DilatingDotsProgressBar: A customizable indeterminate progress bar
DreaminginCodeZH/MaterialProgressBar: Material Design ProgressBar with consistent appearance
passsy/android-HoloCircularProgressBar
lsjwzh/MaterialLoadingProgressBar
amanjeetsingh150/CoolProgressViews: Android library with collection of cool progress views.
glomadrian/loading-balls: A highly configurable library to do loading progress with animated balls - анимация для длительных операций.
droidchef/tinglingsquares: A delightful progress animation
Индикатор прогресса в виде пирога. Домашняя страница FilipPudak/ProgressPieView
biodunalfet/SlidingSquaresLoader: A simple progress loader