Здравствуйте, недавно мне понадобился ViewPager с индикатором. После продолжительных поисков была найдена очень функциональная библиотека — ViewPagerIndicator.
Автор библиотеки — довольно известный в кругах Android-разработчиков Jake Wharton. Также он занимается разработкой ActionBarSherlock, Picasso, Retrofit и многих других интересных библиотек. Вернемся к нашим баранам.
ViewPagerIndicator предлагает 6 разных типов индикаторов. Если вам не понравится стандартный стиль вы можете изменить его. Так как видов индикаторов много и нужно рассмотреть подробно каждый, то я разобью статью на несколько частей.
Предварительная настройка
Для того, чтобы начать пользоваться библиотекой нужно скачать ее с Github и подключить к проекту. Как это сделать подробно описано здесь.
1. CirclePageIndicator
Начнем, пожалуй, с самого простого типа индикаторов — кружков.
main.xml:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical"> <android.support.v4.view.ViewPager android:id="@+id/pager" android:layout_width="fill_parent" android:layout_height="0dp" android:layout_weight="1"> <com.viewpagerindicator.CirclePageIndicator android:id="@+id/indicator" android:layout_width="fill_parent" android:layout_height="wrap_content" android:padding="10dip"> </LinearLayout>
CirclePageIndicator — это и есть наш индикатор. Ничего сложного нет. Инициализируем элементы в активити.
MainActivity.java:
package ru.javahelp.viewpagerindicator; import android.app.Activity; import android.os.Bundle; import android.support.v4.view.ViewPager; import com.viewpagerindicator.CirclePageIndicator; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); chbDefaultCircleIndicatorSnap = (CheckBox) findViewById(R.id.chbDefaultCircleIndicatorSnap); chbDefaultCircleIndicatorSnap.setOnCheckedChangeListener(onCheckedChange); ViewPager viewPager = (ViewPager)findViewById(R.id.pager); ViewPagerAdapter viewPagerAdapter = new ViewPagerAdapter(this); viewPager.setAdapter(viewPagerAdapter); CirclePageIndicator circleIndicator = (CirclePageIndicator)findViewById(R.id.indicator); circleIndicator.setViewPager(viewPager); } }
С помощью метода setViewPager(ViewPager) мы как бы «привязываем» индикатор к определенному ViewPager.
ViewPagerAdapter:
package ru.javahelp.viewpagerindicator; import android.content.Context; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; public class ViewPagerAdapter extends PagerAdapter { Context context; int count = 5; public ViewPagerAdapter(Context context) { this.context = context; } @Override public int getCount() { return count; } public void setCount(int count) { if(count<10){ this.count = count; } } @Override public Object instantiateItem(ViewGroup container, int position) { TextView tv = new TextView(context); tv.setText("Позиция " + position); ViewPager viewPager = (ViewPager) container; viewPager.addView(tv, 0); return tv; } @Override public void destroyItem(ViewGroup container, int position, Object object) { ((ViewPager) container).removeView((TextView) object); } @Override public boolean isViewFromObject(View arg0, Object arg1) { return arg0 == ((View) arg1); } }
В переменной COUNT указываем количество страниц ViewPager’а. При каждом вызове метода getView создаем новый TextView и присваиваем ему текст с номер позиции.
Чтобы сделать переход индикатора резким (без плавного перелезания с одного кружка на другой) нужно вызвать метод setSnap(boolean) у индикатора и передать ему true.
circleIndicator.setSnap(true);
Добавляем элементы
Если в процессе выполнения программы во ViewPager добавляются или удаляются элементы, то необходимо вызвать метод notifyDataSetChanged() у индикатора, чтобы индикатор обновил свои данные.
circleIndicator.notifyDataSetChanged();
Стилизуем индикатор
Наверное не всем может понравиться стандартный стиль индикатора. Автор библиотеки предусмотрел это и добавил возможность кастомизации внешнего вида индикаторов. Изменить вид индикаторов можно как с помощью XML, так и программно.
Стилизуем с помощью XML:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical"> <android.support.v4.view.ViewPager android:id="@+id/pager" android:layout_width="fill_parent" android:layout_height="0dp" android:layout_weight="1"> <com.viewpagerindicator.CirclePageIndicator android:id="@+id/indicator" android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="#FFCCCCCC" android:padding="10dip" app:fillColor="#FF888888" app:pageColor="#88FF0000" app:radius="10dp" app:strokeColor="#FF000000" app:strokeWidth="2dp"> </LinearLayout>
Разберем атрибуты CirclePageIndicator с префиксом app:
fillColor — цвет неактивных индикаторов
pageColor — цвет индикатора текущей страницы
radius — размер кружков
strokeColor — цвет обводки индикатора
strokeWidth — толщина обводки индикатора
Теперь сделаем то же самое, но программно:
float density = getResources().getDisplayMetrics().density; circleIndicator.setBackgroundColor(0xFFCCCCCC); circleIndicator.setRadius(10 * density); circleIndicator.setPageColor(0x880000FF); circleIndicator.setFillColor(0xFF888888); circleIndicator.setStrokeColor(0xFF000000); circleIndicator.setStrokeWidth(2 * density);
Я не буду писать, что делает каждый метод, а проведу аналогию с XML-атрибутами представленными выше:
setBackgroundColor(int) — fillColor.
setRadius(float) — radius.
setPageColor(int) — pageColor.
setFillColor(int) — fillColor.
setStrokeColor(int) — strokeColor.
setStrokeWidth(float) — strokeWidth.
2. LinePageIndicator
LinePageIndicator — индикатор в виде полосок.
main.xml:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical"> <android.support.v4.view.ViewPager android:id="@+id/pager" android:layout_width="fill_parent" android:layout_height="0dp" android:layout_weight="1"> <com.viewpagerindicator.LinePageIndicator android:id="@+id/indicator" android:layout_width="fill_parent" android:layout_height="wrap_content" android:padding="10dip"> </LinearLayout>
MainActivity.java:
package ru.javahelp.viewpagerindicator; import android.app.Activity; import android.os.Bundle; import android.support.v4.view.ViewPager; import com.viewpagerindicator.LinePageIndicator; public class MainActivity extends Activity { ViewPagerAdapter viewPagerAdapter; ViewPager viewPager; LinePageIndicator linePageIndicator; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.lines_default); viewPagerAdapter = new ViewPagerAdapter(this); viewPager = (ViewPager)findViewById(R.id.pager); viewPager.setAdapter(viewPagerAdapter); linePageIndicator = (LinePageIndicator)findViewById(R.id.indicator); linePageIndicator.setViewPager(viewPager); } }
Пока все точно та же как и у CirclePageIndicator, отличаются только имена классов.
Теперь, попробуем изменить внешний вид индикаторов. Делать мы это будем, опять же, через XML и программно.
Стилизуем с помощью XML:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical"> <android.support.v4.view.ViewPager android:id="@+id/pager" android:layout_width="fill_parent" android:layout_height="0dp" android:layout_weight="1"> <com.viewpagerindicator.LinePageIndicator android:id="@+id/indicator" android:layout_width="fill_parent" android:layout_height="wrap_content" android:padding="10dip" app:strokeWidth="4dp" app:lineWidth="30dp" app:unselectedColor="#FF888888" app:selectedColor="#FF880000"> </LinearLayout>
strokeWidth — толщина линии-индикатора
lineWidth — ширина линии-индикатора
unselectedColor — цвет неактивного индикатора
selectedColor — цвет индикатора текущей страницы
Стилизуем программно:
package ru.javahelp.viewpagerindicator; import android.app.Activity; import android.os.Bundle; import android.support.v4.view.ViewPager; import com.viewpagerindicator.LinePageIndicator; public class LinesThemedJava extends Activity { ViewPagerAdapter viewPagerAdapter; ViewPager viewPager; LinePageIndicator linePageIndicator; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.lines_themed_java); viewPagerAdapter = new ViewPagerAdapter(this); viewPager = (ViewPager) findViewById(R.id.pager); viewPager.setAdapter(viewPagerAdapter); linePageIndicator = (LinePageIndicator) findViewById(R.id.indicator); linePageIndicator.setViewPager(viewPager); final float density = getResources().getDisplayMetrics().density; linePageIndicator.setSelectedColor(0x88FF0000); linePageIndicator.setUnselectedColor(0xFF888888); linePageIndicator.setStrokeWidth(4 * density); linePageIndicator.setLineWidth(30 * density); } }
Точно та же приведу аналоги методов в XML:
setSelectedColor(int) — selectedColor
setUnselectedColor(int) — unselectedColor
setStrokeWidth(float) — strokeWidth
setLineWidth(float) — lineWidth
3. UnderlinePageIndicator
Underline PageIndicator — индикатор в виде полоски, нахадящейся в самом низу экрана.
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical"> <android.support.v4.view.ViewPager android:id="@+id/pager" android:layout_width="fill_parent" android:layout_height="0dp" android:layout_weight="1"> <com.viewpagerindicator.UnderlinePageIndicator android:id="@+id/indicator" android:layout_width="fill_parent" android:layout_height="2dp"> </LinearLayout>
MainActivity.java:
package ru.javahelp.viewpagerindicator; import android.app.Activity; import android.os.Bundle; import android.support.v4.view.ViewPager; import com.viewpagerindicator.UnderlinePageIndicator; public class UnderlineDefault extends Activity { ViewPagerAdapter viewPagerAdapter; ViewPager viewPager; UnderlinePageIndicator underlinePageIndicator; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.underline_default); viewPagerAdapter = new ViewPagerAdapter(this); viewPager = (ViewPager)findViewById(R.id.pager); viewPager.setAdapter(viewPagerAdapter); underlinePageIndicator = (UnderlinePageIndicator)findViewById(R.id.indicator); underlinePageIndicator.setViewPager(viewPager); } }
Стилизуем с помощью XML:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <android.support.v4.view.ViewPager android:id="@+id/pager" android:layout_width="fill_parent" android:layout_height="0dp" android:layout_weight="1"> <com.viewpagerindicator.UnderlinePageIndicator android:id="@+id/indicator" android:layout_height="2dp" android:layout_width="fill_parent" android:background="#FFCCCCCC" app:selectedColor="#FFCC0000" app:fadeDelay="1000" app:fadeLength="1000"> </LinearLayout>
selectedColor — цвет активного индикатора
fadeDelay — без понятия
fadeLength — без понятия
Стилизуем программно:
package ru.javahelp.viewpagerindicator; import android.app.Activity; import android.os.Bundle; import android.support.v4.view.ViewPager; import com.viewpagerindicator.UnderlinePageIndicator; public class UnderlineThemedJava extends Activity{ ViewPagerAdapter viewPagerAdapter; ViewPager viewPager; UnderlinePageIndicator underlinePageIndicator; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.underline_themed_java); viewPagerAdapter = new ViewPagerAdapter(this); viewPager = (ViewPager)findViewById(R.id.underline_themed_java_pager); viewPager.setAdapter(viewPagerAdapter); underlinePageIndicator = (UnderlinePageIndicator)findViewById(R.id.underline_themed_java_indicator); underlinePageIndicator.setViewPager(viewPager); underlinePageIndicator.setSelectedColor(0xFFCC0000); underlinePageIndicator.setBackgroundColor(0xFFCCCCCC); underlinePageIndicator.setFadeDelay(1000); underlinePageIndicator.setFadeLength(1000); } }
setSelectedColor(int) — selectedColor
setFadeDelay(int) — fadeDelay
setFadeLength(int) — fadeLength
Библиотека на GitHub: ViewPagerIndicator.
Исходники примера: ViewPagerIndicator.