Для тестирования возможностей добавления анимации в пользовательский интерфейс необходимо создать новый проект с макетом Empty Activity.
Откройте файл activity_main.xml и напишите этот код:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="16dp"
tools:context=".MainActivity">
<ImageView
android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerInParent="true"
android:src="@mipmap/ic_launcher" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:orientation="horizontal">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">
<Button
android:id="@+id/rotateX"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="animateOnClick"
android:text="Rotate X" />
<Button
android:id="@+id/rotateY"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="animateOnClick"
android:text="Rotate Y" />
<Button
android:id="@+id/rotateLeft"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="animateOnClick"
android:text="Rotate Left" />
<Button
android:id="@+id/rotateRight"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="animateOnClick"
android:text="Rotate Right" />
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">
<Button
android:id="@+id/translateX"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="animateOnClick"
android:text="Translate X" />
<Button
android:id="@+id/translateY"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="animateOnClick"
android:text="Translate Y" />
<Button
android:id="@+id/fadeIn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="animateOnClick"
android:text="Fade In" />
<Button
android:id="@+id/fadeOut"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="animateOnClick"
android:text="Fade Out" />
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">
<Button
android:id="@+id/zoomIn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="animateOnClick"
android:text="Zoom In" />
<Button
android:id="@+id/zoomOut"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="animateOnClick"
android:text="Zoom Out" />
<Button
android:id="@+id/animationsStart"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="animatorSet"
android:text="Animation Set" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>
Теперь откройте файл MainActivity.java и напишите следующий код:
public class MainActivity extends AppCompatActivity {
// Переменные для хранения ссылок кнопок для запуска соответствующих анимаций
Button rotateX;
Button rotateY;
Button rotateLeft;
Button rotateRight;
Button translateX;
Button translateY;
Button fadeIn;
Button fadeOut;
Button zoomIn;
Button zoomOut;
ImageView image;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Получение ссылок к переменным в файле макета
image = findViewById(R.id.image);
rotateX = findViewById(R.id.rotateX);
rotateY = findViewById(R.id.rotateY);
rotateLeft = findViewById(R.id.rotateLeft);
rotateRight = findViewById(R.id.rotateRight);
translateX = findViewById(R.id.translateX);
translateY = findViewById(R.id.translateY);
fadeIn = findViewById(R.id.fadeIn);
fadeOut = findViewById(R.id.fadeOut);
zoomIn = findViewById(R.id.zoomIn);
zoomOut = findViewById(R.id.zoomOut);
}
// Функция установлена в качестве значения атрибута onclick для кнопок в файле макета
public void animateOnClick(View view) {
// Перебрать id нажатой кнопки для определения какая кнопка была нажата
switch (view.getId()) {
// Если id нажатой кнопки равен id кнопки вращения по оси Х
case R.id.rotateX:
// Применить анимацию вращения по оси Х равную 360 градусам с продолжительностью 1000 миллисекунд (1 секунда) и установить слушатель анимации, который имеет функции вызывающиеся при запуске, окончании и повторе анимации также для анимации устанавливается интерполятор LinearInterpolator, который меняет значение линейно (без скачков)
image.animate().rotationX(360).setDuration(1000).setListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
image.setRotationX(0);
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
}).setInterpolator(new LinearInterpolator()).start();
break;
// Анимация для вращения по оси Y
case R.id.rotateY:
// Начиная от этой анимации используется другой метод анимирования, который отличается механизмом анимирования. ValueAnimator анимирует не виджет а только указанные значения затем эти значения могут быть использованы как угодно, в данном примере анимированные значения служат для применения анимации объекту image, значения анимируются от 0 до 360, setRepeatMode - устанавливает режим повтора, ValueAnimator.RESTART указывает, что после изменения значения от 0 до 360 значение обнулялось и снова менялось от 0 до 360. ValueAnimator.REVERSE - указывает что значение должно меняться с 0 до 360 и обратно с 360 до 0, setRepeatCount - устанавливает количество повторов анимации, setDuration - устанавливает продолжительность анимации, длиной в 1 секунду (1000 миллисекунд), addUpdateListener - устанавливает обработчик для события обновления анимированного значения, затем в функции onAnimationUpdate получив анимированное значение устанавливается новое значение для вращения объекта image по оси Y. Затем через функцию start запускается анимация.
ValueAnimator va = ValueAnimator.ofInt(0, 360);
va.setRepeatMode(ValueAnimator.RESTART);
va.setRepeatCount(5);
va.setDuration(1000);
va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
image.setRotationY((int) animation.getAnimatedValue());
}
});
va.start();
break;
// Код для кнопки вращения влево
case R.id.rotateLeft:
// В данном случае получаем значение текущего вращения объекта по оси Z, затем для вращения влево надо указать текущее значение - 45 градусов текущее значение вращения получаем через функцию image.getRotation()
ValueAnimator rotateLeft = ValueAnimator.ofFloat(image.getRotation(), image.getRotation() - 45);
rotateLeft.setDuration(250).addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
image.setRotation((float) animation.getAnimatedValue());
}
});
rotateLeft.start();
break;
// Код для кнопки вращения вправо
case R.id.rotateRight:
// Код аналогичен коду вращения влево, единственно отличается тем что надо указать текущее значение вращения + 45 градусов
ValueAnimator rotateRight = ValueAnimator.ofFloat(image.getRotation(), image.getRotation() + 45);
rotateRight.setDuration(250).addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
image.setRotation((float) animation.getAnimatedValue());
}
});
rotateRight.start();
break;
// Анимация translate служит для изменения местоположения объекта по указанной оси
case R.id.translateX:
// Создать объект анимации для анимирования значения перемещения объекта по оси X меняет значение оси X с нуля до 200. 0 - текущее местоположение.
ValueAnimator tX = ValueAnimator.ofFloat(0, 200);
tX.setRepeatMode(ValueAnimator.REVERSE);
tX.setRepeatCount(1);
tX.setInterpolator(new AnticipateInterpolator());
tX.setDuration(250).addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
image.setTranslationX((float) animation.getAnimatedValue());
}
});
tX.start();
break;
case R.id.translateY:
ValueAnimator tY = ValueAnimator.ofFloat(0, 400);
tY.setRepeatMode(ValueAnimator.REVERSE);
tY.setRepeatCount(1);
tY.setInterpolator(new BounceInterpolator());
tY.setDuration(1000).addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
image.setTranslationY((float) animation.getAnimatedValue());
}
});
tY.start();
break;
// Анимация для плавного появления
case R.id.fadeIn:
// Анимирование плавного появления и исчезновения достигается путём изменения значения alpha (прозрачности) объекта, setAlpha(0) - делает объект невидимым, setAlpha(1) - делает объект полностью видимым, полупрозрачность устанавливается значением больше 0 и меньше 1, например 0.5
ValueAnimator fi = ValueAnimator.ofFloat(0, 1);
fi.setDuration(500).addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
image.setAlpha((float) animation.getAnimatedValue());
}
});
fi.start();
break;
// Анимация для плавного исчезновения меняет значение объекта с непрозрачного 1 до прозрачного 0
case R.id.fadeOut:
ValueAnimator fo = ValueAnimator.ofFloat(1, 0);
fo.setDuration(500).addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
image.setAlpha((float) animation.getAnimatedValue());
}
});
fo.start();
break;
// Увеличение и уменьшение размеров объекта
case R.id.zoomIn:
// Увеличение и уменьшение размеров объекта указывается через масштаб - scale объекта, по умолчанию объект имеет масштаб равный 1 в данной анимации масштаб увеличивается с 1 до 3, точнее в три раза становится больше в качестве интерполятора используется CycleInterpolator, который циклически меняет значение с 1 до 3, затем обратно и повторяет это 3 раза для пропорционального изменения масштаба необходимо установить масштаб как для оси Х так и для Y
ValueAnimator zi = ValueAnimator.ofFloat(1, 3);
zi.setInterpolator(new CycleInterpolator(3));
zi.setDuration(3000).addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
image.setScaleX((float) animation.getAnimatedValue());
image.setScaleY((float) animation.getAnimatedValue());
}
});
zi.start();
break;
// Уменьшение масштаба объекта
case R.id.zoomOut:
// Для отдаления объекта используется уменьшение масштаба можно использовать значения меньше 1, например 0.5 (половина масштаба) 0.25 (четверть масштаба) и т.д.
ValueAnimator zo = ValueAnimator.ofFloat(3, 1);
zo.setDuration(300).addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
image.setScaleX((float) animation.getAnimatedValue());
image.setScaleY((float) animation.getAnimatedValue());
}
});
zo.start();
break;
}
}
// Функция служит для создания анимаций и их запуска в определенной очереди
public void animatorSet(View view) {
ValueAnimator rotateLeft = ValueAnimator.ofFloat(image.getRotation(), image.getRotation() - 45);
rotateLeft.setDuration(250).addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
image.setRotation((float) animation.getAnimatedValue());
}
});
ValueAnimator fi = ValueAnimator.ofFloat(0, 1);
fi.setDuration(500).addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
image.setAlpha((float) animation.getAnimatedValue());
}
});
ValueAnimator zi = ValueAnimator.ofFloat(1, 3);
zi.setDuration(3000).addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
image.setScaleX((float) animation.getAnimatedValue());
image.setScaleY((float) animation.getAnimatedValue());
}
});
ValueAnimator rY = ValueAnimator.ofInt(0, 360);
rY.setRepeatMode(ValueAnimator.RESTART);
rY.setRepeatCount(5);
rY.setDuration(1000);
rY.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
image.setRotationY((int) animation.getAnimatedValue());
}
});
// Класс AnimatorSet служит для создания очереди анимаций. Запускать анимации можно одновременно (with), одну анимацию до другой (before), одну анимацию после другой анимации или после указанного интервала времени (after)
AnimatorSet animations = new AnimatorSet();
animations.play(fi).with(zi);
animations.play(zi).with(rotateLeft);
animations.play(rY).after(3000);
animations.start();
}
}
Теперь запустите приложение и посмотрите как работает анимация.
Реклама