Здравствуйте, недавно мне понадобился 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.
