В этом уроке мы познакомимся с особенностями контейнера ViewFlipper
, а также напишем небольшое приложение с использованием ViewFlipper
. Следует отметить, что контейнер ViewFlipper в первую очередь создан для простой реализации слайдшоу или галереи, однако его очень удобно использовать в приложениях, где множество переходов и экранов (карточки больных со множеством форм ввода и т.п.).
Обзор контейнера ViewFlipper
Класс ViewFlipper
наследует базовый класс ViewAnimator
, который делает переходы между двумя или более дочерними View
. На экране может быть показан только один дочерний View, остальные же будут показаны по нажатию или по истечению заданного времени, после чего ViewFlipper
пролистает к следующему по иерархии объекту View.
Анимации в ViewFlipper
ViewFlipper поддерживает анимацию перехода с одного экрана на другой. Это делается с помощью методов setInAnimation()
и setOutAnimation()
, которые анимируют появление и затухание элементов View. Мы можем использовать анимацию по умолчанию Android системы или написать свой собственный класс анимации.
Переходы в ViewFlipper
Для контроля автоматического флипа (пролистывания) экранов приложения мы можем запускать и останавливать таймер на ViewFlipper контейнере. Управлять этим нам помогают методы startFlipping()
и stopFlipping()
, а также метод setFlipInterval()
, который устанавливает интервал между пролистыванием экранов внутри ViewFlipper
.
Явно вызывать следующий или предыдущий экран позволяют методы showNext()
и showPrevious()
контейнера ViewFlipper
.
Пример использования ViewFlipper в Android
Наше приложение будет состоять из 3х экранов. Мы сами будем обрабатывать события, связанные с переходами между экранами. Автоматический переход на следующий экран реализуется всего в одну строчку, а мы хотим попробовать как можно больше возможностей компонента ViewFlipper
.
1. Создание Android проекта
Первым делом создадим новый проект в Android Studio. Кто не знает как, то смотрим пример здесь.
2. Анимация переходов
Теперь идем в папку res и создаем папку ресурсов для анимации: res -> New -> Android Resource Directory:
Теперь создадим 4 новых xml файла Animation Resource File: res -> New -> Animation resource file:
Речь идет о 2 xml для анимации появления объекта View на экране и его ухода с экрана с левой стороны и такие же 2 анимации для появления/затухания с правой стороны:
Анимация появления слева left_in.xml
:
1 2 3 4 5 6 7 8 9 10 11 12 |
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" > <translate android:duration="500" android:fromXDelta="100%p" android:toXDelta="0" /> <alpha android:duration="500" android:fromAlpha="0.1" android:toAlpha="1.0" /> </set> |
Анимация ухода с экрана влево left_out.xml
:
1 2 3 4 5 6 7 8 9 10 11 12 |
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" > <translate android:duration="500" android:fromXDelta="0" android:toXDelta="-100%p" /> <alpha android:duration="500" android:fromAlpha="1.0" android:toAlpha="0.1" /> </set> |
Такие же анимации для появления/ухода с экрана в право:
Анимация right_in.xml
:
1 2 3 4 5 6 7 8 9 10 11 12 |
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" > <translate android:duration="500" android:fromXDelta="-100%p" android:toXDelta="0" /> <alpha android:duration="500" android:fromAlpha="0.1" android:toAlpha="1.0" /> </set> |
Анимация right_out.xml
:
1 2 3 4 5 6 7 8 9 10 11 12 |
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" > <translate android:duration="500" android:fromXDelta="0" android:toXDelta="100%p" /> <alpha android:duration="500" android:fromAlpha="1.0" android:toAlpha="0.1" /> </set> |
Вкратце о тегах анимации:
<set>
— контейнер, который может содержать другие элементы анимаций.<translate>
— описывает вертикальное или горизонтальное движение. В нашем случае, горизонтальное, потому что мы описывали изменения по оси Ox.<alpha>
определяет появления/затухания анимации.
3. Макет с контейнером ViewFlipper
Теперь можем приступить к разметке контейнера ViewFlipper
в макете activity_main.xml
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
<?xml version="1.0" encoding="utf-8"?> <ViewFlipper xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/vf_container" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="ua.com.prologistic.viewflippertestapp.MainActivity"> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:id="@+id/btn_previous_screen_1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_alignTop="@+id/btn_next_screen_1" android:text="Previous" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="1" android:textAppearance="?android:attr/textAppearanceLarge" android:layout_centerVertical="true" android:layout_centerHorizontal="true" /> <Button android:id="@+id/btn_next_screen_1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentEnd="true" android:layout_alignParentRight="true" android:layout_centerVertical="true" android:text="Next" /> </RelativeLayout> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:id="@+id/btn_previous_screen_2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_alignTop="@+id/btn_next_screen_2" android:text="Previous" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="2" android:textAppearance="?android:attr/textAppearanceLarge" android:layout_centerVertical="true" android:layout_centerHorizontal="true" /> <Button android:id="@+id/btn_next_screen_2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentEnd="true" android:layout_alignParentRight="true" android:layout_centerVertical="true" android:text="Next" /> </RelativeLayout> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:id="@+id/btn_previous_screen_3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_alignTop="@+id/btn_next_screen_3" android:text="Previous" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="3" android:textAppearance="?android:attr/textAppearanceLarge" android:layout_centerVertical="true" android:layout_centerHorizontal="true" /> <Button android:id="@+id/btn_next_screen_3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentEnd="true" android:layout_alignParentRight="true" android:layout_centerVertical="true" android:text="Next" /> </RelativeLayout> </ViewFlipper> |
Как видите, в контейнере ViewFlipper
3 дочерних RelativeLayout. в каждом из которых 2 виджета Button (следующий экран, TextView как индикатор текущего экрана и переход на предыдущий экран).
4. Управление контейнером ViewFlipper в коде
Теперь давайте опишем наши виджеты в классе MainActivity:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
package ua.com.prologistic.viewflippertestapp; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.Button; import android.widget.ViewFlipper; public class MainActivity extends AppCompatActivity { private View.OnClickListener mOnClickListener; private ViewFlipper mViewFlipper; // кнопки налево и направо первого экрана private Button mButtonPreviousScreen1; private Button mButtonNextScreen1; private Button mButtonPreviousScreen2; private Button mButtonNextScreen2; private Button mButtonPreviousScreen3; private Button mButtonNextScreen3; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mOnClickListener = new ClickListener(); mViewFlipper = (ViewFlipper) findViewById(R.id.vf_container); mButtonNextScreen1 = (Button) findViewById(R.id.btn_next_screen_1); mButtonPreviousScreen1 = (Button) findViewById(R.id.btn_previous_screen_1); mButtonNextScreen2 = (Button) findViewById(R.id.btn_next_screen_2); mButtonPreviousScreen2 = (Button) findViewById(R.id.btn_previous_screen_2); mButtonNextScreen3 = (Button) findViewById(R.id.btn_next_screen_3); mButtonPreviousScreen3 = (Button) findViewById(R.id.btn_previous_screen_3); mButtonPreviousScreen1.setOnClickListener(mOnClickListener); mButtonNextScreen1.setOnClickListener(mOnClickListener); mButtonPreviousScreen2.setOnClickListener(mOnClickListener); mButtonNextScreen2.setOnClickListener(mOnClickListener); mButtonPreviousScreen3.setOnClickListener(mOnClickListener); mButtonNextScreen3.setOnClickListener(mOnClickListener); } // перейти на предыдущий экран с анимацией справа налево private void showPreviousScreen() { // переход влево доступен только если мы не на первом экране if (!isFirst()) { mViewFlipper.setInAnimation(this, R.anim.right_in); mViewFlipper.setOutAnimation(this, R.anim.right_out); mViewFlipper.showPrevious(); } } // определяем, является ли текущий экран первым private boolean isFirst() { return mViewFlipper.getDisplayedChild() == 0; } // перейти на следующий экран с анимацией слева на право private void showNextScreen() { // переход вправо доступен только если мы не на последнем экране if (!isLast()) { mViewFlipper.setInAnimation(this, R.anim.left_in); mViewFlipper.setOutAnimation(this, R.anim.left_out); // переход вправо доступен mViewFlipper.showNext(); } } // определяем, является ли текущий экран последним private boolean isLast() { return mViewFlipper.getDisplayedChild() + 1 == mViewFlipper.getChildCount(); } private class ClickListener implements View.OnClickListener { @Override public void onClick(View view) { int id = view.getId(); if (id == R.id.btn_previous_screen_1) { showPreviousScreen(); } else if (id == R.id.btn_next_screen_1) { showNextScreen(); } else if (id == R.id.btn_previous_screen_2) { showPreviousScreen(); } else if (id == R.id.btn_next_screen_2) { showNextScreen(); } else if (id == R.id.btn_previous_screen_3) { showPreviousScreen(); } else if (id == R.id.btn_next_screen_3) { showNextScreen(); } } } } |
В коде мы определили кнопки, повешали слушатели и описали логику работу с контейнером ViewFlipper
.
Теперь запустим приложение и посмотрим что получилось:
Ограничения, указанные в методе showNext()
не дают нам пройти дальше третьего экрана. Такое же ограничение в методе showPrevious()
.
Под конец давайте рассмотрим другие атрибуты и возможности ViewFlipper
, которые Вы можете применить в текущем проекте:
- Атрибут
android:flipInterval
используется для задания интервала между автоматическим пролистыванием экранов внутри контейнера ViewFlipper. Задается в миллисекундах, например,android:flipInterval="3000"
. - Атрибут
android:autoStart
обозначает автоматический старт слайдшоу. Может принимать значенияtrue
илиfalse
. - Методы
startFlipping()
,stopFlipping()
,setFlipInterval(int milliseconds)
, отвечающие за старт слайдшоу, остановку слайдшоу и установку интервала между переходами соответственно.
Об остальных атрибутах и возможностях контейнера ViewFlipper
читайте в документации.
Скачать готовый Android проект можно по ссылке.