android 中,常用到的地图有百度地图、google地图、高德地图,由于项目中用到了高德,所有来做个总结。
接下来我们看看高德在android中的使用步骤:
1:相关的准备工作>>包括jar包的引入,相关权限的设置,mapview的布局
,在android的manifest.xml中加入如下的这些所需权限
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.CHANGE_CONFIGURATION" />
//高德所需要的唯一key[需要你在高德官网申请即可]
<meta-data android:name="com.amap.api.v2.apikey" android:value="0274d320d6e750dc88a8c10b1f69f5be" />
在 main.xml中放置我们要显示的map
<com.amap.mapapi.map.MapView android:id="@+id/mapview" android:layout_width="match_parent" android:layout_height="match_parent" android:clickable="true" />2:在MainActivity中获取map,并且做相应的初始化设置
myMapView = (MapView) findViewById( R.id.mapview );
private void initMapParameters() { myMapView.setBuiltInZoomControls( true ); myGestureDetector = new GestureDetector( this ); myMapView.setOnTouchListener( new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { myTapTime = new Date().getTime(); if (Math.abs( event.getEventTime() - myTapTime ) < 500) { if (Math.hypot( event.getX() - myTouch_x, event.getY() - myTouch_y ) < 100) { return true; } } myTapTime = event.getEventTime(); myTouch_x = event.getX(); myTouch_y = event.getY(); } return myGestureDetector.onTouchEvent( event ); } } ); myController = myMapView.getController(); }以上代码主要是完成map的初始化,同时将map的触发操作交给我们的GestureDetector来处理
3: 接下来我们自定义一个view用来显示地图上的标注信息【地图上自定义气泡组件】如图:
它不是我们的overlay,它是我们手动打到map上我们自定义的view,用来一些额外的操作,暂且我们命名为:widget_pop.xml相关的布局文件比较简单,与我们平常的布局没有任何区别;然后是我们自定义的widgetView类【主要完成在map上的展示:不是map的overlay】,关键代码如下:
private void initContentView() { myFrameLayout_Root = (FrameLayout) ((LayoutInflater) myContext.getSystemService( "layout_inflater" )).inflate( R.layout.widget_mappopview, null ); this.addView( myFrameLayout_Root ); myLinearLayout_Overlay_Small = (LinearLayout) findViewById( R.id.linear_pop_small ); myLinearLayout_Overlay_Small.setVisibility( View.VISIBLE ); myLinearLayout_Overlay_Big = (LinearLayout) findViewById( R.id.linear_pop_big ); android.view.ViewGroup.LayoutParams myLayoutParams = myLinearLayout_Overlay_Big.getLayoutParams(); if (LiftApplication.ScreenHeight == 0 | LiftApplication.ScreenWidth == 0) { AndroidSystemUtils.getScreenInfo( myActivity ); } myLayoutParams.width = (int) (LiftApplication.ScreenWidth * 0.8); myLayoutParams.height = LiftApplication.ScreenHeight / 3; myLinearLayout_Overlay_Big.setLayoutParams( myLayoutParams ); myLinearLayout_Overlay_Big.setVisibility( View.GONE ); myTextView_GPSTime = (TextView) findViewById( R.id.text_gpstime ); myTextView_Province = (TextView) findViewById( R.id.text_location_province ); myTextView_VehicleNumber = (TextView) findViewById( R.id.text_vehiclenumber ); myTextView_VehicleNumber_Small = (TextView) findViewById( R.id.text_vehiclenumber_small ); myButton_VehicleInfo = (Button) findViewById( R.id.btn_vehicledetail ); myLinearLayout_CurrentInfo = (LinearLayout) findViewById( R.id.linear_pop_currentinfo ); myLinearLayout_TraceInfo = (LinearLayout) findViewById( R.id.linear_pop_trace ); myLinearLayout_StatisticsInfo = (LinearLayout) findViewById( R.id.linear_pop_statistics ); }以上代码主要完成了用我们自己定义的布局来生成一个组合组件,展示到map上,同时可以对自定义的view的ui组件进行一些操作,例如获取到的buttong处理点击事件等等,这里要注意的是我们必须要添加相应的构造方法【这个内容是自定义组合组件的知识,不知道的话可以查查相关内容】,我们通过自定的构造函数从前台传过来一个相应的bean[包含经纬度、描述信息等等]就可以展示到我们的view上,同时当我们点击相应的按钮跳转到别的视图时将相应的信息的又可以传递过去。关键代码
: public MapPopView(Activity inActivity, Vehicle inVehicle, OnOverlayPopupListener inOverlayPopupListener)
{
this( inActivity.getApplicationContext() );
this.myContext = inActivity.getApplicationContext();
this.myActivity = inActivity;
this.myVehicle = inVehicle;
this.myOverlayPopupListener = inOverlayPopupListener;
initContentView();
fillContents();
}
4:我们接下来自定义map上始终显示的overlay
public class VehicleOverlay extends Overlay{ /** * Bitmap 图片 */ private Bitmap myBitmap_Overlay; /** * GeoPoint gps点 */ private GeoPoint myGeoPoint; /** * Creates a new instance of VehicleOverlay. * @param inGeoPoint * @param inBitmap_Overlay */ public VehicleOverlay(GeoPoint inGeoPoint, Bitmap inBitmap_Overlay) { super(); this.myGeoPoint = inGeoPoint; this.myBitmap_Overlay = inBitmap_Overlay; } /** * (non-Javadoc) * @see com.amap.mapapi.map.Overlay#draw(android.graphics.Canvas, com.amap.mapapi.map.MapView, boolean) */ @Override public void draw(Canvas canvas, MapView mapView, boolean shadow) { if (!shadow) { // 相当于屏幕坐标和地图点(经纬度)的转换器 Projection myProjection = mapView.getProjection(); Point myPoint = new Point(); // 将坐标点投射到屏幕上 myProjection.toPixels( myGeoPoint, myPoint ); // 由于图片指针在下方正中,所以将bitmap左移整图的一半宽,上移整图的高的距离 canvas.drawBitmap( myBitmap_Overlay, myPoint.x - myBitmap_Overlay.getWidth() / 2, myPoint.y - myBitmap_Overlay.getHeight(), null ); } }}这就是始终显示的map中的overlay,只要传递对应的经纬度既可以在map上展示
5:从服务端获取实时的信息,将我们的overlay和MapPopView展示到map上【这两者的主要区别是:所有的overlay以一种视图始终展示在map上,而mappopview根据我们的需要可以切换展示不同的视图】
从服务器获取信息bean的过程就不贴出来了,无非就是启动一个线程去获取即可此时我们获取到的可能不止有一个bean信息,或许是多个bean信息,我们将可以将它们放到一个list中,通过一个for循环全部展示处理。下面的代码展示了如何根据获取到的bean来展示mappopview 和添加overlay
//添加一个mappopview
protected void showSingleDistribution(Vehicle inVehicle) { GeoPoint myGeoPoint = new GeoPoint( (int) (inVehicle.getLatitude() * 1E6), (int) (inVehicle.getLongitude() * 1E6) ); MapPopView myView = new MapPopView( this, inVehicle, this ); MapView.LayoutParams myLayoutParams = new MapView.LayoutParams( MapView.LayoutParams.WRAP_CONTENT, MapView.LayoutParams.WRAP_CONTENT, myGeoPoint, MapView.LayoutParams.BOTTOM_CENTER ); myLayoutParams.mode = MapView.LayoutParams.MODE_MAP; myLayoutParams.y -= 50; myMapView.addView( myView, myLayoutParams ); myMapPopViews.add( myView ); showSingleLocationOnMap( myGeoPoint, inVehicle ); myGeoPoints.add( myGeoPoint ); }//添加一个overlay
private void showSingleLocationOnMap(GeoPoint inGeoPoint, Vehicle inVehicle) { if (myMapView != null && myMapView.getOverlays() != null) { VehicleOverlay myCaroverlay = new VehicleOverlay( inGeoPoint, VehicleStatusBitmapUtil.getStatusBitmap( getApplicationContext(), Integer.parseInt( inVehicle.getVI_STATUS() ) ) ); myMapView.getOverlays().add( myCaroverlay ); } }经过上面的5个步骤,我们基本完成了将一个自定义的view添加到map,同时展示对应的overlay的过程。。。。。。
也有一些其它的细节需要注意,就是当我们点击map视图时,其它的视图应该恢复的初始状态,也就是在GestureDetetor的
@Override
public boolean onSingleTapUp(MotionEvent e)
{
//恢复相关的状态
shrinkAllPopup();
return false;
}
private void shrinkAllPopup()
{
if (myMapPopViews != null)
for ( MapPopView tempMapPopView : myMapPopViews )
tempMapPopView.shrinkPopView();
}
下面链接几个关键类:高德地图关键类