/* * Copyright (C) 2016 Abhay Raj Singh Yadav * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.arsy.maps_library; import android.animation.ValueAnimator; import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.RectF; import android.graphics.Shader; import android.graphics.SweepGradient; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; import android.os.Handler; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.model.BitmapDescriptorFactory; import com.google.android.gms.maps.model.GroundOverlay; import com.google.android.gms.maps.model.GroundOverlayOptions; import com.google.android.gms.maps.model.LatLng; /** * Created by abhay yadav on 12-Jan-17. */ public class MapRadar { private GoogleMap googleMap; private LatLng latLng, prevlatlng; private Bitmap backgroundImage, backgroundImageSweep; //ripple image. private float transparency = 0.5f; //transparency of image. private volatile int distance = 2000; //distance to which ripple should be shown in metres private int fillColor = Color.TRANSPARENT; //fillcolor of circle private int strokeColor = Color.parseColor("#38728f"); //border color of circle private int strokewidth = 4; //border width of circle private GradientDrawable outerDrawable, radarDrawable; private boolean isAnimationRunning = false; private Handler sweepHandler, outerHandler; private int rotationAngle = 0; private boolean isthreesixty = false; private GroundOverlay gOverlaySweep, gOverlay; private ValueAnimator vAnimatorSweep; private float sweeptransparency = 0.5f; //transparency of image. private boolean sweepAnimationClockWiseAnticlockwise = false; private int sweepAnimationClockwiseAnticlockwiseDuration = 1; private int sweepSpeed = 2; //increase this to increase speed private int angle = 0; private int colors[] = {Color.parseColor("#0038728f"), Color.parseColor("#ff38728f")}; //sweep animation colors public MapRadar(GoogleMap googleMap, LatLng latLng, Context context) { this.googleMap = googleMap; this.latLng = latLng; this.prevlatlng = latLng; outerDrawable = (GradientDrawable) context.getResources().getDrawable(R.drawable.background); } public void withOuterCircleTransparency(float transparency) { this.transparency = transparency; } public void withRadarTransparency(float transparency) { this.sweeptransparency = transparency; } public boolean isRadarAnimationClockWiseAnticlockwise() { return sweepAnimationClockWiseAnticlockwise; } public void withClockWiseAnticlockwise(boolean sweepAnimationClockWiseAnticlockwise) { this.sweepAnimationClockWiseAnticlockwise = sweepAnimationClockWiseAnticlockwise; } public int getClockwiseAnticlockwiseDuration() { return sweepAnimationClockwiseAnticlockwiseDuration; } public void withClockwiseAnticlockwiseDuration(int sweepAnimationClockwiseAnticlockwiseDuration) { this.sweepAnimationClockwiseAnticlockwiseDuration = sweepAnimationClockwiseAnticlockwiseDuration; } public void withRadarColors(int startColor, int tailColor) { colors[0] = startColor; colors[1] = tailColor; } public int getRadarSpeed() { return sweepSpeed; } public void withRadarSpeed(int sweepSpeed) { this.sweepSpeed = sweepSpeed; } public void withDistance(int distance) { if (distance < 200) distance = 200; this.distance = distance; } public void withLatLng(LatLng latLng) { prevlatlng = this.latLng; this.latLng = latLng; } public void withOuterCircleFillColor(int fillColor) { this.fillColor = fillColor; } public void withOuterCircleStrokeColor(int strokeColor) { this.strokeColor = strokeColor; } public void withOuterCircleStrokewidth(int strokewidth) { this.strokewidth = strokewidth; } public boolean isAnimationRunning() { return isAnimationRunning; } final Runnable sweepRunnable = new Runnable() { @Override public void run() { gOverlaySweep = googleMap.addGroundOverlay(new GroundOverlayOptions() .position(latLng, distance) .transparency(sweeptransparency) .image(BitmapDescriptorFactory.fromBitmap(backgroundImageSweep))); AnimateSweep(); } }; final Runnable runnable = new Runnable() { @Override public void run() { gOverlay = googleMap.addGroundOverlay(new GroundOverlayOptions() .position(latLng, distance + strokewidth) .transparency(transparency) .image(BitmapDescriptorFactory.fromBitmap(backgroundImage))); } }; private void AnimateSweep() { vAnimatorSweep = ValueAnimator.ofInt(0, 360); vAnimatorSweep.setRepeatCount(ValueAnimator.INFINITE); vAnimatorSweep.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator valueAnimator) { if (sweepAnimationClockWiseAnticlockwise) { if ((angle) >= (360 * 2 * sweepAnimationClockwiseAnticlockwiseDuration)) isthreesixty = true; if (angle <= 0) isthreesixty = false; if (isthreesixty) { rotationAngle = (rotationAngle - sweepSpeed) % 360; angle = angle - sweepSpeed; } else { rotationAngle = (rotationAngle + sweepSpeed) % 360; angle = angle + sweepSpeed; } } else { rotationAngle = (rotationAngle + sweepSpeed) % 360; } gOverlaySweep.setBearing(rotationAngle); if (latLng != prevlatlng) { gOverlaySweep.setPosition(latLng); } } }); vAnimatorSweep.start(); } private void setDrawableAndBitmap() { outerDrawable.setColor(fillColor); float d = Resources.getSystem().getDisplayMetrics().density; int width = (int) (strokewidth * d); // margin in pixels outerDrawable.setStroke(width, strokeColor); backgroundImage = drawableToBitmap(outerDrawable); radarDrawable = new GradientDrawable(GradientDrawable.Orientation.TL_BR, colors); radarDrawable.setGradientType(GradientDrawable.SWEEP_GRADIENT); radarDrawable.setShape(GradientDrawable.OVAL); radarDrawable.setSize(1200, 1200); backgroundImageSweep = drawableToBitmap(radarDrawable); } private Bitmap drawableToBitmap(Drawable drawable) { Bitmap bitmap = null; if (drawable instanceof BitmapDrawable) { BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable; if (bitmapDrawable.getBitmap() != null) { return bitmapDrawable.getBitmap(); } } if (drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) { bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); // Single color bitmap will be created of 1x1 pixel } else { bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); } Canvas canvas = new Canvas(bitmap); drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); drawable.draw(canvas); return bitmap; } public void startRadarAnimation() { setDrawableAndBitmap(); if (!isAnimationRunning) { sweepHandler = new Handler(); sweepHandler.post(sweepRunnable); outerHandler = new Handler(); outerHandler.post(runnable); } isAnimationRunning = true; } public void stopRadarAnimation() { if (isAnimationRunning) { sweepHandler.removeCallbacks(sweepRunnable); vAnimatorSweep.cancel(); gOverlaySweep.remove(); outerHandler.removeCallbacks(runnable); gOverlay.remove(); } isAnimationRunning = false; } //not needed for now private Bitmap drawToBitmap() { int radarColor = Color.parseColor("#ffffff"); Bitmap.Config config = Bitmap.Config.ARGB_8888; Bitmap bitmap = Bitmap.createBitmap(distance, distance, config); Bitmap workingBitmap = Bitmap.createBitmap(bitmap); Bitmap mutableBitmap = workingBitmap.copy(Bitmap.Config.ARGB_8888, true); Canvas canvas = new Canvas((workingBitmap)); Paint mPaintRadar = new Paint(); mPaintRadar.setColor(radarColor); mPaintRadar.setAntiAlias(true); Shader shader = new SweepGradient(0, 0, Color.parseColor("#00000000"), Color.parseColor("#ff000000")); mPaintRadar.setShader(shader); //canvas.concat(matrix); RectF rect = new RectF(0, 0, distance, distance); canvas.drawRoundRect(rect, distance / 2, distance / 2, mPaintRadar); //canvas.drawCircle(0, 0, w/2, mPaintRadar); return workingBitmap; } }