我正在开展类似于UBER,Lyft或OLA的项目。可用移动汽车在家中地图。 我正在寻找某种类型的图书馆,它可以让汽车像UBER一样顺利转动。现在,我可以使用以下代码将汽车平稳地从一个纬度移动到另一个长度。但棘手的部分是轮流并确保汽车在向方向移动时面向前方。
平稳移动的汽车代码:
final LatLng SomePos = new LatLng(12.7796354, 77.4159606);
try {
if (googleMap == null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
googleMap = ((MapFragment) getFragmentManager().findFragmentById(R.id.map)).getMap();
}
}
googleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
googleMap.setMyLocationEnabled(true);
googleMap.setTrafficEnabled(false);
googleMap.setIndoorEnabled(false);
googleMap.setBuildingsEnabled(true);
googleMap.getUiSettings().setZoomControlsEnabled(true);
googleMap.moveCamera(CameraUpdateFactory.newLatLng(SomePos));
googleMap.moveCamera(CameraUpdateFactory.newCameraPosition(new CameraPosition.Builder()
.target(googleMap.getCameraPosition().target)
.zoom(17)
.bearing(30)
.tilt(45)
.build()));
myMarker = googleMap.addMarker(new MarkerOptions()
.position(SomePos)
.icon(BitmapDescriptorFactory.fromResource(R.mipmap.ic_launcher))
.title("Hello world"));
googleMap.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() {
@Override
public boolean onMarkerClick(Marker arg0) {
final LatLng startPosition = myMarker.getPosition();
final LatLng finalPosition = new LatLng(12.7801569, 77.4148528);
final Handler handler = new Handler();
final long start = SystemClock.uptimeMillis();
final Interpolator interpolator = new AccelerateDecelerateInterpolator();
final float durationInMs = 3000;
final boolean hideMarker = false;
handler.post(new Runnable() {
long elapsed;
float t;
float v;
@Override
public void run() {
// Calculate progress using interpolator
elapsed = SystemClock.uptimeMillis() - start;
t = elapsed / durationInMs;
LatLng currentPosition = new LatLng(
startPosition.latitude * (1 - t) + finalPosition.latitude * t,
startPosition.longitude * (1 - t) + finalPosition.longitude * t);
myMarker.setPosition(currentPosition);
// Repeat till progress is complete.
if (t < 1) {
// Post again 16ms later.
handler.postDelayed(this, 16);
} else {
if (hideMarker) {
myMarker.setVisible(false);
} else {
myMarker.setVisible(true);
}
}
}
});
return true;
}
});
} catch (Exception e) {
e.printStackTrace();
}
答案 0 :(得分:45)
我最近遇到过相同的用例。这是我的解决方案。
首先,我要感谢@VipiN分享&#34;平稳移动汽车代码&#34;。它运作顺畅。
第二部分是将车标放在正确的方向并根据转弯旋转。为此,我计算了两个连续点之间的方位角或方向角(即从设备/服务器接收的位置更新)。这个link将帮助您理解它背后的数学。
以下代码将介绍两个位置:
private double bearingBetweenLocations(LatLng latLng1,LatLng latLng2) {
double PI = 3.14159;
double lat1 = latLng1.latitude * PI / 180;
double long1 = latLng1.longitude * PI / 180;
double lat2 = latLng2.latitude * PI / 180;
double long2 = latLng2.longitude * PI / 180;
double dLon = (long2 - long1);
double y = Math.sin(dLon) * Math.cos(lat2);
double x = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1)
* Math.cos(lat2) * Math.cos(dLon);
double brng = Math.atan2(y, x);
brng = Math.toDegrees(brng);
brng = (brng + 360) % 360;
return brng;
}
最后,我们需要按照从上面的方法获得的角度旋转汽车标记。
private void rotateMarker(final Marker marker, final float toRotation) {
if(!isMarkerRotating) {
final Handler handler = new Handler();
final long start = SystemClock.uptimeMillis();
final float startRotation = marker.getRotation();
final long duration = 1000;
final Interpolator interpolator = new LinearInterpolator();
handler.post(new Runnable() {
@Override
public void run() {
isMarkerRotating = true;
long elapsed = SystemClock.uptimeMillis() - start;
float t = interpolator.getInterpolation((float) elapsed / duration);
float rot = t * toRotation + (1 - t) * startRotation;
marker.setRotation(-rot > 180 ? rot / 2 : rot);
if (t < 1.0) {
// Post again 16ms later.
handler.postDelayed(this, 16);
} else {
isMarkerRotating = false;
}
}
});
}
}
干杯!
答案 1 :(得分:15)
这是我的代码移动标记像超级。我已经展示了两种移动标记的方法。
重要提示:要在适当的道路上行驶[如ola,uber],您需要使用谷歌提供的道路api
1.静态经纬度
2.By实时纬度和经度
package com.gangsofcoder.googlemapdemo;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.PersistableBundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.animation.LinearInterpolator;
import android.widget.Button;
import android.widget.Toast;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.loopj.android.http.AsyncHttpResponseHandler;
import com.loopj.android.http.RequestParams;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import cz.msebera.android.httpclient.Header;
public class MoveCar extends AppCompatActivity {
private GoogleMap googleMap;
SupportMapFragment mapFragment;
Marker marker;
private boolean isMarkerRotating = false;
ArrayList<LatLng> listOfPoints = new ArrayList<>();
int currentPt = 0;
LatLng finalPosition;
Marker mMarker;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setUpMapIfNeeded();
//new location details
listOfPoints.add(new LatLng(30.701623, 76.684220));
listOfPoints.add(new LatLng(30.702486, 76.685487));
listOfPoints.add(new LatLng(30.703135, 76.684891));
listOfPoints.add(new LatLng(30.703256, 76.685000));
listOfPoints.add(new LatLng(30.703883, 76.685941));
listOfPoints.add(new LatLng(30.703413, 76.685190));
}
private void setUpMapIfNeeded() {
if (mapFragment == null) {
mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
if (mapFragment != null) {
mapFragment.getMapAsync(new OnMapReadyCallback() {
@Override
public void onMapReady(GoogleMap googleMap) {
loadMap(googleMap);
}
});
}
}
}
private void loadMap(GoogleMap map) {
googleMap = map;
mMarker = googleMap.addMarker(new MarkerOptions().position(new LatLng(30.701623, 76.684220)).icon(BitmapDescriptorFactory.fromResource(R.drawable.icon_car)));
final Handler handler = new Handler();
//Code to move car along static latitude and longitude
/* handler.postDelayed(new Runnable() {
@Override
public void run() {
if (currentPt < listOfPoints.size()) {
//post again
Log.d("tess", "inside run ");
Location targetLocation = new Location(LocationManager.GPS_PROVIDER);
targetLocation.setLatitude(listOfPoints.get(currentPt).latitude);
targetLocation.setLongitude(listOfPoints.get(currentPt).longitude);
animateMarkerNew(targetLocation, mMarker);
handler.postDelayed(this, 3000);
currentPt++;
} else {
Log.d("tess", "call back removed");
//removed callbacks
handler.removeCallbacks(this);
}
}
}, 3000);*/
//Here move marker along real time updates
final RequestParams params = new RequestParams();
params.put("source_lattitude", "lat");
params.put("source_longitude", "long");
params.put("date", "date");
//new handler
handler.postDelayed(new Runnable() {
@Override
public void run() {
LoopjHttpClient.post(getString(R.string.default_upload_website), params, new AsyncHttpResponseHandler() {
@Override
public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
try {
JSONObject jsonObject = new JSONObject(new String(responseBody));
String status = jsonObject.getString("status");
String text = jsonObject.getString("text");
//reading json array
JSONArray jsonArray = jsonObject.getJSONArray("result");
String source = jsonArray.getJSONObject(0).getString("source");
String[] latLong = source.split(",");
Location location = new Location(LocationManager.GPS_PROVIDER);
location.setLatitude(Double.parseDouble(latLong[0]));
location.setLongitude(Double.parseDouble(latLong[1]));
//calling method to animate marker
animateMarkerNew(location, mMarker);
} catch (JSONException e) {
e.printStackTrace();
}
}
@Override
public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
Log.d("onFailure", "onFailure");
}
});
handler.postDelayed(this, 3000);
}
}, 3000);
}
private void animateMarkerNew(final Location destination, final Marker marker) {
if (marker != null) {
final LatLng startPosition = marker.getPosition();
final LatLng endPosition = new LatLng(destination.getLatitude(), destination.getLongitude());
final float startRotation = marker.getRotation();
final LatLngInterpolatorNew latLngInterpolator = new LatLngInterpolatorNew.LinearFixed();
ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1);
valueAnimator.setDuration(3000); // duration 3 second
valueAnimator.setInterpolator(new LinearInterpolator());
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
try {
float v = animation.getAnimatedFraction();
LatLng newPosition = latLngInterpolator.interpolate(v, startPosition, endPosition);
marker.setPosition(newPosition);
googleMap.moveCamera(CameraUpdateFactory.newCameraPosition(new CameraPosition.Builder()
.target(newPosition)
.zoom(15.5f)
.build()));
marker.setRotation(getBearing(startPosition, new LatLng(destination.getLatitude(), destination.getLongitude())));
} catch (Exception ex) {
//I don't care atm..
}
}
});
valueAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
// if (mMarker != null) {
// mMarker.remove();
// }
// mMarker = googleMap.addMarker(new MarkerOptions().position(endPosition).icon(BitmapDescriptorFactory.fromResource(R.drawable.icon_car)));
}
});
valueAnimator.start();
}
}
private interface LatLngInterpolatorNew {
LatLng interpolate(float fraction, LatLng a, LatLng b);
class LinearFixed implements LatLngInterpolatorNew {
@Override
public LatLng interpolate(float fraction, LatLng a, LatLng b) {
double lat = (b.latitude - a.latitude) * fraction + a.latitude;
double lngDelta = b.longitude - a.longitude;
// Take the shortest path across the 180th meridian.
if (Math.abs(lngDelta) > 180) {
lngDelta -= Math.signum(lngDelta) * 360;
}
double lng = lngDelta * fraction + a.longitude;
return new LatLng(lat, lng);
}
}
}
//Method for finding bearing between two points
private float getBearing(LatLng begin, LatLng end) {
double lat = Math.abs(begin.latitude - end.latitude);
double lng = Math.abs(begin.longitude - end.longitude);
if (begin.latitude < end.latitude && begin.longitude < end.longitude)
return (float) (Math.toDegrees(Math.atan(lng / lat)));
else if (begin.latitude >= end.latitude && begin.longitude < end.longitude)
return (float) ((90 - Math.toDegrees(Math.atan(lng / lat))) + 90);
else if (begin.latitude >= end.latitude && begin.longitude >= end.longitude)
return (float) (Math.toDegrees(Math.atan(lng / lat)) + 180);
else if (begin.latitude < end.latitude && begin.longitude >= end.longitude)
return (float) ((90 - Math.toDegrees(Math.atan(lng / lat))) + 270);
return -1;
}
}
答案 2 :(得分:11)
由于SO用户在两个不同的帖子中寻找工作代码有点混乱。以下是旋转和移动标记的工作代码,它为我无缝工作。
MainActivity.java 中的
public void rotateMarker(final Marker marker, final float toRotation, final float st) {
final Handler handler = new Handler();
final long start = SystemClock.uptimeMillis();
final float startRotation = st;
final long duration = 1555;
final Interpolator interpolator = new LinearInterpolator();
handler.post(new Runnable() {
@Override
public void run() {
long elapsed = SystemClock.uptimeMillis() - start;
float t = interpolator.getInterpolation((float) elapsed / duration);
float rot = t * toRotation + (1 - t) * startRotation;
marker.setRotation(-rot > 180 ? rot / 2 : rot);
if (t < 1.0) {
// Post again 16ms later.
handler.postDelayed(this, 16);
}
}
});
}
public void animateMarker(final LatLng toPosition,final boolean hideMarke) {
final Handler handler = new Handler();
final long start = SystemClock.uptimeMillis();
Projection proj = googleMap.getProjection();
Point startPoint = proj.toScreenLocation(m.getPosition());
final LatLng startLatLng = proj.fromScreenLocation(startPoint);
final long duration = 5000;
final Interpolator interpolator = new LinearInterpolator();
handler.post(new Runnable() {
@Override
public void run() {
long elapsed = SystemClock.uptimeMillis() - start;
float t = interpolator.getInterpolation((float) elapsed
/ duration);
double lng = t * toPosition.longitude + (1 - t)
* startLatLng.longitude;
double lat = t * toPosition.latitude + (1 - t)
* startLatLng.latitude;
m.setPosition(new LatLng(lat, lng));
if (t < 1.0) {
// Post again 16ms later.
handler.postDelayed(this, 16);
} else {
if (hideMarke) {
m.setVisible(false);
} else {
m.setVisible(true);
}
}
}
});
}
答案 3 :(得分:5)
最后编写的代码完全按照与 OLA CABS 类似的方式工作......
这是 -
将您的谷歌地图片段放在相对布局中,并将标记(如图像视图)放在中心 -
在您的片段代码中,一旦您设置了所有谷歌地图基本工作,请为 onMapReady(GoogleMap googleMap)功能编写以下代码 -
我的代码如下 -
//第1步 -
For i = 0 to 5
x = 4
InputSheet.Range("A1:C1").Offset(0, i * 4) = x
Next i
//第2步 -
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:id="@+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MapsActivity_for_request_pages" />
<ImageView
android:layout_width="30sp"
android:layout_height="30sp"
android:layout_centerInParent="true"
android:id="@+id/central_marker"
android:src="@drawable/marker_pic"/>
</RelativeLayout>
答案 4 :(得分:0)
首先,我要感谢@Vipin Negi和@Prasad都提供了如此出色且出色的代码。由于上面有许多悬而未决的查询,因此我想使以上所有内容变得更简单。伙计们,只需执行以下步骤即可实现标记旋转。
1。在MainActivity.java文件中定义以下两种方法
private double bearingBetweenLocations(LatLng latLng1, LatLng latLng2) {
double PI = 3.14159;
double lat1 = latLng1.latitude * PI / 180;
double long1 = latLng1.longitude * PI / 180;
double lat2 = latLng2.latitude * PI / 180;
double long2 = latLng2.longitude * PI / 180;
double dLon = (long2 - long1);
double y = Math.sin(dLon) * Math.cos(lat2);
double x = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1)
* Math.cos(lat2) * Math.cos(dLon);
double brng = Math.atan2(y, x);
brng = Math.toDegrees(brng);
brng = (brng + 360) % 360;
return brng;
}
&
private void rotateMarker(final Marker marker, final float toRotation) {
final Handler handler = new Handler();
final long start = SystemClock.uptimeMillis();
final float startRotation = marker.getRotation();
final long duration = 1000;
final Interpolator interpolator = new LinearInterpolator();
handler.post(new Runnable() {
@Override
public void run() {
long elapsed = SystemClock.uptimeMillis() - start;
float t = interpolator.getInterpolation((float) elapsed / duration);
float rot = t * toRotation + (1 - t) * startRotation;
marker.setRotation(-rot > 180 ? rot / 2 : rot);
if (t < 1.0) {
// Post again 16ms later.
handler.postDelayed(this, 16);
}
}
});
}
2。之后,将以下行添加到您希望标记旋转的代码中。
double bearing = bearingBetweenLocations(m.getPosition(), updatedLatLng);
rotateMarker(m, (float) bearing);
请注意,“ m”是您要旋转的标记对象。 而且,您完成了!!
如果需要与标记动画有关的帮助,可以使用this代码。
答案 5 :(得分:0)
尝试使用Google默认轮播或查看详细说明Markers Rotation
private void updateCamera(LatLng currentLatLng, Location location) {
//googleMap.clear();
if (marker == null) {
MarkerOptions options = new MarkerOptions();
options.position(currentLatLng);
options.icon(BitmapDescriptorFactory.fromResource(R.mipmap.ic_driver_car_pin_v));
options.flat(true);
options.anchor(0.5f, 0.5f);
marker = googleMap.addMarker(options);
} else {
marker.setPosition(currentLatLng);
marker.setRotation(location.getBearing());
}
CameraPosition cameraPosition = new CameraPosition.Builder(googleMap.getCameraPosition())
.target(currentLatLng).zoom(18).build();
googleMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
}