集成地图SDK
国内常用的地图SDK就是百度和高德了,二者的用法大同小异,可按照官网上的开发指南一步步来。下面是我在集成地图SDK时遇到的问题说明:
1、点击基本地图功能选项,不能打开地图,弹出“key验证出错!请在AndroidManifest.xml文件中检查key设置的”的红色字提示。查看日志提示“galaxy lib host missing meta-data,make sure you know the right way to integrate galaxy”
该问题是因为key值对应的签名与app打包用的签名不一致。app在开发时与发布时有两个不同的签名,开发时用的是ADT默认签名,查看默认签名的SHA1值可依次选择“Window”->“Preferences”->“Android”->“Build SHA1 fingerprint”。app发布时的签名是密钥文件的签名,查看发布签名的SHA1值可依次选择“File”->“Export”->“Export Android Application”->“Next”后选择密钥文件并输入密码与app输出路径->在“Certificate
fingerprints”下查看SHA1值。
2、百度地图SDK3.6及以上版本找不到overlayutil包。
这是因为新版SDK的jar包不再包含这部分源码,得到官方demo的src目录下获取源码加入到开发者自己的工程中,源码路径为:BaiduMap_AndroidMapSDK_v3.7.1_Sample\BaiduMapsApiDemo\src\com\baidu\mapapi
3、在一个工程中同时包含了百度地图和高德地图的sdk,编译时报错“Found duplicate file for APK: assets/lineDashTexture.png”。
这是因为百度和高德的sdk,其jar包存在同名文件“assets/lineDashTexture.png”,所以无法通过编译。即百度sdk与高德sdk是互斥的,不能同时存在于同个工程中,必须分开来使用。
显示地图和定位
对于一个地图SDK来说,首先要显示地图,然后定位到当前城市。
这方面百度地图和高德地图的处理代码差不多,下面是两种地图sdk显示并定位的代码例子:
百度地图
// 以下主要是定位用到的代码 private MapView mMapView; private BaiduMap mMapLayer; private LocationClient mLocClient; private boolean isFirstLoc = true;// 是否首次定位 private void initLocation() { mMapView = (MapView) findViewById(R.id.bmapView); // 先隐藏地图,待定位到当前城市时再显示 mMapView.setVisibility(View.INVISIBLE); mMapLayer = mMapView.getMap(); mMapLayer.setOnMapClickListener(this); // 开启定位图层 mMapLayer.setMyLocationEnabled(true); mLocClient = new LocationClient(this); // 设置定位监听器 mLocClient.registerLocationListener(new MyLocationListenner()); LocationClientOption option = new LocationClientOption(); option.setOpenGps(true);// 打开gps option.setCoorType("bd09ll"); // 设置坐标类型 option.setScanSpan(1000); option.setIsNeedAddress(true); // 设置true才能获得详细的地址信息 // 设置定位参数 mLocClient.setLocOption(option); // 开始定位 mLocClient.start(); //获取最近一次的位置 // mLocClient.getLastKnownLocation(); } public class MyLocationListenner implements BDLocationListener { @Override public void onReceiveLocation(BDLocation location) { // map view 销毁后不在处理新接收的位置 if (location == null || mMapView == null) { Log.d(TAG, "location is null or mMapView is null"); return; } m_latitude = location.getLatitude(); m_longitude = location.getLongitude(); String position = String.format("当前位置:%s|%s|%s|%s|%s|%s|%s", location.getProvince(), location.getCity(), location.getDistrict(), location.getStreet(), location.getStreetNumber(), location.getAddrStr(), location.getTime()); loc_position.setText(position); MyLocationData locData = new MyLocationData.Builder() .accuracy(location.getRadius()) // 此处设置开发者获取到的方向信息,顺时针0-360 .direction(100).latitude(m_latitude) .longitude(m_longitude).build(); mMapLayer.setMyLocationData(locData); if (isFirstLoc) { isFirstLoc = false; LatLng ll = new LatLng(m_latitude, m_longitude); MapStatusUpdate update = MapStatusUpdateFactory.newLatLngZoom(ll, 14); mMapLayer.animateMapStatus(update); // 定位到当前城市时再显示图层 mMapView.setVisibility(View.VISIBLE); } } public void onReceivePoi(BDLocation poiLocation) { } }
高德地图
// 以下主要是定位用到的代码 private MapView mMapView; private AMap mMapLayer; private AMapLocationClient mLocClient; private boolean isFirstLoc = true;// 是否首次定位 private void initLocation(Bundle savedInstanceState) { mMapView = (MapView) findViewById(R.id.amapView); mMapView.onCreate(savedInstanceState); // 先隐藏地图,待定位到当前城市时再显示 mMapView.setVisibility(View.INVISIBLE); if (mMapLayer == null) { mMapLayer = mMapView.getMap(); } mMapLayer.setOnMapClickListener(this); // 开启定位图层 mMapLayer.setMyLocationEnabled(true); mMapLayer.setMyLocationType(AMap.LOCATION_TYPE_LOCATE); mLocClient = new AMapLocationClient(this.getApplicationContext()); // 设置定位监听器 mLocClient.setLocationListener(new MyLocationListenner()); AMapLocationClientOption option = new AMapLocationClientOption(); option.setLocationMode(AMapLocationMode.Battery_Saving); option.setNeedAddress(true); // 设置true才能获得详细的地址信息 // 设置定位参数 mLocClient.setLocationOption(option); // 开始定位 mLocClient.startLocation(); //获取最近一次的位置 // mLocClient.getLastKnownLocation(); } public class MyLocationListenner implements AMapLocationListener { @Override public void onLocationChanged(AMapLocation location) { // map view 销毁后不在处理新接收的位置 if (location == null || mMapView == null) { Log.d(TAG, "location is null or mMapView is null"); return; } m_latitude = location.getLatitude(); m_longitude = location.getLongitude(); String position = String.format("当前位置:%s|%s|%s|%s|%s|%s|%s", location.getProvince(), location.getCity(), location.getDistrict(), location.getStreet(), location.getAdCode(), location.getAddress(), location.getTime()); loc_position.setText(position); if (isFirstLoc) { isFirstLoc = false; LatLng ll = new LatLng(m_latitude, m_longitude); CameraUpdate update = CameraUpdateFactory.newLatLngZoom(ll, 12); mMapLayer.moveCamera(update); // 定位到当前城市时再显示图层 mMapView.setVisibility(View.VISIBLE); } } }
POI搜索
POI即地图注点,它是“Point of Interest”的缩写,在地图上标注地点名称、类别、经度、纬度等信息,是一个带位置信息的地图标注。POI搜索是地图sdk的一个重要应用,根据关键字搜索并在地图上显示POI结果,这是智能出行的基础。
下面是使用百度地图搜索POI的截图:
下面是两种地图sdk进行POI搜索的代码例子:
百度地图
// 以下主要是POI搜索用到的代码 private PoiSearch mPoiSearch = null; private SuggestionSearch mSuggestionSearch = null; private AutoCompleteTextView mKey = null; private EditText mScope = null; private Button btn_search, btn_nextpage, btn_cleardata; private ArrayAdapter<String> sugAdapter = null; private int load_Index = 0; private void initMap() { mPoiSearch = PoiSearch.newInstance(); mPoiSearch.setOnGetPoiSearchResultListener(this); mSuggestionSearch = SuggestionSearch.newInstance(); mSuggestionSearch.setOnGetSuggestionResultListener(this); mScope = (EditText) findViewById(R.id.poi_city); mKey = (AutoCompleteTextView) findViewById(R.id.poi_searchkey); btn_search = (Button) findViewById(R.id.search); btn_nextpage = (Button) findViewById(R.id.map_next_data); btn_cleardata = (Button) findViewById(R.id.map_clear_data); btn_search.setOnClickListener(this); btn_nextpage.setOnClickListener(this); btn_cleardata.setOnClickListener(this); sugAdapter = new ArrayAdapter<String>(this, R.layout.spinner_dropdown_item); mKey.setAdapter(sugAdapter); // 当输入关键字变化时,动态更新建议列表 mKey.addTextChangedListener(new TextWatcher() { @Override public void afterTextChanged(Editable arg0) { } @Override public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) { } @Override public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) { if (cs.length() <= 0) { return; } String city = mScope.getText().toString(); // 使用建议搜索服务获取建议列表,结果在onGetSuggestionResult中更新 mSuggestionSearch .requestSuggestion((new SuggestionSearchOption()) .keyword(cs.toString()).city(city)); } }); } @Override public void onGetSuggestionResult(SuggestionResult res) { if (res == null || res.getAllSuggestions() == null) { return; } else { sugAdapter.clear(); for (SuggestionResult.SuggestionInfo info : res.getAllSuggestions()) { if (info.key != null) { sugAdapter.add(info.key); } } sugAdapter.notifyDataSetChanged(); } } // 影响搜索按钮点击事件 public void searchButtonProcess(View v) { Log.d(TAG, "editCity=" + mScope.getText().toString() + ", editSearchKey=" + mKey.getText().toString() + ", load_Index=" + load_Index); String keyword = mKey.getText().toString(); if (search_method == SEARCH_CITY) { String city = mScope.getText().toString(); mPoiSearch.searchInCity((new PoiCitySearchOption()).city(city) .keyword(keyword).pageNum(load_Index)); } else if (search_method == SEARCH_NEARBY) { LatLng position = new LatLng(m_latitude, m_longitude); int radius = Integer.parseInt(mScope.getText().toString()); mPoiSearch.searchNearby((new PoiNearbySearchOption()) .location(position).keyword(keyword).radius(radius) .pageNum(load_Index)); } } public void goToNextPage(View v) { load_Index++; searchButtonProcess(null); } public void onGetPoiResult(PoiResult result) { if (result == null || result.error == SearchResult.ERRORNO.RESULT_NOT_FOUND) { Toast.makeText(this, "未找到结果", Toast.LENGTH_LONG).show(); return; } else if (result.error == SearchResult.ERRORNO.NO_ERROR) { mMapLayer.clear(); PoiOverlay overlay = new MyPoiOverlay(mMapLayer); mMapLayer.setOnMarkerClickListener(overlay); List<PoiInfo> poiList = result.getAllPoi(); overlay.setData(result); overlay.addToMap(); overlay.zoomToSpan(); // for (PoiInfo poi : poiList) { // String detail = String.format( // "uid=%s,city=%s,name=%s,phone=%s, address=%s", poi.uid, // poi.city, poi.name, poi.phoneNum, poi.address); // Log.d(TAG, detail); // 坐标为poi.location(LatLng结构) // } } else if (result.error == SearchResult.ERRORNO.AMBIGUOUS_KEYWORD) { // 当输入关键字在本市没有找到,但在其他城市找到时,返回包含该关键字信息的城市列表 String strInfo = "在"; for (CityInfo cityInfo : result.getSuggestCityList()) { strInfo += cityInfo.city + ","; } strInfo += "找到结果"; Toast.makeText(this, strInfo, Toast.LENGTH_LONG).show(); } } public void onGetPoiDetailResult(PoiDetailResult result) { if (result.error != SearchResult.ERRORNO.NO_ERROR) { Toast.makeText(this, "抱歉,未找到结果", Toast.LENGTH_SHORT).show(); } else { Log.d(TAG, "name=" + result.getName() + ",address=" + result.getAddress() + ",detail_url=" + result.getDetailUrl() + ",shop_hours=" + result.getShopHours() + ",telephone=" + result.getTelephone() + ",price=" + result.getPrice() + ",type=" + result.getType() + ",tag=" + result.getTag()); Toast.makeText(this, result.getName() + ": " + result.getAddress(), Toast.LENGTH_SHORT).show(); } } private class MyPoiOverlay extends PoiOverlay { public MyPoiOverlay(BaiduMap baiduMap) { super(baiduMap); } @Override public boolean onPoiClick(int index) { super.onPoiClick(index); PoiInfo poi = getPoiResult().getAllPoi().get(index); mPoiSearch.searchPoiDetail((new PoiDetailSearchOption()).poiUid(poi.uid)); return true; } }
高德地图
// 以下主要是POI搜索用到的代码 private PoiSearch mPoiSearch = null; private AutoCompleteTextView mKey = null; private EditText mScope = null; private Button btn_search, btn_nextpage, btn_cleardata; private ArrayAdapter<String> sugAdapter = null; private int load_Index = 0; private void initMap() { mScope = (EditText) findViewById(R.id.poi_city); mKey = (AutoCompleteTextView) findViewById(R.id.poi_searchkey); btn_search = (Button) findViewById(R.id.search); btn_nextpage = (Button) findViewById(R.id.map_next_data); btn_cleardata = (Button) findViewById(R.id.map_clear_data); btn_search.setOnClickListener(this); btn_nextpage.setOnClickListener(this); btn_cleardata.setOnClickListener(this); sugAdapter = new ArrayAdapter<String>(this, R.layout.spinner_dropdown_item); mKey.setAdapter(sugAdapter); // 当输入关键字变化时,动态更新建议列表 mKey.addTextChangedListener(new TextWatcher() { @Override public void afterTextChanged(Editable arg0) { } @Override public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) { } @Override public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) { if (cs.length() <= 0) { return; } String city = mScope.getText().toString(); // 使用建议搜索服务获取建议列表,结果在onGetInputtips中更新 InputtipsQuery inputquery = new InputtipsQuery(cs.toString(), city); Inputtips inputTips = new Inputtips(GaodeActivity.this, inputquery); inputTips.setInputtipsListener(GaodeActivity.this); inputTips.requestInputtipsAsyn(); } }); } @Override public void onGetInputtips(List<Tip> tipList, int rCode) { if (rCode != 1000) { Toast.makeText(this, "推荐文字错误代码是"+rCode, Toast.LENGTH_LONG).show(); } else { sugAdapter.clear(); for (Tip info : tipList) { if (info.getName() != null) { sugAdapter.add(info.getName()); } } sugAdapter.notifyDataSetChanged(); } } // 影响搜索按钮点击事件 public void searchButtonProcess(View v) { Log.d(TAG, "editCity=" + mScope.getText().toString() + ", editSearchKey=" + mKey.getText().toString() + ", load_Index=" + load_Index); String keyword = mKey.getText().toString(); if (search_method == SEARCH_CITY) { String city = mScope.getText().toString(); PoiSearch.Query query = new PoiSearch.Query(keyword, null, city); query.setPageSize(10); query.setPageNum(load_Index); mPoiSearch = new PoiSearch(this, query); mPoiSearch.setOnPoiSearchListener(this); mPoiSearch.searchPOIAsyn(); } else if (search_method == SEARCH_NEARBY) { LatLonPoint position = new LatLonPoint(m_latitude, m_longitude); int radius = Integer.parseInt(mScope.getText().toString()); PoiSearch.Query query = new PoiSearch.Query(keyword, null, "福州"); query.setPageSize(10); query.setPageNum(load_Index); mPoiSearch = new PoiSearch(this, query); SearchBound bound = new SearchBound(position, radius); mPoiSearch.setBound(bound); mPoiSearch.setOnPoiSearchListener(this); mPoiSearch.searchPOIAsyn(); } } public void goToNextPage(View v) { load_Index++; searchButtonProcess(null); } @Override public void onPoiSearched(PoiResult result, int rCode) { if (rCode != 1000) { Toast.makeText(this, "POI错误代码是"+rCode, Toast.LENGTH_LONG).show(); } else if (result == null || result.getQuery() == null) { Toast.makeText(this, "未找到结果", Toast.LENGTH_LONG).show(); return; } else { mMapLayer.clear(); List<PoiItem> poiList = result.getPois(); // 当搜索不到poiitem数据时,会返回含有搜索关键字的城市信息 List<SuggestionCity> suggestionCities = result.getSearchSuggestionCitys(); if (poiList!=null && poiList.size()>0) { PoiOverlay poiOverlay = new PoiOverlay(mMapLayer, poiList); //从地图上移除原POI信息 poiOverlay.removeFromMap(); //往地图添加新POI信息 poiOverlay.addToMap(); poiOverlay.zoomToSpan(); //给POI添加监听器。在点击POI时提示POI信息 mMapLayer.setOnMarkerClickListener(new OnMarkerClickListener() { @Override public boolean onMarkerClick(Marker marker) { marker.showInfoWindow(); return true; } }); // for (PoiItem poi : poiList) { // String detail = String.format( // "uid=%s,city=%s,name=%s,phone=%s, address=%s", poi.getPoiId(), // poi.getCityName(), poi.getTitle(), poi.getTel(), poi.getAdName()); // Log.d(TAG, detail); // 坐标为poi.location(LatLng结构) // } } else if (suggestionCities != null && suggestionCities.size() > 0) { String infomation = "推荐城市\n"; for (int i = 0; i < suggestionCities.size(); i++) { SuggestionCity city = suggestionCities.get(i); infomation += "城市名称:" + city.getCityName() + "城市区号:" + city.getCityCode() + "城市编码:" + city.getAdCode() + "\n"; } Toast.makeText(this, infomation, Toast.LENGTH_LONG).show(); } else { Toast.makeText(this, "结果记录数为0", Toast.LENGTH_LONG).show(); } return; } } @Override public void onPoiItemSearched(PoiItem paramPoiItem, int paramInt) { // TODO Auto-generated method stub }
测距、测面积
测量距离和测量面积是地图sdk的又一个应用,除了在地图上添加标注之外,就是要用到数学的两个公式。
其中测距用的是勾股定理(又名商高定理):勾股定理是一个基本的几何定理:一个直角三角形,两直角边的平方和等于斜边的平方。如果直角三角形两直角边为a和b,斜边为c,那么a*a+b*b=c*c
测面积用的是海伦公式(又名秦九韶公式):海伦公式是利用三角形的三个边长直接求三角形面积的公式,表达式为:S=√p(p-a)(p-b)(p-c)。基于海伦公式,可以推导出根据多边形各边长求多边形面积的公式,即S = 0.5 * ( (x0*y1-x1*y0) + (x1*y2-x2*y1) + ... + (xn*y0-x0*yn) )
两种地图sdk在测量上的数学原理是一样的,只在添加地图标注上有些小差异,下面是使用高德地图进行测量的截图:
下面是两种地图sdk进行测量的代码例子:
百度地图
// 下面是在地图上添加绘图操作 private static int lineColor = 0x55FF0000; private static int arcColor = 0xbb00FFFF; private static int textColor = 0x990000FF; private static int polygonColor = 0x77FFFF00; private static int radius = 100; private ArrayList<LatLng> posArray = new ArrayList<LatLng>(); boolean is_polygon = false; private void addDot(LatLng pos) { if (is_polygon == true && posArray.size() > 1 && MapUtil.isInsidePolygon(pos, posArray) == true) { Log.d(TAG, "isInsidePolygon"); LatLng centerPos = MapUtil.getCenterPos(posArray); OverlayOptions ooText = new TextOptions().bgColor(0x00ffffff) .fontSize(26).fontColor(textColor).text("标题")// .rotate(-30) .position(centerPos); mMapLayer.addOverlay(ooText); return; } if (is_polygon == true) { Log.d(TAG, "is_polygon == true"); posArray.clear(); is_polygon = false; } boolean is_first = false; LatLng thisPos = pos; if (posArray.size() > 0) { LatLng firstPos = posArray.get(0); int distance = (int) Math.round(MapUtil.getShortDistance( thisPos.longitude, thisPos.latitude, firstPos.longitude, firstPos.latitude)); //多次点击起点,要忽略之 if (posArray.size()==1 && distance<=0) { return; } else if (posArray.size() > 1) { LatLng lastPos = posArray.get(posArray.size()-1); int lastDistance = (int) Math.round(MapUtil.getShortDistance( thisPos.longitude, thisPos.latitude, lastPos.longitude, lastPos.latitude)); //重复响应当前位置的点击,要忽略之 if (lastDistance <= 0) { return; } } if (distance < radius * 2) { thisPos = firstPos; is_first = true; } Log.d(TAG, "distance="+distance+", radius="+radius+", is_first="+is_first); // 画直线 LatLng lastPos = posArray.get(posArray.size() - 1); List<LatLng> points = new ArrayList<LatLng>(); points.add(lastPos); points.add(thisPos); OverlayOptions ooPolyline = new PolylineOptions().width(2) .color(lineColor).points(points); mMapLayer.addOverlay(ooPolyline); // 下面计算两点之间距离 distance = (int) Math.round(MapUtil.getShortDistance( thisPos.longitude, thisPos.latitude, lastPos.longitude, lastPos.latitude)); String disText = ""; if (distance > 1000) { disText = Math.round(distance * 10 / 1000) / 10d + "公里"; } else { disText = distance + "米"; } LatLng llText = new LatLng( (thisPos.latitude + lastPos.latitude) / 2, (thisPos.longitude + lastPos.longitude) / 2); OverlayOptions ooText = new TextOptions().bgColor(0x00ffffff) .fontSize(24).fontColor(textColor).text(disText)// .rotate(-30) .position(llText); mMapLayer.addOverlay(ooText); } if (is_first != true) { // 画圆圈 OverlayOptions ooCircle = new CircleOptions().fillColor(lineColor) .center(thisPos).stroke(new Stroke(2, 0xAAFF0000)).radius(radius); mMapLayer.addOverlay(ooCircle); // 画图片标记 BitmapDescriptor bitmapDesc = BitmapDescriptorFactory .fromResource(R.drawable.icon_geo); OverlayOptions ooMarker = new MarkerOptions().draggable(false) .visible(true).icon(bitmapDesc).position(thisPos); mMapLayer.addOverlay(ooMarker); mMapLayer.setOnMarkerClickListener(new OnMarkerClickListener() { @Override public boolean onMarkerClick(Marker marker) { LatLng markPos = marker.getPosition(); addDot(markPos); return true; } }); } else { Log.d(TAG, "posArray.size()="+posArray.size()); //可能存在地图与标记同时响应点击事件的情况 if (posArray.size() < 3) { posArray.clear(); is_polygon = false; return; } // 画多边形 OverlayOptions ooPolygon = new PolygonOptions().points(posArray) .stroke(new Stroke(1, 0xFF00FF00)) .fillColor(polygonColor); mMapLayer.addOverlay(ooPolygon); is_polygon = true; // 下面计算多边形的面积 LatLng centerPos = MapUtil.getCenterPos(posArray); double area = Math.round(MapUtil.getArea(posArray)); String areaText = ""; if (area > 1000000) { areaText = Math.round(area * 100 / 1000000) / 100d + "平方公里"; } else { areaText = (int) area + "平方米"; } OverlayOptions ooText = new TextOptions().bgColor(0x00ffffff) .fontSize(26).fontColor(textColor).text(areaText)// .rotate(-30) .position(centerPos); mMapLayer.addOverlay(ooText); } posArray.add(thisPos); if (posArray.size() >= 3) { // 画弧线 OverlayOptions ooArc = new ArcOptions() .color(arcColor) .width(2) .points(posArray.get(posArray.size() - 1), posArray.get(posArray.size() - 2), posArray.get(posArray.size() - 3)); mMapLayer.addOverlay(ooArc); } } @Override public void onMapClick(LatLng arg0) { addDot(arg0); } @Override public boolean onMapPoiClick(MapPoi arg0) { addDot(arg0.getPosition()); return false; }
高德地图
// 下面是在地图上添加绘图操作 private static int lineColor = 0x55FF0000; private static int arcColor = 0xbb00FFFF; private static int textColor = 0x990000FF; private static int polygonColor = 0x77FFFF00; private static int radius = 100; private ArrayList<LatLng> posArray = new ArrayList<LatLng>(); boolean is_polygon = false; private void addDot(LatLng pos) { if (is_polygon == true && posArray.size() > 1 && MapUtil.isInsidePolygon(pos, posArray) == true) { Log.d(TAG, "isInsidePolygon"); LatLng centerPos = MapUtil.getCenterPos(posArray); TextOptions ooText = new TextOptions().backgroundColor(0x00ffffff) .fontSize(26).fontColor(textColor).text("标题")// .rotate(-30) .position(centerPos); mMapLayer.addText(ooText); return; } if (is_polygon == true) { Log.d(TAG, "is_polygon == true"); posArray.clear(); is_polygon = false; } boolean is_first = false; LatLng thisPos = pos; if (posArray.size() > 0) { LatLng firstPos = posArray.get(0); int distance = (int) Math.round(MapUtil.getShortDistance( thisPos.longitude, thisPos.latitude, firstPos.longitude, firstPos.latitude)); //多次点击起点,要忽略之 if (posArray.size()==1 && distance<=0) { return; } else if (posArray.size() > 1) { LatLng lastPos = posArray.get(posArray.size()-1); int lastDistance = (int) Math.round(MapUtil.getShortDistance( thisPos.longitude, thisPos.latitude, lastPos.longitude, lastPos.latitude)); //重复响应当前位置的点击,要忽略之 if (lastDistance <= 0) { return; } } if (distance < radius * 2) { thisPos = firstPos; is_first = true; } Log.d(TAG, "distance="+distance+", radius="+radius+", is_first="+is_first); // 画直线 LatLng lastPos = posArray.get(posArray.size() - 1); List<LatLng> points = new ArrayList<LatLng>(); points.add(lastPos); points.add(thisPos); PolylineOptions ooPolyline = new PolylineOptions().width(2) .color(lineColor).addAll(points); mMapLayer.addPolyline(ooPolyline); // 下面计算两点之间距离 distance = (int) Math.round(MapUtil.getShortDistance( thisPos.longitude, thisPos.latitude, lastPos.longitude, lastPos.latitude)); String disText = ""; if (distance > 1000) { disText = Math.round(distance * 10 / 1000) / 10d + "公里"; } else { disText = distance + "米"; } LatLng llText = new LatLng( (thisPos.latitude + lastPos.latitude) / 2, (thisPos.longitude + lastPos.longitude) / 2); TextOptions ooText = new TextOptions().backgroundColor(0x00ffffff) .fontSize(24).fontColor(textColor).text(disText)// .rotate(-30) .position(llText); mMapLayer.addText(ooText); } if (is_first != true) { // 画圆圈 CircleOptions ooCircle = new CircleOptions().fillColor(lineColor) .center(thisPos).strokeWidth(2).strokeColor(0xAAFF0000).radius(radius); mMapLayer.addCircle(ooCircle); // 画图片标记 BitmapDescriptor bitmapDesc = BitmapDescriptorFactory .fromResource(R.drawable.icon_geo); MarkerOptions ooMarker = new MarkerOptions().draggable(false) .visible(true).icon(bitmapDesc).position(thisPos); mMapLayer.addMarker(ooMarker); mMapLayer.setOnMarkerClickListener(new OnMarkerClickListener() { @Override public boolean onMarkerClick(Marker marker) { LatLng markPos = marker.getPosition(); addDot(markPos); marker.showInfoWindow(); return true; } }); } else { Log.d(TAG, "posArray.size()="+posArray.size()); //可能存在地图与标记同时响应点击事件的情况 if (posArray.size() < 3) { posArray.clear(); is_polygon = false; return; } // 画多边形 PolygonOptions ooPolygon = new PolygonOptions().addAll(posArray) .strokeColor(0xFF00FF00).strokeWidth(1) .fillColor(polygonColor); mMapLayer.addPolygon(ooPolygon); is_polygon = true; // 下面计算多边形的面积 LatLng centerPos = MapUtil.getCenterPos(posArray); double area = Math.round(MapUtil.getArea(posArray)); String areaText = ""; if (area > 1000000) { areaText = Math.round(area * 100 / 1000000) / 100d + "平方公里"; } else { areaText = (int) area + "平方米"; } TextOptions ooText = new TextOptions().backgroundColor(0x00ffffff) .fontSize(26).fontColor(textColor).text(areaText)// .rotate(-30) .position(centerPos); mMapLayer.addText(ooText); } posArray.add(thisPos); if (posArray.size() >= 3) { // 画弧线 ArcOptions ooArc = new ArcOptions() .strokeColor(arcColor) .strokeWidth(2) .point(posArray.get(posArray.size() - 1), posArray.get(posArray.size() - 2), posArray.get(posArray.size() - 3)); mMapLayer.addArc(ooArc); } } @Override public void onMapClick(LatLng arg0) { addDot(arg0); }