1,首先在Maps上添加路径Ployline的代码实现如下:
public Polyline addMarker( List latLngs )
{
Polyline polyline = null;
GoogleMap map = supportMapFragment.getMap( );
if ( map != null )
{
PolylineOptions polylineOptions = new PolylineOptions( );
polylineOptions = new PolylineOptions( );
polylineOptions.width( STROKE_WIDTH );
polylineOptions.color( fillColor );
polylineOptions.geodesic( true );
for ( LatLng latLng : latLngs )
{
polylineOptions.add( latLng );
}
polyline = map.addPolyline( mPolylineOptions );
}
return polyline;
}
2, 在项目过程中,我们需要把这条线动态的去添加到Google maps 上,也就是让这个polyline动起来,让线一点一点的画,像是在地图上行进一样,应该怎么实现呢?下面我的实现拿出来给大家讨论下,如果大家有更好的办法也拿出来讨论,大家一起提高嘛!
(1)首先我们已知起点和目的地,并不知道整个路径是怎么样的。那么我们就必须通过已知的两点去请求google Api去得到整个的路径集合,具体方法可以去看看google的官方文档:https://developers.google.com/maps/documentation/directions/ , 其实就是请求http://maps.googleapis.com/maps/api/directions/json?parameters,得到一个JSON文件,解析就可以获得这个两点之间的路径。
(2)我们通过SupportMapFragment的getView可以的View, 其实这个View就是FrameLayout, 知道是FrameLayout就好办了, 我们直接在整个View的上面再覆盖一个View就可以了,然后在这个自定义VIew里面写上动画,就大功告成了!好了,来看看我是怎么写这个View的。大家注意这里的Routes是通过前面的Json解析而来的。
public class RouteOverlay extends View
{
private static final int DEFAULT_ZOOM = 16;
// max distance is 25 MI
private final static double MAX_DISTANCE = 40233.6;
private final static int STROKE_WIDTH = 8;
private final static float SPEEDS = 20.0f;
private List mLatLngs;
private GoogleMap map;
private Path mRoutePath;
private PathMeasure mPathMeasure;
private PolylineOptions mPolylineOptions;
private Paint paint;
private float[] mIntervals =
{
0f, 0f
};
private boolean isDrawing = false;
private Polyline polyline;
private CameraPosition cameraPosition;
private Marker replayMarker;
private LatLng start;
private LatLng end;
private Marker endMarker;
private LatLngBounds bounds;
private int boundsPadding;
private int fillColor;
private double mDistance = .0;
public RouteOverlay( Context context, AttributeSet attrs, int defStyle )
{
super( context, attrs, defStyle );
setUpView( context );
}
public RouteOverlay( Context context, AttributeSet attrs )
{
super( context, attrs );
setUpView( context );
}
public RouteOverlay( Context context )
{
super( context );
setUpView( context );
}
private void setUpView( Context context )
{
boundsPadding = ( int ) getResources( ).getDimension( R.dimen.map_bounds_padding );
fillColor = context.getResources( ).getColor( R.color.color_hibu_blue );
paint = new Paint( Paint.ANTI_ALIAS_FLAG );
paint.setAntiAlias( true );
paint.setColor( fillColor );
paint.setStrokeWidth( STROKE_WIDTH );
paint.setStyle( Paint.Style.STROKE );
}
public void initialize( GoogleMap map, Routes routes )
{
if ( routes == null )
{
return;
}
if ( routes.getLegs( ) == null )
{
return;
}
Leg leg = routes.getLegs( ).get( 0 );
this.mLatLngs = leg.getPoints( );
this.map = map;
int count = mLatLngs.size( );
start = mLatLngs.get( 0 );
end = mLatLngs.get( count - 1 );
String distance = leg.getDistance( ).getValue( );
if ( AppUtils.isNumeric( distance ) )
{
mDistance = Double.valueOf( distance );
}
bounds = routes.getBounds( );
}
public void onPolyCancel( )
{
isDrawing = false;
}
public void onPolyEnd( )
{
isDrawing = false;
setVisibility( View.GONE );
setFreezeMap( false );
showPolyLine( );
cameraPosition = map.getCameraPosition( );
}
public void onPolyRepeat( )
{
if ( isDrawing )
{
return;
}
if ( endMarker == null )
{
this.map.clear( );
// add start point marker
BitmapDescriptor icon = BitmapDescriptorFactory
.fromResource( R.drawable.current_location_marker );
addMarker( start, icon );
// add end point marker
icon = BitmapDescriptorFactory.fromResource( R.drawable.poly_end_marker );
endMarker = addMarker( end, icon );
}
boolean isPositionChanged = !map.getCameraPosition( ).equals( cameraPosition );
if ( isPositionChanged )
{
animateCamera( replayCallback );
}
else
{
executeViewTask( );
}
}
public void onPolyStart( )
{
if ( mPathMeasure == null && mPolylineOptions == null )
{
return;
}
if ( mDistance > MAX_DISTANCE )
{
onPolyEnd( );
return;
}
isDrawing = true;
setVisibility( View.VISIBLE );
mIntervals[0] = 0;
mIntervals[1] = mPathMeasure.getLength( );
dismissReplayMarker( );
dismissPolyLine( );
setFreezeMap( true );
invalidate( );
}
@Override
protected void onDraw( Canvas canvas )
{
super.onDraw( canvas );
doDraw( canvas );
}
public Marker getReorientMarker( )
{
if ( endMarker != null )
{
return endMarker;
}
return null;
}
private void computeRoutes( Projection projection )
{
if ( projection == null )
{
return;
}
mPolylineOptions = new PolylineOptions( );
mPolylineOptions.width( STROKE_WIDTH );
mPolylineOptions.color( fillColor );
mPolylineOptions.geodesic( true );
mRoutePath = new Path( );
boolean isOrigin = true;
for ( LatLng latLng : mLatLngs )
{
mPolylineOptions.add( latLng );
Point point = projection.toScreenLocation( latLng );
if ( isOrigin )
{
mRoutePath.moveTo( point.x, point.y );
isOrigin = false;
}
else
{
mRoutePath.lineTo( point.x, point.y );
}
}
mPathMeasure = new PathMeasure( );
mPathMeasure.setPath( mRoutePath, false );
}
private void doDraw( Canvas canvas )
{
if ( !isDrawing )
{
return;
}
if ( mIntervals[1] <= 0 )
{
if ( mIntervals[0] <= 0f )
{
// do nothing.
}
else
{
onPolyEnd( );
return;
}
}
else
{
synchronized ( canvas )
{
// when animating adjust the path effect param to adapt the
// arrow
float dlt = 12.0f;
float[] tempIntervals = new float[]
{
mIntervals[0] - dlt, mIntervals[1] + dlt
};
DashPathEffect pathEffect = new DashPathEffect( tempIntervals, 0f );
paint.setPathEffect( pathEffect );
// draw the path
canvas.drawPath( mRoutePath, paint );
}
// Update the path effects values, to draw a little more
// on the path.
mIntervals[0] += SPEEDS;
mIntervals[1] -= SPEEDS;
this.invalidate( );
}
}
private void setFreezeMap( Boolean isFreeze )
{
map.getUiSettings( ).setAllGesturesEnabled( !isFreeze );
}
private void showPolyLine( )
{
if ( polyline == null )
{
polyline = map.addPolyline( mPolylineOptions );
}
polyline.setVisible( true );
}
private void dismissPolyLine( )
{
if ( polyline != null )
{
polyline.setVisible( false );
}
}
private void dismissReplayMarker( )
{
if ( replayMarker != null )
{
replayMarker.setVisible( false );
}
}
public Marker addMarker( LatLng position, BitmapDescriptor icon )
{
if ( position == null )
{
return null;
}
if ( icon == null )
{
icon = BitmapDescriptorFactory.fromResource( R.drawable.marker );
}
MarkerOptions options = new MarkerOptions( );
options.icon( icon );
return map.addMarker( options.position( position ) );
}
private void animateCamera( GoogleMap.CancelableCallback callback )
{
if ( bounds == null )
{
return;
}
CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngBounds( bounds, boundsPadding );
map.animateCamera( cameraUpdate, callback );
}
private GoogleMap.CancelableCallback replayCallback = new GoogleMap.CancelableCallback( )
{
@Override
public void onFinish( )
{
executeViewTask( );
}
@Override
public void onCancel( )
{
onPolyCancel( );
}
};
private void executeViewTask( )
{
new AsyncTask( )
{
@Override
protected Void doInBackground( Projection... params )
{
Projection projection = params[0];
if ( mPathMeasure == null && mPolylineOptions == null )
{
computeRoutes( projection );
}
return null;
}
protected void onPostExecute( Void result )
{
onPolyStart( );
}
}.execute( map.getProjection( ) );
}
public void reset( int visibleMapHeight )
{
dismissPolyLine( );
moveCamera( end, DEFAULT_ZOOM, visibleMapHeight );
}
public void moveCamera( LatLng position, int zoom, int offset )
{
if ( map != null && position != null )
{
CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom( position, zoom );
map.moveCamera( cameraUpdate );
Point point = map.getProjection( ).toScreenLocation( position );
cameraUpdate = CameraUpdateFactory.scrollBy( 0, Math.abs( offset / 2 - point.y ) );
map.animateCamera( cameraUpdate );
}
}
}