English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Эта статья介绍了 пример анимации загрузки, имитирующей爱奇艺的android, конкретный код следующий:
Эскиз:
Используемые знания:
Если вы еще не знакомы с Path и ValueAnimator, рекомендуется ознакомиться с блогами этих великих людей, статьи которых о создании собственных view на данный момент наиболее подходящие для меня, подробные инструкции и практика по созданию собственных view, также это и инструкция с практикой, благодарю их за их труды! (Надеюсь, что все смогут серьезно изучить это, и это даст много启发).
Разбивка анимации
Основная сложность здесь заключается в вычислении координат, и я постараюсь详细说一下:
Верю, что это изображение уже вынесено, и с помощью тригонометрических функций, координаты p1, p2, p3 уже определены.
p1.x = -(int) ((radius / 2 * Math.tan(30 * Math.PI / 180)));
p1.y = -radius / 2;
p2.x = p1.x;
p2.y = radius / 2;
p3.x = (int) (radius / 2 / Math.sin(60 * Math.PI / 180));
p3.y = 0;
Определяем некоторые свойства
private static final String DEFAULT_COLOR = "#00ba9b"; private static final int DEFAULT_SIZE = 50; // По умолчанию размер private static final int DRAW_CIRCLE = 10001; // Статический флаг состояния: рисует круг и треугольник, выполняет анимацию рисования круга private static final int ROTATE_TRIANGLE = 10002; // Статический флаг состояния: выполняет анимацию вращения треугольника и сворачивания круга private Context mContext; private Paint trianglePaint; // Кисть для треугольника private Paint circlePaint; // Кисть для круга private float paintStrokeWidth = 1; // Устанавливает ширину круга private long duration = 800; //время выполнения private int mWidth; //ширина и высота View private int mHeight; private Path trianglePath; //путь треугольника private Path circlePath; //путь окружности private Path dst; //путь, вычисленный после измерения pathMeasure private Point p1, p2, p3; //три вершины треугольника private ValueAnimator animator; //анимация свойств, главным образом для получения значения от 0 до 1 для выполнения анимации private float mAnimatorValue = 0; //хранение полученного значения от 0 до 1 private int mCurrentState = 0; //текущее состояние private int radius = 0; //радиус окружности private float startSegment; //длина начала окружности private PathMeasure mMeasure; //измерение пути private int triangleColor = -1; private int circleColor = -1;
Настройка пути
1.Поскольку треугольник всегда существует, сначала нарисуйте треугольник, используя путь, мы уже знаем координаты трёх вершины треугольника, и рисование треугольника становится очень простым.
trianglePath = new Path(); p1 = new Point(); p2 = new Point(); p3 = new Point(); trianglePath.moveTo(p1.x, p1.y); trianglePath.lineTo(p2.x, p2.y); trianglePath.lineTo(p3.x, p3.y); trianglePath.close();
Таким образом, путь треугольника настроен, и достаточно вызвать canvans.drawPath(), чтобы нарисовать треугольник на холсте.
2.Затем рисуется окружность, как уже говорилось, у окружности есть выемка,所以我们 также добавляем окружность в путь, и мы не рисуем её directamente на canvas, потому что позже мы ещё будем вычислять периметр окружности, и эти операции помогут нам с путём.
circlePath = new Path(); RectF circleRect = new RectF(-radius, -radius, radius, radius); circlePath.addArc(circleRect, 268, 358); // Это начнется с 268° от круга, нарисовать 258° с двухградусным промежутком
Настройка анимации свойств
Поскольку анимации требуются данные в диапазоне от 0 до 1
Здесь мы используем числовые значения, предоставляемые анимацией свойств, для создания анимации.
private void initAnimation() { TimeInterpolator timeInterpolator = new AccelerateDecelerateInterpolator(); animator = ValueAnimator.ofFloat(0, 1).setDuration(duration); animator.setInterpolator(timeInterpolator); animator.setRepeatMode(ValueAnimator.RESTART); animator.setRepeatCount(ValueAnimator.INFINITE); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { mAnimatorValue = (float) animation.getAnimatedValue(); // Здесь мы получим значение от 0 до 1 invalidate(); // Здесь выполняется перерисовка {} }); animator.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { {} @Override public void onAnimationEnd(Animator animation) { {} @Override public void onAnimationCancel(Animator animation) { {} @Override public void onAnimationRepeat(Animator animation) { // здесь выполняется переход между состояниями, выполняются различные анимации switch (mCurrentState) { case DRAW_CIRCLE: mCurrentState = ROTATE_TRIANGLE; break; case ROTATE_TRIANGLE: mCurrentState = DRAW_CIRCLE; break; default: break; {} {} }); {}
onDraw
анализ метода onDraw
protected void onDraw(Canvas canvas) { super.onDraw(canvas); // переместить origen в центральное положение canvas.translate(mWidth / 2, mHeight / 2); // сбросить path dst dst.reset(); // определяем текущее состояние switch (mCurrentState) { // здесь мы говорим о первом состоянии case DRAW_CIRCLE: // это строка используется для получения начальной позиции для вырезанного path (dst), если внимательно наблюдать за анимацией, можно увидеть, что начало окружности // рисуется с обоих концов, это положение大约 равно 1/5 окружности, когда достигается начальная точка окружности, начну рисовать с начальной точки окружности, я выполняю этот анимационный // время大致 установлено на положение около 0.3 от 0 до 1. startSegment = (float) (mMeasure.getLength() / 5 * ((0.3 - mAnimatorValue) > 0 ? (0.3 - mAnimatorValue) : 0)); // здесь нет ничего, просто рисуется треугольник trianglePaint.setStyle(Paint.Style.FILL_AND_STROKE); canvas.drawPath(trianglePath, trianglePaint); // этот метод используется для получения требуемого фрагмента, первый параметр - это начальная позиция, второй параметр - это конечная позиция, третий параметр - это // это число - это вырезанный path, добавляется к path (dst), обратите внимание, что это добавление, а не замена, поэтому перед этим нужно выполнить reset, четвертый параметр - это // нужно ли перемещать начальную точку к началу текущего пути, чтобы сохранить путь в dst без изменений (например, если в dst уже есть path, здесь // установлено false, в этом случае гарантируется непрерывность dst, а после перемещения dst добавляется начальная точка нового пути к концу предыдущего пути, чтобы поддерживать непрерывность) mMeasure.getSegment(startSegment, mMeasure.getLength() * mAnimatorValue, dst, true); canvas.drawPath(dst, circlePaint); break; //Второй вид анимации case ROTATE_TRIANGLE: //Сохранить холст, так как нужно выполнить два анимации, сохранить состояние холста в начальном состоянии canvas.save(); //Затем выполнить вращение треугольника trianglePaint.setStyle(Paint.Style.FILL_AND_STROKE); canvas.rotate(360 * mAnimatorValue); canvas.drawPath(trianglePath, trianglePaint); //Восстановить холст canvas.restore(); //Затем исчезновение внешнего круга, исчезновение действительно похоже на рисование круга, у нас есть набор значений от 0 до 1, нам нужно только //Когда мы截取片段时,пусть точка старта постоянно приближается к общей длине, и появится эффект исчезновения mMeasure.getSegment(mMeasure.getLength() * mAnimatorValue, mMeasure.getLength(), dst, true); canvas.drawPath(dst, circlePaint); break; default: break; {} {}
Вот и все, что было в этой статье, надеюсь, это поможет вам в изучении, также希望大家多多支持呐喊教程。
Заявление: содержимое этой статьи взято из Интернета, авторские права принадлежат соответствующему автору, материалы предоставлены пользователями Интернета в порядке добровольного участия и самостоятельной загрузки, сайт не обладает правами собственности, не был обработан редакторами, не несет ответственности за связанные с этим法律责任. Если вы обнаружите материалы,涉嫌侵犯版权, пожалуйста, отправьте письмо по адресу: notice#oldtoolbag.com (при отправке письма замените # на @) для сообщения о нарушении и предоставьте соответствующие доказательства. В случае подтверждения факта нарушения, сайт незамедлительно удалят涉嫌侵权的内容。