Android Google Maps V2之动态Polyline

Android Google Maps V2之动态Polyline_第1张图片

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 );
		}
	}

}

这个的关键代码是onDraw里面的 DashPathEffect这个类,有兴趣的朋友可以研究下。

你可能感兴趣的:(谷歌地图,google,maps,polyline,V2,动态Polyline)