我正在地图上每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);
}
}
}
但是我希望这些动作能够动画(流畅)我搜索了一些帮助并找到了几个链接
但是我无法弄清楚如何做到这一点,我教导了将标记+汽车放入Hashmap<Marker, GeoPosition>
并通过carname
(id)检查新的GeoPosition,然后使用animate,但我还没有设法让它发挥作用。
答案 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'