android每隔x秒动画标记

时间:2017-04-18 07:46:42

标签: android google-maps animation

我正在地图上每1秒移动一次标记,这是有效的(我从API调用每1秒获得CarList

  //Inside CarList there is carname which serves as id

  void updateCarsLocation(final List<GeoPosition> CarList) {

    //Remove old markers

    if (carMarkers != null){
        for (Marker marker : carMarkers) {
            marker.remove();
        }
    }
    carMarkers.clear();

    if (CarList != null) {
        for (GeoPosition car : CarList) {

            //Rotate Car
            Bitmap myImg = BitmapFactory.decodeResource(getResources(), R.drawable.car);
            Matrix matrix = new Matrix();
            matrix.postRotate(car.bearing);
            Bitmap rotated = Bitmap.createBitmap(myImg, 0, 0, myImg.getWidth(), myImg.getHeight(),
                    matrix, true);

            //From Bitmap
            MarkerOptions markerOptions = new MarkerOptions();
            LatLng latLng = new LatLng(car.lat, car.lng);
            markerOptions.position(latLng);
            markerOptions.icon(BitmapDescriptorFactory.fromBitmap(rotated));
            Marker cMarker = mMap.addMarker(markerOptions);

            carMarkers.add(cMarker);

        }
    }
 }

但是我希望这些动作能够动画(流畅)我搜索了一些帮助并找到了几个链接

Animate markers 1

Animate markers 2

但是我无法弄清楚如何做到这一点,我教导了将标记+汽车放入Hashmap<Marker, GeoPosition>并通过carname(id)检查新的GeoPosition,然后使用animate,但我还没有设法让它发挥作用。

1 个答案:

答案 0 :(得分:1)

我已经实施了很长时间我会发布我的解决方案,但请确保你阅读并理解我在做什么

private Emitter.Listener onNewDriversOnMap = new Emitter.Listener() {
    @Override
    public void call(final Object... args) {
        final JSONObject receivedDrivers = (JSONObject) args[0];
        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                if (!BusyParsingDrivers) {
                    BusyParsingDrivers = true;
                    new Parse_NearbyDrivers_Task(receivedDrivers).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
                    Log.e("receivedDrivers", receivedDrivers.toString());
                }
            }
        });
    }
};


private ArrayList<Marker> existingMapMarkers = new ArrayList<>();
private boolean noNearby = false;
private boolean BusyParsingDrivers = false;
private List<Driver> driverList = new ArrayList<>();
private GoogleMap map;

/**
 * Parse the new drivers list
 **/
public class Parse_NearbyDrivers_Task extends AsyncTask<Void, Void, Integer>
{
    JSONObject receivedDrivers;
    List<Driver> newDrivers = new ArrayList<>();
    List<Driver> oldDriversMoved = new ArrayList<>();
    List<Driver> removedDrivers = new ArrayList<>();

    public Parse_NearbyDrivers_Task(JSONObject receivedDrivers)
    {
        this.receivedDrivers = receivedDrivers;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }

    @Override
    protected Integer doInBackground(Void... params)
    {

        try
        {
            //Get the status object from the received JSONObject
            JSONObject status = receivedDrivers.getJSONObject("Status");
            //Get the status code
            int status_code = Integer.parseInt(status.getString("Status"));

            //Here we define a switch to handle the values of the status code and return an integer after some work to filter the drivers
            switch (status_code) {

                case 0:    //The list is not empty
                {
                    JSONArray nearbyDrivers = receivedDrivers.getJSONArray("NearbyDrivers");




                    if (driverList.isEmpty())     //If the driversList is empty
                    {
                        //Iterate over all the new drivers and add them to the driverList and return 0
                        for (int i = 0; i < nearbyDrivers.length(); ++i) {
                            Driver tempDriver = new Driver();
                            tempDriver.id = Integer.parseInt(nearbyDrivers.getJSONObject(i).getString("pkDriverId"));
                            tempDriver.longitude = Double.parseDouble(nearbyDrivers.getJSONObject(i).getString("Longitude"));
                            tempDriver.latitude = Double.parseDouble(nearbyDrivers.getJSONObject(i).getString("Latitude"));
                            tempDriver.altitude = Double.parseDouble(nearbyDrivers.getJSONObject(i).getString("Altitude"));
                            tempDriver.angle = Float.parseFloat(nearbyDrivers.getJSONObject(i).getString("Angle"));
                            tempDriver.speed = Float.parseFloat(nearbyDrivers.getJSONObject(i).getString("Speed"));
                            tempDriver.accuracy = Float.parseFloat(nearbyDrivers.getJSONObject(i).getString("Accuracy"));
                            tempDriver.distanceCovered = Double.parseDouble(nearbyDrivers.getJSONObject(i).getString("DistanceCovered"));
                            tempDriver.carType = Integer.parseInt(nearbyDrivers.getJSONObject(i).getString("CarTypeCode"));
                            driverList.add(tempDriver);
                        }
                        return 0;
                    } else         //If the driversList is not empty
                    {
                        //Iterate over the received list and if the list contain a new driver then add it to the newDrivers
                        // but if it contain an already added driver but with different coordinates then add this driver to
                        // the oldDriversMoved to later move this driver to the new coordinates
                        for (int i = 0; i < nearbyDrivers.length(); i++) {
                            Driver tempDriver = new Driver();
                            tempDriver.id = Integer.parseInt(nearbyDrivers.getJSONObject(i).getString("pkDriverId"));
                            tempDriver.longitude = Double.parseDouble(nearbyDrivers.getJSONObject(i).getString("Longitude"));
                            tempDriver.latitude = Double.parseDouble(nearbyDrivers.getJSONObject(i).getString("Latitude"));
                            tempDriver.altitude = Double.parseDouble(nearbyDrivers.getJSONObject(i).getString("Altitude"));
                            tempDriver.angle = Float.parseFloat(nearbyDrivers.getJSONObject(i).getString("Angle"));
                            tempDriver.speed = Float.parseFloat(nearbyDrivers.getJSONObject(i).getString("Speed"));
                            tempDriver.accuracy = Float.parseFloat(nearbyDrivers.getJSONObject(i).getString("Accuracy"));
                            tempDriver.distanceCovered = Double.parseDouble(nearbyDrivers.getJSONObject(i).getString("DistanceCovered"));
                            tempDriver.carType = Integer.parseInt(nearbyDrivers.getJSONObject(i).getString("CarTypeCode"));

                            if (!isDriverAlreadyExists(driverList, nearbyDrivers.getJSONObject(i).getInt("pkDriverId"))) {
                                newDrivers.add(tempDriver);
                            } else {
                                for (int j = 0; j < driverList.size(); ++j) {
                                    if (nearbyDrivers.getJSONObject(i).getInt("pkDriverId") == driverList.get(j).id) {
                                        if (Double.parseDouble(nearbyDrivers.getJSONObject(i).getString("Longitude")) != driverList.get(j).longitude || Double.parseDouble(nearbyDrivers.getJSONObject(i).getString("Latitude")) != driverList.get(j).latitude) {
                                            oldDriversMoved.add(tempDriver);
                                        }
                                    }

                                }
                            }
                        }
                        //If a driver is no more existing then add it to the removedDrivers List
                        for (int j = 0; j < driverList.size(); j++) {

                            if (!isDriverAlreadyExists(nearbyDrivers, driverList.get(j).id)) {
                                removedDrivers.add(driverList.get(j));
                            }
                        }

                        //return 1 to be handled in the onPostExecute
                        return 1;
                    }

                }
                case 1:    //The list is empty
                case 500:  //The list is empty
                    return 2;
                default:   //Some error
                    return -1;

            }

        } catch (JSONException e) {
            return -2;
        }
    }

    @Override
    protected void onPostExecute(Integer status)
    {
        super.onPostExecute(status);

        try {
            //According to what is received from the doInBackground make some actions that will affect the markers of the drivers
            switch (status) {
                case 0:
                    noNearby = false;

                    Plant_NearbyDrivers();

                    //helper_methods.Debug("Arrays sizes","DriverList:"+driverList.size()+"  Existing map markers: "+existingMapMarkers.size());
                    break;
                case 1:
                    noNearby = false;

                    Add_Remove_Move_Drivers(removedDrivers, oldDriversMoved, newDrivers);
                    break;

                case 2:
                    Remove_AllDriverFromMap();
                    break;

            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        BusyParsingDrivers = false;

    }
}

/**
 * This method is called after receiving the drivers list and filtering this list according to new,removed,moved drivers to handle these actions
 **/
private void Add_Remove_Move_Drivers(List<Driver> removedDrivers, List<Driver> oldDriversMoved, List<Driver> newDrivers)
{
    //Get the icon that will be used to add the new drivers
    BitmapDescriptor icon = getCarIcon();

    ArrayList<ObjectAnimator> objectAnimatorsArray = new ArrayList<>();
    ObjectAnimator[] objectAnimators;

    TypeEvaluator<LatLng> typeEvaluator = new TypeEvaluator<LatLng>() {
        @Override
        public LatLng evaluate(float fraction, LatLng startValue, LatLng endValue) {
            return new LatLngInterpolator.Spherical().interpolate(fraction, startValue, endValue);
        }
    };

    //Iterate the removedDrivers list to see the matching drivers in the driversList and remove it
    for (int i = 0; i < removedDrivers.size(); ++i) {
        for (int j = 0; j < driverList.size(); ++j) {
            //When Ids match then remove from the existingMapMarkers list and driversList
            if (removedDrivers.get(i).id == driverList.get(j).id) {
                driverList.remove(j);
                existingMapMarkers.get(j).remove();
                existingMapMarkers.remove(j);
            }
        }
    }

    //Iterate the oldDriversMoved List to get the matching in the driversList and update it and move it according to the new coordinates
    for (int i = 0; i < oldDriversMoved.size(); ++i) {
        for (int j = 0; j < driverList.size(); ++j) {
            //When we get the match update the driver in driversList and move it to the new LatLang
            if (oldDriversMoved.get(i).id == driverList.get(j).id) {
                LatLng newDriverLatLng = new LatLng(oldDriversMoved.get(i).latitude, oldDriversMoved.get(i).longitude);
                float desiredRotation = oldDriversMoved.get(i).angle;

                ObjectAnimator rotationAnimator = ObjectAnimator.ofFloat(existingMapMarkers.get(j), "rotation", existingMapMarkers.get(j).getRotation(), desiredRotation);
                rotationAnimator.setDuration(1500);
                objectAnimatorsArray.add(rotationAnimator);

                Property<Marker, LatLng> property = Property.of(Marker.class, LatLng.class, "position");
                ObjectAnimator directionAnimator = ObjectAnimator.ofObject(existingMapMarkers.get(j), property, typeEvaluator, newDriverLatLng);
                directionAnimator.setDuration(3000);
                objectAnimatorsArray.add(directionAnimator);

                objectAnimators = objectAnimatorsArray.toArray(new ObjectAnimator[objectAnimatorsArray.size()]);
                AnimatorSet animDrivers = new AnimatorSet();
                animDrivers.playTogether(objectAnimators);
                animDrivers.start();
                int position = driverList.indexOf(driverList.get(j));
                driverList.remove(position);
                driverList.add(position, oldDriversMoved.get(i));
            }
        }
    }

    //Iterate the newDrivers List to add them as markers and to the driversList
    for (int i = 0; i < newDrivers.size(); ++i) {
        LatLng newDriverLatLng = new LatLng(newDrivers.get(i).latitude, newDrivers.get(i).longitude);
        driverList.add(newDrivers.get(i));
        existingMapMarkers.add(map.addMarker(new MarkerOptions().anchor(0.5f, 0.5f).position(newDriverLatLng).icon(icon)));
    }
}

/**
 * Remove all the drivers from the map
 **/
public void Remove_AllDriverFromMap()
{
    //Iterate all the drivers markers and remove them
    for (int i = 0; i < existingMapMarkers.size(); ++i) {
        existingMapMarkers.get(i).remove();
    }
    //Clear the arrays and set noNearby to true
    noNearby = true;
    driverList.clear();
    existingMapMarkers.clear();
}

/**
 * This method is called when there is no drivers visible on the map and we receive a list of drivers so we plant them right away
 **/
private void Plant_NearbyDrivers()
{
    try {

        BitmapDescriptor icon = getCarIcon();
        for (int i = 0; i < driverList.size(); i++) {
            LatLng newDriverLatLng = new LatLng(driverList.get(i).latitude, driverList.get(i).longitude);
            existingMapMarkers.add(map.addMarker(new MarkerOptions().anchor(0.5f, 0.5f).position(newDriverLatLng).icon(icon)));
        }

    } catch (Exception e) {
        e.printStackTrace();
    }
}

/**
 * Called to compare if the new drivers received is contained in the old driver list
 **/
public boolean isDriverAlreadyExists(List<Driver> array, int driverId)
{
    for (int c = 0; c < array.size(); c++) {
        Driver current = array.get(c);
        if (current.id == driverId)
            return true;
    }
    return false;
}

/**
 * Called to compare if the old drivers list  is contained in the new drivers list
 **/
public boolean isDriverAlreadyExists(JSONArray nearbyDrivers, int driverId)
{
    for (int c = 0; c < nearbyDrivers.length(); c++) {
        try {
            JSONObject current = nearbyDrivers.getJSONObject(c);
            if (current.getInt("pkDriverId") == driverId)
                return true;
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
    return false;
}

/**
 * Get the icon of the car to be displayed according to the selected filter
 **/
public BitmapDescriptor getCarIcon()
{
    BitmapDescriptor icon = null;

    //make the icon as you want

    return icon;
}

将此添加到您的构建

compile 'com.nineoldandroids:library:2.4.0'