Анимация по массиву точек

Я уверен, что есть простой способ сделать это, но я застрял. Допустим, у меня есть список пунктов:

Point[] list = {pointA, pointB, pointC, ...} 

Я хотел бы оживить ImageView через каждую точку. Поэтому я попробовал это:

 id = 0; AnimatorListenerAdapter animEnd = new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); id++; if(id != list.length) { iv.animate() .translationX(list[id].getX()) .translationY(list[id].getY()) .setDuration(200) .setListener(this); } } }; iv.animate() .translationX(list[id].getX()).translationY(list[id].getY()) .setDuration(200).setListener(animEnd); 

Он работает, но между каждой анимацией есть небольшая задержка.

Есть идеи? Благодаря !

Solutions Collecting From Web of "Анимация по массиву точек"

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

Keyframes

Здесь вы можете найти технику под названием Keyframe Animation, которая является очень распространенной технологией анимации и, вероятно, именно то, что вы хотите.

Объект Keyframe состоит из пары времени / значения, которая позволяет вам определить определенное состояние в определенное время анимации. Каждый ключевой кадр может также иметь свой собственный интерполятор для управления поведением анимации в интервале между предыдущим временем ключевого кадра и временем этого ключевого кадра.

 Keyframe kf0 = Keyframe.ofFloat(0f, 0f); Keyframe kf1 = Keyframe.ofFloat(.5f, 360f); Keyframe kf2 = Keyframe.ofFloat(1f, 0f); PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2); ObjectAnimator rotationAnim = ObjectAnimator.ofPropertyValuesHolder(target, pvhRotation) rotationAnim.setDuration(5000ms); 

В вашем случае вы можете сопоставить точки в своем list со списком экземпляров Keyframe и …

 Point[] list = {pointA, pointB, pointC, ...} List<Keyframe> kfs = new ArrayList<Keyframe>(); foreach (Point p : points) { Keyframe kf = new Keyframe.ofFloat(px); // or what ever kfs.add(kf); } 

… позже передайте эти ключевые кадры некоторому заводскому методу для создания некоторого PropertyValuesHolder , напримерFloat, который имеет следующую подпись:

 public static PropertyValuesHolder ofFloat ( Property<?, Float> property, float... values ) 

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

В вашем случае я разработал бы следующие методы, так как вы разрабатываете для dalvik VM, вы не можете использовать java8 лямбда-выражения:

 // maps points to X/Y float values List<Float> toArrayX(Point[] points) { ... } List<Float> toArrayY(Point[] points) { ... } // maps float values to Keyframes List<Keyframe> toKeyframes(List<Float> floats) { ... } void createAnimation(Point[] points) { List<Keyframe> xs = toKeyframes(toArrayX(points)); PropertyValuesHolder phvX = PropertyValuesHolder .ofKeyframe("translationX", xs); List<Keyframe> ys = toKeyframes(toArrayY(points)); PropertyValuesHolder phvY = PropertyValuesHolder .ofKeyframe("translationY", ys); linkPropertyValuesHolder(phvX); linkPropertyValuesHolder(phvY); } void linkPropertyValuesHolder(PropertyValuesHolder phv) { // setup target ObjectAnimator anim = ObjectAnimator .ofPropertyValuesHolder(target, phv) anim.setDuration(5000ms); } 

Интерполяторы

В качестве альтернативы вы можете указать переходы, заданные точками, через экземпляр Interpolator .

Интерполятор определяет скорость изменения анимации. Это позволяет ускорять, замедлять, повторять и воспроизводить основные эффекты анимации (альфа, масштаб, перевод, поворот).

Интерполятор отображает дробное поплавок между 0.0 и 1.0 на другое дробное значение с плавающей точкой между 0.0 и 1.0 . Как и следующие три; LinearInterpolator , AccelerateDecelerateInterpolator и BounceInterpolator :

Изображения отсюда

Интерполятор пути

С помощью PathInterpolator s можно использовать вспомогательные интерполяторы с использованием экземпляров Path . Нарисованный путь будет использоваться для управления анимацией. В вашем случае вы можете создать два пути: один для x и другой для перевода y.

Однако будьте осторожны при построении интерполяторов из путей, потому что

… Путь должен соответствовать функции y = f (x).

Путь не должен иметь пробелов в направлении x и не должен зацикливаться на себе, так что могут быть две точки, разделяющие одну и ту же координату x. Хорошо иметь дизъюнктную линию в вертикальном направлении:

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

 Path path = new Path(); path.lineTo(0.25f, 0.25f); path.moveTo(0.25f, 0.5f); path.lineTo(1f, 1f); 

Пользовательский интерполятор

Если заданные интерполяторы недостаточно гибки, вы также можете просто реализовать интерфейс Interpolator и впоследствии создать новый экземпляр. Интерфейс очень узкий, и он предоставляет только один метод под названием getInterpolation со следующей подписью.

 public abstract float getInterpolation (float input) 

Код и XML

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

Надеюсь, это поможет, но это всего лишь псевдокод. Я не тестировал код … так что никаких гарантий для правильности.