Animation of a pulse ring around Google Maps on Android

I want to add an impulse ring animation to the current location of the blue dot user in Android google mapFragment (e.g. Uber).

Can someone help me with this?

+6
source share
2 answers

I found a solution to add pulsating animation to the marker. Here is a part of the map. Here the variable "map" denotes your 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; } 

You should call this on location updates by adding a PositionChangedListener. You can easily find this in google maps docs. After that, for each update call, the above method is used.

Fixing the radius of the pulse to a certain equal value, so that it is not too large and not too small

Write this method

 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; } 

And change this line

 userLocation.getAccuracy() 

to

 getDisplayPulseRadius(userLocation.getAccuracy() 

As well as

 .radius((Float) animation.getAnimatedValue()) 

to

 .radius(getDisplayPulseRadius((Float) animation.getAnimatedValue())) 

If you want a color-like effect to become transparent when it gets big, you can only use it in the next line, where you set the radius inside the animator

 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); } 
+10
source
 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() } } 
+1
source

Source: https://habr.com/ru/post/1014124/


All Articles