[java]
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
[java]
<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 );
[java]
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】,關鍵代碼如下:
[java]
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
[java]
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
[java]
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
[java]
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();
}