Android 中围绕 Google 地图标记的脉冲环动画
Posted
技术标签:
【中文标题】Android 中围绕 Google 地图标记的脉冲环动画【英文标题】:Pulse ring animation around a Google Maps marker in Android 【发布时间】:2017-05-31 02:11:17 【问题描述】:我想在 android google mapFragment(如 Uber)中的蓝点当前用户位置上添加一个脉冲环动画。
有人可以帮我解决这个问题吗?
【问题讨论】:
【参考方案1】:我找到了一种将脉动动画添加到标记的解决方案。 这是地图部分,这里变量“map”表示您的地图。
private Circle lastUserCircle;
private long pulseDuration = 1000;
private ValueAnimator lastPulseAnimator;
private void addPulsatingEffect(LatLng userLatlng)
if(lastPulseAnimator != null)
lastPulseAnimator.cancel();
Log.d("onLocationUpdated: ","cancelled" );
if(lastUserCircle != null)
lastUserCircle.setCenter(userLatlng);
lastPulseAnimator = valueAnimate(userLocation.getAccuracy(), pulseDuration, new ValueAnimator.AnimatorUpdateListener()
@Override
public void onAnimationUpdate(ValueAnimator animation)
if(lastUserCircle != null)
lastUserCircle.setRadius((Float) animation.getAnimatedValue());
else
lastUserCircle = map.addCircle(new CircleOptions()
.center(userLatlng)
.radius((Float) animation.getAnimatedValue())
.strokeColor(Color.RED)
.fillColor(Color.BLUE));
);
protected ValueAnimator valueAnimate(float accuracy,long duration, ValueAnimator.AnimatorUpdateListener updateListener)
Log.d( "valueAnimate: ", "called");
ValueAnimator va = ValueAnimator.ofFloat(0,accuracy);
va.setDuration(duration);
va.addUpdateListener(updateListener);
va.setRepeatCount(ValueAnimator.INFINITE);
va.setRepeatMode(ValueAnimator.RESTART);
va.start();
return va;
您必须通过添加 PositionChangedListener 来调用位置更新。您可以在 Google 地图文档中轻松找到它。之后,为每次更新调用上述方法。
将脉冲半径固定为大致相同的值,使其既不太大也不太小
写这个方法
protected float getDisplayPulseRadius(float radius)
float diff = (map.getMaxZoomLevel() - map.getCameraPosition().zoom);
if (diff < 3)
return radius;
if (diff < 3.7)
return radius * (diff / 2);
if (diff < 4.5)
return (radius * diff);
if (diff < 5.5)
return (radius * diff) * 1.5f;
if (diff < 7)
return (radius * diff) * 2f;
if (diff < 7.8)
return (radius * diff) * 3.5f;
if (diff < 8.5)
return (float) (radius * diff) * 5;
if (diff < 10)
return (radius * diff) * 10f;
if (diff < 12)
return (radius * diff) * 18f;
if (diff < 13)
return (radius * diff) * 28f;
if (diff < 16)
return (radius * diff) * 40f;
if (diff < 18)
return (radius * diff) * 60;
return (radius * diff) * 80;
并改变这一行
userLocation.getAccuracy()
到
getDisplayPulseRadius(userLocation.getAccuracy()
还有
.radius((Float) animation.getAnimatedValue())
到
.radius(getDisplayPulseRadius((Float) animation.getAnimatedValue()))
如果您想要颜色变大时变为透明的效果,您可以在设置动画器内部半径的下一行中使用它
circle.setFillColor(adjustAlpha(pulseAroundMeFillColor, 1 - animation.getAnimatedFraction()));
private int adjustAlpha(int color, float factor)
int alpha = Math.round(Color.alpha(color) * factor);
int red = Color.red(color);
int green = Color.green(color);
int blue = Color.blue(color);
return Color.argb(alpha, red, green, blue);
【讨论】:
帮帮我。你的“userLocation.getAccuracy()”在哪里 您好,我不明白您的问题。 “userLocation”是一个 android.location.Location 对象。你可以在这里查看我的一个具有许多地图功能的项目。 github.com/itsdebs/MapEasy 和所有这些与地图相关的实现的文件在这里。 github.com/itsdebs/MapEasy/blob/master/app/src/main/java/com/… 看看,如果这回答了您的问题。 @Debanjan:我必须放大才能看到动画。知道如何设置固定大小吗?谢谢 @Neha 抱歉迟到了。那很难。我尝试找出屏幕中的坐标,以显示脉动效果,但这从来都不是准确的,所以我在答案中附上了唯一可能的选项。您可以使用试错法来改变这一点。 你先生,真是太棒了。【参考方案2】:import android.animation.ValueAnimator
import android.graphics.Color
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import com.google.android.gms.maps.CameraUpdateFactory
import com.google.android.gms.maps.GoogleMap
import com.google.android.gms.maps.MapFragment
import com.google.android.gms.maps.model.Circle
import com.google.android.gms.maps.model.CircleOptions
import com.google.android.gms.maps.model.LatLng
import com.google.android.gms.maps.model.MarkerOptions
class MainActivity : AppCompatActivity()
private val pulseCount = 4
private val animationDuration = (pulseCount + 1) * 1000
private val SAN_FRANCISCO_LOCATION = LatLng(37.7749295, -122.4194155)
private var gMap: GoogleMap? = null
private var circles = Array<Circle?>(pulseCount, null )
override fun onCreate(savedInstanceState: Bundle?)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
(fragmentManager.findFragmentById(R.id.mpFrgmnt) as MapFragment).getMapAsync map ->
gMap = map
setCurrentLocation()
private fun setCurrentLocation()
gMap?.let gMap ->
gMap.moveCamera(CameraUpdateFactory.newLatLngZoom(SAN_FRANCISCO_LOCATION, 17f))
gMap.animateCamera(CameraUpdateFactory.zoomIn())
gMap.animateCamera(CameraUpdateFactory.zoomTo(17f), animationDuration, null)
gMap.addMarker(MarkerOptions().position(SAN_FRANCISCO_LOCATION).title("San Francisco !"))
val from = 0
val to = 100
val fraction = 255 / to
for (i in 0 until pulseCount)
addPulseAnimator(gMap, circles, SAN_FRANCISCO_LOCATION, from, to, fraction, i)
private fun addPulseAnimator(gMap: GoogleMap, circles: Array<Circle?>, latLng: LatLng, from: Int, to: Int, colorFraction: Int, currentPosition: Int)
val valueAnimator = ValueAnimator.ofInt(from, to)
valueAnimator.duration = animationDuration.toLong()
valueAnimator.repeatCount = ValueAnimator.INFINITE
valueAnimator.repeatMode = ValueAnimator.RESTART
valueAnimator.startDelay = currentPosition * 1000L
valueAnimator.addUpdateListener valueAnimator ->
val radius = valueAnimator.animatedValue as Int
circles[currentPosition]?.let circle ->
circle.center = latLng
circle.radius = radius.toDouble()
circle.fillColor = Color.argb((to - radius) * colorFraction, 48, 118, 254)
circle.strokeWidth = 0f
?: run
circles[currentPosition] = gMap.addCircle(CircleOptions()
.center(latLng)
.radius(radius.toDouble())
.fillColor(Color.argb((to - radius) * colorFraction, 48, 118, 254))
.strokeWidth(0f))
valueAnimator.start()
【讨论】:
代码是用Kotlin编写的,您可以使用Android Studio直接在java中转换代码。还有一件事是对 Debanjan 上述解决方案的扩展。 很好的答案! 这适用于单标记动画。但是当为多个标记添加时,动画会闪烁。您是否尝试过多个标记?以上是关于Android 中围绕 Google 地图标记的脉冲环动画的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Google MAps API v2 围绕引脚绘制圆圈
如何在 Android 中使用 Google 地图按类别隐藏/显示标记组?
在 Android 中步行/驾驶时更新位置标记并在 Google 地图上绘制路径
如何在 Android 上的 Google 地图上的标记旁边显示标签?