Создадим полноэкранное приложение, как показано в уроке:
Создание полноэкранного приложения в Android Studio
Наше приложение будет работать по следующему принципу:
На каждом шаге прорисовки (onDraw(Canvas)) получаем переменную curTime, которая будет хранить текущее время. В зависимости от ее значения, объекты, которые мы рисуем, меняют свои положение и свойства. Под конец метода прорисовки вызываем invalidate(), который заставляет MyView вызвать функцию прорисовки заново.
MyView:
package me.graphica.canvasanimation; import android.animation.ArgbEvaluator; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.view.View; public class MyView extends View { private final int CIRCLE_COUNT = 20; //количество окружностей private final float CIRCLE_ANIMATION = 0.5f; //величина поворота окружностей на каждый кадр private final long RECT_ANIMATION = 1_000; //длительность анимации прямоугольника = 1 секунда private final long COLOR_ANIMATION = 1_000; //длительность анимации смены цветов = 1 секунда private int mWidth; //ширина view private int mHeight; //высота view private Paint mCirclePaint; private Paint mRectPaint; private ArgbEvaluator mArgbEvaluator; //класс для анимации смены цветов private long mStartTime; //время начала анимации private float mCircleDegree; //текущий угол поворота окружностей public MyView(Context context) { super(context); mCirclePaint = new Paint(); mCirclePaint.setAntiAlias(true); mCirclePaint.setColor(Color.WHITE); mCirclePaint.setStyle(Paint.Style.FILL); mRectPaint = new Paint(mCirclePaint); mRectPaint.setColor(Color.RED); mArgbEvaluator = new ArgbEvaluator(); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { //вызывается при изменении размера view mWidth = w; //запоминаем ширину view mHeight = h; //запоминаем высоту view mStartTime = getTime(); //начинаем отсчет времени } private long getTime() { //возвращает текущее время в миллисекундах return System.nanoTime() / 1_000_000; } @Override protected void onDraw(Canvas canvas) { colorAnimation(canvas); //демонстрация анимации цвета rotateAnimation(canvas); //демонстрация анимации поворота moveAnimation(canvas); //демонстрация анимации движения invalidate(); //заставляет перерисовывать view, пока view находится в поле зрения пользователя } private void rotateAnimation(Canvas canvas) { canvas.save(); //запоминаем текущее состояние canvas int centerX = mWidth / 2; int centerY = mHeight / 2; canvas.translate(centerX, centerY); //рисуем окружности вокруг центра view mCircleDegree += CIRCLE_ANIMATION; // += 0.5f canvas.rotate(mCircleDegree); //устанавливаем угол поворота int rad = Math.min(mWidth, mHeight) / 4; //расстояние между противоположными окружностями int cir_rad = rad / 12; //радиус самих окружностей for (int i = 0; i < CIRCLE_COUNT; i++) { //вычисляет положение и рисует 20 окружностей double t = (2 * Math.PI / CIRCLE_COUNT) * i; double x = rad * Math.cos(t); double y = rad * Math.sin(t); canvas.drawCircle((float) x, (float) y, cir_rad, mCirclePaint); } canvas.restore(); //восстанавливаем canvas } private void moveAnimation(Canvas canvas) { canvas.save(); float rectWidth = mWidth / 10; float rectHeight = mHeight / 10; long curTime = getTime() - mStartTime; //время с момента начала анимации в мс float fraction = (float) (curTime % RECT_ANIMATION) / RECT_ANIMATION; //дробь от 0 до 1, где 0 - начало анимации, 1 - ее завершение if ((curTime / RECT_ANIMATION) % 2 == 1) fraction = 1 - fraction; //делает обратную анимацию, если она завершилась canvas.translate((mWidth - rectWidth) * fraction, mHeight - rectHeight); canvas.drawRect(0, 0, rectWidth, rectHeight, mRectPaint); canvas.restore(); } private void colorAnimation(Canvas canvas) { long curTime = getTime() - mStartTime; float fraction = (float) (curTime % COLOR_ANIMATION) / COLOR_ANIMATION; if ((curTime / COLOR_ANIMATION) % 2 == 1) fraction = 1 - fraction; int color = (int) mArgbEvaluator.evaluate(fraction, Color.BLACK, Color.GREEN); //evaluate вычислаяет промежуточный цвет между двумя цветами //в зависимоти от fraction = [0, 1] canvas.drawColor(color); } }
Приложение выглядит следующим образом:
Обратите внимание, что размер и положение графических объектов зависят только от ширины (mWidth) и высоты (mHeight) экрана. Таким образом наше приложение будет корректно отображаться на всех Android устройствах.
Меняя следующие строки
private final int CIRCLE_COUNT = 20; //количество окружностей private final float CIRCLE_ANIMATION = 0.5f; //величина поворота окружностей на каждый кадр private final long RECT_ANIMATION = 1_000; //длительность анимации прямоугольника = 1 секунда private final long COLOR_ANIMATION = 1_000; //длительность анимации смены цветов = 1 секунда
мы можем легко изменить поведение нашего приложения.
Например,
private final int CIRCLE_COUNT = 10; //количество окружностей private final float CIRCLE_ANIMATION = 1f; //величина поворота окружностей на каждый кадр private final long RECT_ANIMATION = 1_000; //длительность анимации прямоугольника = 1 секунда private final long COLOR_ANIMATION = 500; //длительность анимации смены цветов = 0,5 секунды