Добавить анимацию как маркер гугл карты андроид - PullRequest
0 голосов
/ 06 мая 2018

Я хотел добавить анимацию как «текущий выбранный маркер» на моей карте, как показано ниже:

enter image description here

Анимация - это ресурс LottieAnimation (расширяется из ImageView).

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

У Убера или Лифта есть анимации в виде маркеров или для текущей позиции, так как они этого достигают?

Или, возможно, они слушают движение карты и обновляют местоположение своего маркера, не используя свойство marker?

1 Ответ

0 голосов
/ 06 мая 2018

Насколько я знаю, Google Map Marker и InfoWindow нарисованы на карте в виде плоского растрового изображения. Таким образом, вы не можете выполнять анимацию, взаимодействие с компонентами или даже рисовать тень вокруг них.

Приложение Uber использует другой слой, расположенный поверх карты (вы можете попробовать сделать жест на карте и увидеть, что маркер перемещается, но с небольшой задержкой). Это не легко, потому что вы должны уловить жест каждой карты и соответственно анимировать вид наложения. Я пробовал это раньше, но это слишком много работы, поэтому я оставил это позади.

Ваш импульсный эффект может быть достигнут с помощью Circle с ValueAnimator

private @ColorInt int mPulseEffectColor;
private int[] mPulseEffectColorElements;
private ValueAnimator mPulseEffectAnimator;
private Circle mPulseCircle;


private void initPulseEffect() {
    mPulseEffectColor = ContextCompat.getColor(mContext, R.color.pink);
    mPulseEffectColorElements = new int[] {
            Color.red(mPulseEffectColor),
            Color.green(mPulseEffectColor),
            Color.blue(mPulseEffectColor)
    };

    mPulseEffectAnimator = ValueAnimator.ofFloat(0, calculatePulseRadius(current_map_zoom_level));
    mPulseEffectAnimator.setStartDelay(3000);
    mPulseEffectAnimator.setDuration(400);
    mPulseEffectAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
}

Рассчитать радиус на основе уровня масштабирования карты

private static float calculatePulseRadius(float zoomLevel) {
    return (float) Math.pow(2, 16 - zoomLevel) * 160;
}

Регистрация OnCameraIdleListener для прослушивания измененного масштаба карты

@Override
public void onCameraIdle() {
    CameraPosition cameraPosition = mMap.getCameraPosition();
    if (mPulseEffectAnimator != null)
        mPulseEffectAnimator.setFloatValues(0, calculatePulseRadius(cameraPosition.zoom));
}

Запустить анимацию

private void startPulseAnimation() {
    if (mPulseCircle != null)
        mPulseCircle.remove();

    if (mPulseEffectAnimator != null) {
        mPulseEffectAnimator.removeAllUpdateListeners();
        mPulseEffectAnimator.removeAllListeners();
        mPulseEffectAnimator.end();
    }

    if (your_marker_coordinate != null) {
        mPulseCircle = mMap.addCircle(new CircleOptions()
                .center(your_marker_coordinate)
                .radius(0).strokeWidth(0)
                .fillColor(mPulseEffectColor));
        mPulseEffectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                if (mPulseCircle == null)
                    return;

                int alpha = (int) ((1 - valueAnimator.getAnimatedFraction()) * 128);
                mPulseCircle.setFillColor(Color.argb(alpha,
                        mPulseEffectColorElements[0], mPulseEffectColorElements[1], mPulseEffectColorElements[2]));
                mPulseCircle.setRadius((float) valueAnimator.getAnimatedValue());
            }
        });
        mPulseEffectAnimator.addListener(new AnimatorListenerAdapter {
            @Override
            public void onAnimationEnd(Animator animation) {
                mPulseEffectAnimator.setStartDelay(2000);
                mPulseEffectAnimator.start();
            }
        });
        mPulseEffectAnimator.start();
    }
}

Пояснение:

  • Используйте calculatePulseRadius для пересчета базы радиуса на уровне масштабирования карты, поскольку радиус круга измеряется расстоянием реального мира.
  • Используйте int[] mPulseEffectColorElements, чтобы сохранить r, g, b цвета круга, чтобы мне не нужно было воссоздавать цвет в каждом кадре. Я только хочу изменить альфа-значение
  • Прослушайте конец Аниматора и запустите его снова с задержкой.

Этот код применяется только для 1 круга за раз, несколько кругов требуют более сложной работы, но с одинаковой логикой.

Результат:

demo

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...