ViewPagerIndicator — индикатор для ViewPager

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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Ваш комментарий будет опубликован после модерации