首先介绍下这张图,屏幕中间是一个图片(居中显示),我们可以拖动底层的地图 ,让这张图上的中心点指示在我们需要的地方,然后点击【打点】,就可以在图上标注一个点(我点的取图有点大,可以做小点),当我们在图上标注了3个点 他就会计算出标注地区的面积;
项目中使用了高德地图和ArcGis-android-10.2.7.aar;
高德地图只使用了定位和后面介绍高德地图获取面积的方法;
集成ArcGis:
1.将本地ArcGis-android-10.2.7.aar添加到lib目录(和jar同目录);
2.在app的build.gradle中添加
repositories{ flatDir { dirs 'libs' }}
compile (name: 'arcgis-android-10.2.7', ext: 'aar')
重新构建下项目 ok;
3.在xml中添加
原本想法是获取屏幕中心点,然后转换成地图坐标 来计算面积(当然这种方法没有使用,但是原理差不多):获取屏幕中心点方法:
int[] iv_locations = new int[2];
iv.getLocationInWindow(iv_locations); //获取在当前窗口内的绝对坐标
iv.getLocationOnScreen(iv_locations);//获取在整个屏幕内的绝对坐标
int x = iv_locations[0];//横坐标
int y = iv_locations[1];//纵坐标
//如果在Activity的OnCreate()事件输出那些参数,是全为0,要等UI控件都加载完了才能获取到这些。
//在onWindowFocusChanged(boolean hasFocus)中获取为好
-----------------------------------------华丽分割线----------------------------------------------------------------------------------
下面是代码:
public class Main2Activity extends AppCompatActivity {
//图中间的标注物
private ImageView iv;
private MapView mMapView;
//声明AMapLocationClient类对象
public AMapLocationClient mLocationClient = null;
//声明mLocationOption对象
public AMapLocationClientOption mLocationOption = null;
//记录定位j经纬度
LatLng latlng;
//选中的位置
private LatLng mLatlng;
//地图的图层
private GoogleMapLayer YXLayer;// 影像图层
private GoogleMapLayer XZQHLayer;// 行政区划图层
private GraphicsLayer gpsLayers;// 卫星定位图层
private final String FOLDER_NAME = app.folderName + "/MapCache";
//范围
public static Envelope townEnvelope;
/**
* 计算
*/
private List pointList;
private boolean clickComplete = true;
private AreaBean areaBean;
private FillSymbol fillSymbol;
private List areaList = new ArrayList<>();
private PictureMarkerSymbol symbol;
private Graphic MyLocation;
private Point pointText;
private TextSymbol textSymbol;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
mMapView= (MapView) findViewById(R.id.mapview);
iv= (ImageView) findViewById(R.id.iv);
location();
//设置图层
initMap();
}
/**
* 图上按钮点击事件
* @param v
*/
public void click(View v){
//获取地图中心点的x,y坐标点;
Point point=mMapView.getCenter();
Log.i("tag","屏幕位置:"+"X:"+point.getX()+">Y:"+point.getY());
double [] mdouble=selectGoogleMapLonAndLat(point);
Log.i("tag","Double:"+mdouble[0]+">>"+mdouble[1]);
Point pointXY = mMapView.toMapPoint(point);
/**
* clickComplete:控制第一次进来时否点击的是已经选中的地块
*/
if (clickComplete){
pointList=new ArrayList<>();
areaBean = new AreaBean();
areaBean.setPointList(pointList);
areaBean.setIsChanging(true);
areaList.add(areaBean);
clickComplete=false;
}
pointList.add(point);
addAreaOnMap();
}
private void initMap() {
fillSymbol = new SimpleFillSymbol(Color.BLUE);
fillSymbol.setAlpha(90);
pointList = new ArrayList<>();
pointText = new Point();
textSymbol = new TextSymbol(18, "", Color.RED);
// textSymbol.setFontFamily("DroidSansFallback.ttf");
textSymbol.setOffsetX(0);
textSymbol.setOffsetY(-15);
Drawable image = getResources().getDrawable(R.mipmap.poi_marker_pressed);
symbol = new PictureMarkerSymbol(image);
try {
YXLayer = new GoogleMapLayer(GoogleMapLayerTypes.IMAGE_GOOGLE_MAP,
FOLDER_NAME + "/yxCache");
XZQHLayer = new GoogleMapLayer(
GoogleMapLayerTypes.ANNOTATION_GOOGLE_MAP,
FOLDER_NAME + "/qhCache");
mMapView.addLayer(YXLayer);
mMapView.addLayer(XZQHLayer);
} catch (Exception e) {}
gpsLayers = new GraphicsLayer();
mMapView.addLayer(gpsLayers);
townEnvelope = new Envelope(12957628.58241, 4864247.2803126, 12958114.4225065, 4864490.20036087);//范围
mMapView.setExtent(townEnvelope);
}
/**
* 高德地图的定位监听
*/
public AMapLocationListener mLocationListener =new AMapLocationListener() {
@Override
public void onLocationChanged(AMapLocation aMapLocation) {
if (aMapLocation.getErrorCode() == 0) {
//定位成功回调信息,设置相关消息
aMapLocation.getLocationType();//获取当前定位结果来源,如网络定位结果,详见定位类型表
aMapLocation.getLatitude();//获取纬度
aMapLocation.getLongitude();//获取经度
aMapLocation.getAccuracy();//获取精度信息
// 经纬度
latlng = new LatLng(aMapLocation.getLatitude(), aMapLocation.getLongitude());
double latitude = aMapLocation.getLatitude();
double longitude = aMapLocation.getLongitude();
mMapView.centerAt(latitude, longitude, true);
// mMapView.centerAndZoom(latitude,longitude,0.1f);
Drawable image = getResources().getDrawable(R.mipmap.icon_point);
PictureMarkerSymbol symbol = new PictureMarkerSymbol(image);
MyLocation = new Graphic(new Point(longitude, latitude), symbol);
addAreaOnMap();
} else {
//显示错误信息ErrCode是错误码,errInfo是错误信息,详见错误码表。
Log.e("AmapError","location Error, ErrCode:"
+ aMapLocation.getErrorCode() + ", errInfo:"
+ aMapLocation.getErrorInfo());
}
}
};
/**
* 定位
*/
private void location() {
mLocationClient = new AMapLocationClient(this);
//初始化定位参数
mLocationOption = new AMapLocationClientOption();
//设置定位监听
mLocationClient.setLocationListener(mLocationListener);
//设置定位模式为高精度模式,Battery_Saving为低功耗模式,Device_Sensors是仅设备模式
mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
//mLocationOption.setGpsFirst(true);//可选,设置是否gps优先,只在高精度模式下有效。默认关闭
//设置定位间隔,单位毫秒,默认为2000ms
mLocationOption.setInterval(2000);
mLocationOption.setOnceLocation(true);
//设置定位参数
mLocationClient.setLocationOption(mLocationOption);
// 此方法为每隔固定时间会发起一次定位请求,为了减少电量消耗或网络流量消耗,
// 注意设置合适的定位时间的间隔(最小间隔支持为2000ms),并且在合适时间调用stopLocation()方法来取消定位请求
// 在定位结束后,在合适的生命周期调用onDestroy()方法
// 在单次定位情况下,定位无论成功与否,都无需调用stopLocation()方法移除请求,定位sdk内部会移除
//启动定位
mLocationClient.startLocation();
}
@Override
protected void onDestroy() {
super.onDestroy();
mMapView.destroyDrawingCache();
}
@Override
protected void onResume() {
super.onResume();
mMapView.unpause();
}
@Override
protected void onPause() {
super.onPause();
mMapView.pause();
}
//转换成地理坐标
private double[] selectGoogleMapLonAndLat(Point point) {
SpatialReference reference = SpatialReference.create(104199);
Point pointB = (Point) GeometryEngine.project(point,
mMapView.getSpatialReference(), reference);
Gps gps = PositionUtil.gcj_To_Gps84(pointB.getY(), pointB.getX());
return new double[]{gps.getWgLon(), gps.getWgLat()};
}
/**
* 图上绘点
*
* @param geo
*/
private void gpsTooMapView(Geometry geo) {
Graphic graphic = new Graphic(geo, symbol);
gpsLayers.addGraphic(graphic);
}
/**
* 转换面积
*/
private String getAreaString(double dValue) {
long areaL = Math.abs(Math.round(dValue));
String sArea = "";
// 顺时针绘制多边形,面积为正,逆时针绘制,则面积为负
if (areaL >= 1000000) {
double dArea = areaL / 1000000.0;
// sArea = Double.toString(dArea) + " 平方公里";
sArea = String.format("%.2f", dArea * 1500);//1平方千米(km²)=1500亩
} else
// sArea = Double.toString(areaL) + " 平方米";
sArea = String.format("%.2f", areaL * 0.0015);//1平方米(㎡)=0.0015亩
return sArea;
}
double mResult=0;
double total = 0;
private void addAreaOnMap() {
gpsLayers.removeAll();
gpsLayers.addGraphic(MyLocation);
for (int i=0;i points = areaBean.getPointList();
Polygon polygon = new Polygon();
double x = 0, y = 0;
for(int z=0;z
public class GoogleMapLayer extends TiledServiceLayer {
private int GoogleMapLayerType;
private String cachepath;
public GoogleMapLayer(int layerType, String cachepath) {
super(true);
this.cachepath = cachepath;
this.GoogleMapLayerType = layerType;
this.init();
}
private int minLevel = 0;
private int maxLevel = 19;
private double[] scales = new double[] { 591657527.591555,
295828763.79577702, 147914381.89788899, 73957190.948944002,
36978595.474472001, 18489297.737236001, 9244648.8686180003,
4622324.4343090001, 2311162.217155, 1155581.108577, 577790.554289,
288895.277144, 144447.638572, 72223.819286, 36111.909643,
18055.954822, 9027.9774109999998, 4513.9887049999998, 2256.994353,
1128.4971760000001 };
private double[] resolutions = new double[] { 156543.03392800014,
78271.516963999937, 39135.758482000092, 19567.879240999919,
9783.9396204999593, 4891.9698102499797, 2445.9849051249898,
1222.9924525624949, 611.49622628138, 305.748113140558,
152.874056570411, 76.4370282850732, 38.2185141425366,
19.1092570712683, 9.55462853563415, 4.7773142679493699,
2.3886571339746849, 1.1943285668550503, 0.59716428355981721,
0.29858214164761665 };
private Point origin = new Point(-20037508.342787, 20037508.342787);
private int dpi = 96;
private int tileWidth = 256;
private int tileHeight = 256;
private void init() {
try {
getServiceExecutor().submit(new Runnable() {
public void run() {
GoogleMapLayer.this.initLayer();
}
});
} catch (RejectedExecutionException rejectedexecutionexception) {
Log.e("Google Map Layer", "initialization of the layer failed.",
rejectedexecutionexception);
}
}
protected byte[] getTile(int level, int col, int row) throws Exception {
if (level > maxLevel || level < minLevel) {
return new byte[0];
}
byte[] result = null;
result = getOfflineCacheFile(level, col, row);
if (result == null) {
String s = "Galileo".substring(0, ((3 * col + row) % 8));
String url = "";
switch (GoogleMapLayerType) {
case GoogleMapLayerTypes.IMAGE_GOOGLE_MAP:
url = "http://mt" + (col % 4)
+ ".google.cn/vt/lyrs=s&hl=zh-CN&gl=cn&" + "x=" + col
+ "&" + "y=" + row + "&" + "z=" + level + "&" + "s="
+ s;
break;
case GoogleMapLayerTypes.VECTOR_GOOGLE_MAP:
url = "http://mt" + (col % 4)
+ ".google.cn/vt/lyrs=m@158000000&hl=zh-CN&gl=cn&"
+ "x=" + col + "&" + "y=" + row + "&" + "z=" + level
+ "&" + "s=" + s;
break;
case GoogleMapLayerTypes.TERRAIN_GOOGLE_MAP:
url = "http://mt"
+ (col % 4)
+ ".google.cn/vt/lyrs=t@131,r@227000000&hl=zh-CN&gl=cn&"
+ "x=" + col + "&" + "y=" + row + "&" + "z=" + level
+ "&" + "s=" + s;
break;
case GoogleMapLayerTypes.ANNOTATION_GOOGLE_MAP:
url = "http://mt"
+ (col % 4)
+ ".google.cn/vt/imgtp=png32&lyrs=h@169000000&hl=zh-CN&gl=cn&"
+ "x=" + col + "&" + "y=" + row + "&" + "z=" + level
+ "&" + "s=" + s;
break;
}
Map map = null;
result = com.esri.core.internal.io.handler.a.a(url, map);
AddOfflineCacheFile(level, col, row, result);
}
return result;
}
protected void initLayer() {
if (getID() == 0L) {
nativeHandle = create();
changeStatus(com.esri.android.map.event.OnStatusChangedListener.STATUS
.fromInt(-1000));
} else {
this.setDefaultSpatialReference(SpatialReference.create(102113));
this.setFullExtent(new Envelope(-22041257.773878,
-32673939.6727517, 22041257.773878, 20851350.0432886));
this.setTileInfo(new TileInfo(origin, scales, resolutions,
scales.length, dpi, tileWidth, tileHeight));
super.initLayer();
}
}
private byte[] getOfflineCacheFile(int level, int col, int row) {
byte[] bytes = null;
File rowfile = new File(cachepath + "/" + level + "/" + col + "/" + row
+ ".png");
if (rowfile.exists()) {
try {
bytes = CopySdcardbytes(rowfile);
} catch (IOException e) {
e.printStackTrace();
}
} else {
bytes = null;
}
return bytes;
}
public byte[] CopySdcardbytes(File file) throws IOException {
FileInputStream in = new FileInputStream(file);
ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
byte[] temp = new byte[1024];
int size = 0;
while ((size = in.read(temp)) != -1) {
out.write(temp, 0, size);
}
in.close();
byte[] bytes = out.toByteArray();
return bytes;
}
private byte[] AddOfflineCacheFile(int level, int col, int row, byte[] bytes) {
File file = new File(cachepath);
if (!file.exists()) {
file.mkdirs();
}
File levelfile = new File(cachepath + "/" + level);
if (!levelfile.exists()) {
levelfile.mkdirs();
}
File colfile = new File(cachepath + "/" + level + "/" + col);
if (!colfile.exists()) {
colfile.mkdirs();
}
File rowfile = new File(cachepath + "/" + level + "/" + col + "/" + row
+ ".png");
if (!rowfile.exists()) {
try {
FileOutputStream out = new FileOutputStream(rowfile);
out.write(bytes);
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return bytes;
}
}
public class GoogleMapLayerTypes {
/**
* 谷歌矢量地图服务
*/
public final static int VECTOR_GOOGLE_MAP = 1;
/**
* 谷歌影像地图服务
*/
public final static int IMAGE_GOOGLE_MAP = 2;
/**
* 谷歌地形地图服务
*/
public final static int TERRAIN_GOOGLE_MAP = 3;
/**
* 谷歌道路等POI地图服务
*/
public final static int ANNOTATION_GOOGLE_MAP = 4;
}
【我们中间图片和在图上标记点的位置会有一点偏差,在此并未做处理】
二:
高德地图获取地图中心点的方法是:实现implements AMap.OnCameraChangeListener接口;
实现他的2个方法:
@Override public void onCameraChange(CameraPosition cameraPosition) {//获取屏幕中心点的经纬度值target = cameraPosition.target; double latitude = target.latitude;}@Overridepublic void onCameraChangeFinish(CameraPosition cameraPosition) { }{代码中可能存在一些冗余,见谅,该实现方法可能有欠妥的地方,可以在评论指出 谢谢}