ArcGIS for Android 自定义地图比例尺
来源:互联网 发布:python 创建临时文件 编辑:程序博客网 时间:2024/05/20 23:40
在我们进行地图相关开发时候,避免不了要绘制比例尺。在百度,高德的地图API里都提供了比例尺控件,但是ArcGIS for Android里并没有提供。不过没关系,我们可以自己绘制一个比例尺来。
在绘制比例尺前,我们先了解几个概念:
- PPI,Pixels Per Inch的所写,表示的是每英寸所拥有的像素数目;
- PX,像素,表示图像中的一个最小单位;
- DPI,Dots Per Inch,每英寸点数,即图像密度;
- .9.PNG,Android开发里面的一种特殊的图片,这种格式的图片通过ADT自带的编辑工具生成,使用九宫格切分的方法,使图片支持在Android环境下的自适应展示。即这种类型图片在Android里无论怎样拉伸缩小都不失真。
其中PPI和DPI在实际生活中的定义是不太一样的,而在Android里,他们的含义却是相似的。单独把DPI拿出来主要是Android里有个方法可以分别获取到屏幕X轴和Y轴的像素密度。
.9.PNG格式的图片不失真,正好适合我们做来做比例尺图片。
好了,我们好绘制一个比例尺,需要做些什么呢?
首先,我们得知道当前地图比例,这个参数可以通过MapView.getScale来获取;
其次,我们要根据当前地图比例绘制一个比例尺。绘制的方案有两种,一个是固定尺子长度,根据当前地图比例更换比例尺的比,比如1:2000,1:3000等;另一种是固定一些比例单位,比如1:50000后就是1:20000,然后比例尺的长度根据实际长度会做一定伸缩。这里我采用第二种,因为第一种根据实际比例往往比例尺的比值不是整数,并且在较大比例时候显示位数较长,四舍五入又会失去精度。
最后,是监听地图放大缩小事件,并作出响应改变比例尺。
方法就是这么简单,那就实际开动吧。
第一步,实例化地图,加载图层:
mMapView=(MapView)findViewById(R.id.mapview);mMapScaleView=(MapScaleView)findViewById(R.id.scaleView);String path= StorageUtil.getSDCardRootPath(getApplicationContext());ArcGISLocalTiledLayer layer=new ArcGISLocalTiledLayer(path);mMapView.addLayer(layer,0);mMapScaleView.setMapView(mMapView);ArcGISRuntime.setClientId(System.clint);//设置许可mMapView.setMapBackground(0xFAFAFA, 0xffffff, 0.0f, 0.0f);//地图背景
第二步,自定义View,绘制比例尺:
初始化自定义View:
public MapScaleView(Context context) { this(context, null); this.context=context; this.initVariables();}public MapScaleView(Context context, AttributeSet attrs) { this(context, attrs, 0); this.context=context; this.initVariables();}public MapScaleView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); this.context=context; this.initVariables();}
初始化自定义View的参数:
private void initVariables(){ scaleWidth=104;// scaleHeight=8;//比比例尺宽度例尺高度 textColor= Color.BLACK;//比例尺字体颜色 text="20公里";//比例尺文本 textSize=18;//比例尺宽度 scaleSpaceText=8;//比例尺文本与图形的间隔高度 mPaint = new Paint();//画笔}
重写onMearsure()方法:
@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int widthSize = getWidthSize(widthMeasureSpec); int heightSize = getHeightSize(heightMeasureSpec); setMeasuredDimension(widthSize, heightSize);}
获取自定义View的宽和高:
** * 测量ScaleView的宽度 * @param widthMeasureSpec * @return */private int getWidthSize(int widthMeasureSpec){ return MeasureSpec.getSize(widthMeasureSpec);}/** * 测量ScaleView的高度 * @param heightMeasureSpec * @return */private int getHeightSize(int heightMeasureSpec){ int mode = MeasureSpec.getMode(heightMeasureSpec); int height = 0; switch (mode) { case MeasureSpec.AT_MOST: height = textSize + scaleSpaceText + scaleHeight; break; case MeasureSpec.EXACTLY:{ height = MeasureSpec.getSize(heightMeasureSpec); break; } case MeasureSpec.UNSPECIFIED:{ height = Math.max(textSize + scaleSpaceText + scaleHeight, MeasureSpec.getSize(heightMeasureSpec)); break; } } return height;}
重写onDraw()方法,绘制比例尺:
** * 绘制上面的文字和下面的比例尺,因为比例尺是.9.png,我们需要利用drawNinepath方法绘制比例尺 */@SuppressLint("DrawAllocation")@Overrideprotected void onDraw(Canvas canvas) { super.onDraw(canvas); int width = scaleWidth ; mPaint.setColor(textColor); mPaint.setAntiAlias(true); mPaint.setTextSize(textSize); mPaint.setTypeface(Typeface.DEFAULT_BOLD); float textWidth = mPaint.measureText(text); canvas.drawText(text, (width - textWidth) / 2, textSize, mPaint); Rect scaleRect = new Rect(0, textSize + scaleSpaceText, width, textSize + scaleSpaceText + scaleHeight); drawNinepath(canvas, R.drawable.icon_scale, scaleRect);}
绘制.9.PNG图片:
private void drawNinepath(Canvas canvas, int resId, Rect rect){ Bitmap bmp= BitmapFactory.decodeResource(getResources(), resId); NinePatch patch = new NinePatch(bmp, bmp.getNinePatchChunk(), null); patch.draw(canvas, rect);}
接下来就是根据获取的地图比例,绘制比例尺,更新比例尺的单位以及绘制它的长度,这里我按照2、5、1的进制选取了比例尺的单位:
public void refreshScaleView() { if(mapView == null){ throw new NullPointerException("you can call setMapView(MapView mapView) at first"); } double scale=this.mapView.getScale()/100;//结果单位米,表示图上1厘米代表*米 double ppi=getPPIOfDevice(); if(scale>0&&scale<=20){//换算20米 String unit = "20米"; int scaleWidth=(int)(20*264/2.54/scale);//264为ppi,264/2.54为1厘米的像素数 setText(unit);//更新文字 setScaleWidth(scaleWidth);//更新比例尺长度 }else if(scale>20&&scale<=50){//换算50米 String unit = "50米"; int scaleWidth=(int)(50*264/2.54/scale); setText(unit);//更新文字 setScaleWidth(scaleWidth);//更新比例尺长度 }else if(scale>50&&scale<=100){//换算20米 String unit = "100米"; int scaleWidth=(int)(100*264/2.54/scale); setText(unit);//更新文字 setScaleWidth(scaleWidth);//更新比例尺长度 }else if(scale>100&&scale<=200){//换算20米 String unit = "200米"; int scaleWidth=(int)(200*264/2.54/scale); setText(unit);//更新文字 setScaleWidth(scaleWidth);//更新比例尺长度 }else if(scale>200&&scale<=500){//换算20米 String unit = "500米"; int scaleWidth=(int)(500*264/2.54/scale); setText(unit);//更新文字 setScaleWidth(scaleWidth);//更新比例尺长度 }else if(scale>500&&scale<=1000){//换算20米 String unit = "1公里"; int scaleWidth=(int)(1000*264/2.54/scale); setText(unit);//更新文字 setScaleWidth(scaleWidth);//更新比例尺长度 }else if(scale>1000&&scale<=2000){//换算20米 String unit = "2公里"; int scaleWidth=(int)(2000*264/2.54/scale); setText(unit);//更新文字 setScaleWidth(scaleWidth);//更新比例尺长度 }else if(scale>2000&&scale<=5000){//换算20米 String unit = "5公里"; int scaleWidth=(int)(5000*264/2.54/scale); setText(unit);//更新文字 setScaleWidth(scaleWidth);//更新比例尺长度 }else if(scale>5000&&scale<=10000){//换算20米 String unit = "10公里"; int scaleWidth=(int)(10000*264/2.54/scale); setText(unit);//更新文字 setScaleWidth(scaleWidth);//更新比例尺长度 }else if(scale>10000&&scale<=20000){//换算20米 String unit = "20公里"; int scaleWidth=(int)(20000*264/2.54/scale); setText(unit);//更新文字 setScaleWidth(scaleWidth);//更新比例尺长度 }else if(scale>20000&&scale<=25000){//换算20米 String unit = "25公里"; int scaleWidth=(int)(25000*264/2.54/scale); setText(unit);//更新文字 setScaleWidth(scaleWidth);//更新比例尺长度 }else if(scale>25000&&scale<=50000){//换算20米 String unit = "50公里"; int scaleWidth=(int)(50000*264/2.54/scale); setText(unit);//更新文字 setScaleWidth(scaleWidth);//更新比例尺长度 }else if(scale>50000&&scale<=100000){//换算20米 String unit = "100公里"; int scaleWidth=(int)(100000*264/2.54/scale); setText(unit);//更新文字 setScaleWidth(scaleWidth);//更新比例尺长度 }else if(scale>100000&&scale<=200000){//换算20米 String unit = "200公里"; int scaleWidth=(int)(200000*264/2.54/scale); setText(unit);//更新文字 setScaleWidth(scaleWidth);//更新比例尺长度 }else if(scale>200000&&scale<=250000){//换算20米 String unit = "250公里"; int scaleWidth=(int)(250000*264/2.54/scale); setText(unit);//更新文字 setScaleWidth(scaleWidth);//更新比例尺长度 }else if(scale>250000&&scale<=500000){//换算20米 String unit = "500公里"; int scaleWidth=(int)(500000*264/2.54/scale); setText(unit);//更新文字 setScaleWidth(scaleWidth);//更新比例尺长度 }else if(scale>500000&&scale<=scale){//换算20米 String unit = "1000公里"; int scaleWidth=(int)(1000000*264/2.54/scale); setText(unit);//更新文字 setScaleWidth(scaleWidth);//更新比例尺长度 } invalidate(); }
其中,获取屏幕PPI的方法如下:首先是用android.view包下的Display类里的getRealSize()方法获取屏幕分辨率;其次是用android.util包下有个DisplayMetrics类来获取密度相关的信息,该类里的xdpi和ydpi参数分别表示屏幕X轴和Y轴的点数密度,用X轴和Y轴的像素除以密度得到X轴和Y轴的真实长度,进而求得屏幕对角线的真实长度;最后用屏幕对角线的像素点数除以屏幕对角线的真实长度,得到屏幕的PPI:
private double getPPIOfDevice() { Point point = new Point(); Activity activity=(Activity) context; activity.getWindowManager().getDefaultDisplay().getRealSize(point);//获取屏幕的真实分辨率 DisplayMetrics dm = getResources().getDisplayMetrics(); double x = Math.pow(point.x/ dm.xdpi, 2);// double y = Math.pow(point.y / dm.ydpi, 2); double screenInches = Math.sqrt(x + y); Double ppi=Math.sqrt(Math.pow(point.x, 2)+Math.pow(point.y, 2))/screenInches; return ppi;}
第三步:写响应事件
在ArcGIS的MapView有个监听地图大小变化的方法,叫setOnZoomListener(),在里面写响应事件即可:
mMapView.setOnZoomListener(new OnZoomListener() { @Override public void preAction(float v, float v1, double v2) { //todo } @Override public void postAction(float v, float v1, double v2) { mMapScaleView.refreshScaleView(); }});
效果图如下:
- ArcGIS for Android 自定义地图比例尺
- ArcGIS For Android 地图比例尺获取
- cGIS for Android 自定义地图比例尺
- Arcgis For Android实现比例尺
- 【ArcGIS for Android】使用自定义Callout显示地图信息
- Arcgis Javascript那些事儿(五)--arcgis server发布自定义比例尺地图
- Android安卓 自定义高德地图比例尺
- Arcgis for android 地图放大镜
- ArcGIS Server 自定义比例尺切图
- arcgis for android 地图查询并定位
- ArcGIS for Android —— 显示地图
- arcgis for android 离线地图实现
- ArcGIS for android 离线地图 案例
- ArcGIS for Android 体验(一) 添加地图
- ArcGIS for Android 体验(一) 添加地图
- Arcgis For Android加载离线地图
- ArcGIS for Android 体验(一) 添加地图
- ArcGIS for Android 设置地图网格背景
- Sqlite 分组查询
- 【Jsoup】配合 htmlunit 爬取异步加载的网页
- REST架构
- JAVA的动态代理入门
- 【spring配置】——spring整合Quartz定时器
- ArcGIS for Android 自定义地图比例尺
- IT基础22
- 机器视觉halcon软件:获取圆形的半径和圆度
- IT基础23
- jmeter压测----环境准备(PerfMon Metrics Collector and Server Agent原理和使用)
- 【微营销】第6天 微营销实战技巧之如何把你的微博炒成热门微博
- MySQL中tinytext、text、mediumtext和longtext详解
- IT基础24 内容待写
- IT基础25 内容待写