Статьи

Введение в переходы Android

Платформа переходов Android позволяет настраивать внешний вид изменений в пользовательском интерфейсе вашего приложения. Вы можете анимировать изменения на экране приложения, определяя каждую фазу как сцену и управляя тем, как переход изменяет внешний вид приложения с одной сцены на другую.

В этом уроке мы создадим простое приложение с анимированным переходом. Это потребует подготовки макета и отрисовки файлов в XML, а затем настройки и применения перехода в Java. Мы определим две сцены, в которых одни и те же элементы вида расположены на экране по-разному. Поскольку мы используем переход, Android автоматически оживит переход от одной сцены к другой.

Начните с создания нового приложения в выбранной вами IDE. Вам необходим минимум SDK 19 для классов переходов, поэтому вам нужно будет предпринять дополнительные шаги, если вы планируете поддерживать более старые версии.

Дайте приложению основной файл Activity и макет, выбрав для макета имя start_layout.xml . Позже мы добавим еще один файл макета, используя переход для перехода с одного на другой. На следующих изображениях показан процесс в Android Studio.

Давайте теперь подготовим несколько нарисованных фигур для использования в переходе. Мы будем использовать четыре формы круга с разноцветными градиентными заливками. В каталоге ресурсов drawables вашего приложения начните с создания нового файла с именем shape1.xml . Введите следующую форму:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
<?xml version=»1.0″ encoding=»utf-8″?>
<shape xmlns:android=»http://schemas.android.com/apk/res/android»
    android:dither=»true»
    android:shape=»oval» >
 
    <gradient
        android:endColor=»#66ff0000″
        android:gradientRadius=»150″
        android:startColor=»#ffffcc00″
        android:type=»radial»
        android:useLevel=»false» />
 
    <size
        android:height=»100dp»
        android:width=»100dp» />
 
</shape>

Форма представляет собой круг с радиальной градиентной заливкой. Все четыре формы будут одинаковыми, за исключением цветов, используемых в них. Возможно, вы захотите создать разные версии чертежей для разных плотностей устройства. Добавьте shape2.xml далее:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
<?xml version=»1.0″ encoding=»utf-8″?>
<shape xmlns:android=»http://schemas.android.com/apk/res/android»
    android:dither=»true»
    android:shape=»oval» >
 
    <gradient
        android:endColor=»#66ffcc00″
        android:gradientRadius=»150″
        android:startColor=»#ff00ff00″
        android:type=»radial»
        android:useLevel=»false» />
 
    <size
        android:height=»100dp»
        android:width=»100dp» />
 
</shape>

Теперь добавьте shape3.xml :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
<?xml version=»1.0″ encoding=»utf-8″?>
<shape xmlns:android=»http://schemas.android.com/apk/res/android»
    android:dither=»true»
    android:shape=»oval» >
 
    <gradient
        android:endColor=»#6600ff00″
        android:gradientRadius=»150″
        android:startColor=»#ff0000ff»
        android:type=»radial»
        android:useLevel=»false» />
 
    <size
        android:height=»100dp»
        android:width=»100dp» />
 
</shape>

Наконец добавьте shape4.xml :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
<?xml version=»1.0″ encoding=»utf-8″?>
<shape xmlns:android=»http://schemas.android.com/apk/res/android»
    android:dither=»true»
    android:shape=»oval» >
 
    <gradient
        android:endColor=»#660000ff»
        android:gradientRadius=»150″
        android:startColor=»#ffff0000″
        android:type=»radial»
        android:useLevel=»false» />
 
    <size
        android:height=»100dp»
        android:width=»100dp» />
 
</shape>

Мы будем использовать эти формы в качестве ImageButtons в двух сценах макета.

Давайте определим две сцены, между которыми мы перейдем, как макеты XML. Начните с основного файла макета, который вы добавили при создании приложения, start_layout.xml. Откройте его и переключитесь на вкладку редактирования XML. Используйте RelativeLayout как показано ниже:

1
2
3
4
5
6
7
8
9
<RelativeLayout xmlns:android=»http://schemas.android.com/apk/res/android»
    xmlns:tools=»http://schemas.android.com/tools»
    android:layout_width=»match_parent»
    android:layout_height=»match_parent»
    android:background=»#ff000000″
    android:id=»@+id/base»
    tools:context=».TransitionsActivity»>
 
</RelativeLayout>

Мы добавляем цвет фона и идентификатор для макета. Идентификатор важен для обеспечения перехода Android между вашими сценами, мы будем использовать тот же идентификатор во второй сцене. При переходе между двумя сценами Android будет анимировать изменения, если у каждого вида одинаковые идентификаторы в обеих сценах, в противном случае он будет обрабатывать представления как разные и просто затухать или исчезать при переходе.

Внутри RelativeLayout добавьте ImageButton для каждой фигуры, которую мы создали:

01
02
03
04
05
06
07
08
09
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
<ImageButton
    android:layout_width=»wrap_content»
    android:layout_height=»wrap_content»
    android:id=»@+id/btn1″
    android:src=»@drawable/shape1″
    android:background=»#00000000″
    android:contentDescription=»shape»
    android:layout_alignParentLeft=»true»
    android:layout_alignParentTop=»true»
    android:onClick=»changeScene»/>
 
<ImageButton
    android:layout_width=»wrap_content»
    android:layout_height=»wrap_content»
    android:id=»@+id/btn2″
    android:src=»@drawable/shape2″
    android:background=»#00000000″
    android:contentDescription=»shape»
    android:layout_alignParentRight=»true»
    android:layout_alignParentTop=»true»
    android:onClick=»changeScene»/>
 
<ImageButton
    android:layout_width=»wrap_content»
    android:layout_height=»wrap_content»
    android:id=»@+id/btn3″
    android:src=»@drawable/shape3″
    android:background=»#00000000″
    android:contentDescription=»shape»
    android:layout_alignParentLeft=»true»
    android:layout_alignParentBottom=»true»
    android:onClick=»changeScene»/>
 
<ImageButton
    android:layout_width=»wrap_content»
    android:layout_height=»wrap_content»
    android:id=»@+id/btn4″
    android:src=»@drawable/shape4″
    android:background=»#00000000″
    android:contentDescription=»shape»
    android:layout_alignParentRight=»true»
    android:layout_alignParentBottom=»true»
    android:onClick=»changeScene»/>

Обратите внимание, что каждая кнопка формы имеет идентификатор, который будет одинаковым во втором макете, который мы создаем, и атрибут onClick . Мы включим этот метод в основное действие позже и начнем переход, когда пользователь щелкнет любую из фигур.

Вы увидите предварительный просмотр макета в вашей IDE, хотя в некоторых случаях градиент и / или прозрачность не будут отображаться, пока вы не запустите приложение на устройстве или эмуляторе. Формы расположены в каждом углу экрана, как показано ниже.

Первый макет, который мы создали, будет представлять начало перехода. Давайте теперь создадим второй файл макета для сцены, на которую изменится переход. Добавьте новый файл в каталог ресурсов макета приложения, назвав его end_layout.xml . Перейдите на вкладку редактирования текста и введите следующее:

01
02
03
04
05
06
07
08
09
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
<RelativeLayout xmlns:android=»http://schemas.android.com/apk/res/android»
    xmlns:tools=»http://schemas.android.com/tools»
    android:layout_width=»match_parent»
    android:layout_height=»match_parent»
    android:background=»#ff000000″
    android:id=»@+id/base»
    tools:context=».TransitionsActivity»>
 
    <ImageButton
        android:layout_width=»wrap_content»
        android:layout_height=»wrap_content»
        android:id=»@+id/btn1″
        android:src=»@drawable/shape1″
        android:background=»#00000000″
        android:contentDescription=»shape»
        android:layout_alignParentRight=»true»
        android:layout_alignParentBottom=»true»
        android:onClick=»changeScene»/>
 
    <ImageButton
        android:layout_width=»wrap_content»
        android:layout_height=»wrap_content»
        android:id=»@+id/btn2″
        android:src=»@drawable/shape2″
        android:background=»#00000000″
        android:contentDescription=»shape»
        android:layout_alignParentLeft=»true»
        android:layout_alignParentBottom=»true»
        android:onClick=»changeScene»/>
 
    <ImageButton
        android:layout_width=»wrap_content»
        android:layout_height=»wrap_content»
        android:id=»@+id/btn3″
        android:src=»@drawable/shape3″
        android:background=»#00000000″
        android:contentDescription=»shape»
        android:layout_alignParentRight=»true»
        android:layout_alignParentTop=»true»
        android:onClick=»changeScene»/>
 
    <ImageButton
        android:layout_width=»wrap_content»
        android:layout_height=»wrap_content»
        android:id=»@+id/btn4″
        android:src=»@drawable/shape4″
        android:background=»#00000000″
        android:contentDescription=»shape»
        android:layout_alignParentLeft=»true»
        android:layout_alignParentTop=»true»
        android:onClick=»changeScene»/>
 
</RelativeLayout>

Найдите минутку, чтобы взглянуть на код макета. Он идентичен первому макету, за исключением расположения кнопок формы. Каждая фигура находится в противоположном углу от своей позиции в первом макете. Таким образом, переход поменяет местами фигуры, переместив их по диагонали по экрану.

Мы определили два макета, теперь давайте используем переход для перемещения между ними. Откройте основной класс Activity вашего приложения. Вам понадобятся следующие операторы импорта:

1
2
3
4
5
6
7
8
import android.transition.AutoTransition;
import android.transition.Scene;
import android.transition.Transition;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.widget.RelativeLayout;
import android.transition.TransitionManager;

В объявлении класса Activity перед методом onCreate добавьте следующие переменные экземпляра, которые мы будем использовать для применения перехода:

1
2
3
4
5
6
//scenes to transition
private Scene scene1, scene2;
//transition to move between scenes
private Transition transition;
//flag to swap between scenes
private boolean start;

Теперь давайте подготовимся к переходу, который начнется, когда пользователь щелкнет фигуру. В onCreate после того, как существующий код введен вашей IDE, добавьте следующее:

01
02
03
04
05
06
07
08
09
10
//get the layout ID
RelativeLayout baseLayout = (RelativeLayout)findViewById(R.id.base);
 
//first scene
ViewGroup startViews = (ViewGroup)getLayoutInflater()
    .inflate(R.layout.start_layout, baseLayout, false);
 
//second scene
ViewGroup endViews = (ViewGroup)getLayoutInflater()
    .inflate(R.layout.end_layout, baseLayout, false);

Сначала мы определяем базовую сцену, которая является идентификатором, который мы дали содержащему макету в обоих файлах макета сцены. Затем мы определяем две сцены, между которыми мы перемещаемся, определяя их имена файлов макета и содержащую базовую сцену. Это скажет Android, что мы хотим перенести представления в двух сценах, обрабатывая любое представление с одинаковым идентификатором в обеих сценах как один и тот же объект, так что это оживляет переход от одной сцены к другой.

Далее мы определяем две сцены, между которыми мы хотим перейти, все еще в onCreate :

1
2
3
//create the two scenes
scene1 = new Scene(baseLayout, startViews);
scene2 = new Scene(baseLayout, endViews);

Мы передаем базовый макет и соответствующие макеты сцены каждому конструктору. Теперь мы можем ссылаться на эти сцены при определении перехода.

Давайте подготовим переход, все еще в onCreate :

1
2
3
4
5
6
7
//create transition, set properties
transition = new AutoTransition();
transition.setDuration(5000);
transition.setInterpolator(new AccelerateDecelerateInterpolator());
 
//initialize flag
start=true;

В Android предусмотрено несколько типов переходов в зависимости от того, как анимируются изменения в ваших сценах. В этом случае мы выбираем AutoTransition , поэтому Android рассчитает, как внести изменения, основываясь на свойствах, которые изменяются между сценами. См. Переходы для получения дополнительной информации.

Устанавливаем длительность и интерполятор для перехода. При желании вы также можете установить задержку запуска для изменения. Наконец, мы инициализируем логический флаг как true. Для простоты мы будем использовать это для переключения между двумя сценами всякий раз, когда пользователь щелкает форму, но это просто для демонстрации задействованной функциональности.

Помните, что мы добавили атрибут onClick к кнопкам формы при создании XML-макета. Давайте теперь добавим этот метод в Activity :

01
02
03
04
05
06
07
08
09
10
11
12
public void changeScene(View v){
 
    //check flag
    if(start) {
        TransitionManager.go(scene2, transition);
        start=false;
    }
    else {
        TransitionManager.go(scene1, transition);
        start=true;
    }
}

Мы используем TransitionManager для перехода от текущей сцены к другой, с булевым флагом, отслеживающим, на каком мы находимся. Мы указываем объект Transition мы создали, чтобы адаптировать, как разворачивается изменение.

Теперь вы сможете запускать свое приложение и видеть переход всякий раз, когда вы нажимаете на фигуру. Каждый раз, когда вы щелкаете, переход должен медленно перемещать фигуры в противоположные углы, а затем снова менять их при повторном нажатии.

В этом уроке мы только начали изучать, что можно сделать с помощью платформы переходов Android. Для дальнейшего развития ваших переходов ознакомьтесь с дополнительными методами в классе TransitionManager , такими как beginDelayedTransition и transitionTo . Вы также можете использовать TransitionSet для объединения нескольких переходов, например, для настройки эффектов замирания и перемещения. В зависимости от сложности ваших переходов вы также можете воспользоваться классом TransitionValues , который предоставляет ссылку на значения данных, относящиеся к переходу. Чтобы узнать больше о том, что вы можете делать со сценами, посмотрите также класс Scene .