ArcGIS for Android 自定义地图比例尺_移动开发_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > 移动开发 > ArcGIS for Android 自定义地图比例尺

ArcGIS for Android 自定义地图比例尺

 2017/11/2 17:11:40  一猴当先  程序员俱乐部  我要评论(0)
  • 摘要:在我们进行地图相关开发时候,避免不了要绘制比例尺。在百度,高德的地图API里都提供了比例尺控件,但是ArcGISforAndroid里并没有提供。不过没关系,我们可以自己绘制一个比例尺来。在绘制比例尺前,我们先了解几个概念:PPI,PixelsPerInch的所写,表示的是每英寸所拥有的像素数目;PX,像素,表示图像中的一个最小单位;DPI,DotsPerInch,每英寸点数,即图像密度;.9.PNG,Android开发里面的一种特殊的图片,这种格式的图片通过ADT自带的编辑工具生成
  • 标签:android ArcGIS for 自定义

在我们进行地图相关开发时候,避免不了要绘制比例尺。在百度,高德的地图API里都提供了比例尺控件,但是ArcGIS for Android里并没有提供。不过没关系,我们可以自己绘制一个比例尺来。

 

      在绘制比例尺前,我们先了解几个概念:

 

 

  1. PPI,Pixels Per Inch的所写,表示的是每英寸所拥有的像素数目;
  2. PX,像素,表示图像中的一个最小单位;
  3. DPI,Dots Per Inch,每英寸点数,即图像密度;
  4. .9.PNGAndroid开发里面的一种特殊的图片,这种格式的图片通过ADT自带的编辑工具生成,使用九宫格切分的方法,使图片支持在Android环境下的自适应展示。即这种类型图片在Android里无论怎样拉伸缩小都不失真。

 

 

      其中PPI和DPI在实际生活中的定义是不太一样的,而在Android里,他们的含义却是相似的。单独把DPI拿出来主要是Android里有个方法可以分别获取到屏幕X轴和Y轴的像素密度。

 

      .9.PNG格式的图片不失真,正好适合我们做来做比例尺图片。

 

       好了,我们好绘制一个比例尺,需要做些什么呢?

 

       首先,我们得知道当前地图比例,这个参数可以通过MapView.getScale来获取;

 

       其次,我们要根据当前地图比例绘制一个比例尺。绘制的方案有两种,一个是固定尺子长度,根据当前地图比例更换比例尺的比,比如1:2000,1:3000等;另一种是固定一些比例单位,比如1:50000后就是1:20000,然后比例尺的长度根据实际长度会做一定伸缩。这里我采用第二种,因为第一种根据实际比例往往比例尺的比值不是整数,并且在较大比例时候显示位数较长,四舍五入又会失去精度。

 

      最后,是监听地图放大缩小事件,并作出响应改变比例尺。

 

      方法就是这么简单,那就实际开动吧。

 

第一步,实例化地图,加载图层:

 

[java] view plainclass="tracking-ad" data-mod="popu_168"> copy  
  1. mMapView=(MapView)findViewById(R.id.mapview);  
  2. mMapScaleView=(MapScaleView)findViewById(R.id.scaleView);  
  3. String path= StorageUtil.getSDCardRootPath(getApplicationContext());  
  4. ArcGISLocalTiledLayer layer=new ArcGISLocalTiledLayer(path);  
  5. mMapView.addLayer(layer,0);  
  6. mMapScaleView.setMapView(mMapView);  
  7. ArcGISRuntime.setClientId(System.clint);//设置许可  
  8. mMapView.setMapBackground(0xFAFAFA, 0xffffff, 0.0f, 0.0f);//地图背景  

 

 

第二步,自定义View,绘制比例尺:

      

      初始化自定义View:

 

[java] view plain copy  
  1. public MapScaleView(Context context) {  
  2.     this(context, null);  
  3.     this.context=context;  
  4.     this.initVariables();  
  5. }  
  6.   
  7. public MapScaleView(Context context, AttributeSet attrs) {  
  8.     this(context, attrs, 0);  
  9.     this.context=context;  
  10.     this.initVariables();  
  11. }  
  12.   
  13. public MapScaleView(Context context, AttributeSet attrs, int defStyle) {  
  14.     super(context, attrs, defStyle);  
  15.     this.context=context;  
  16.     this.initVariables();  
  17. }  

 

 

      初始化自定义View的参数:

 

[java] view plain copy  
  1. private void initVariables(){  
  2.     scaleWidth=104;//  
  3.     scaleHeight=8;//比比例尺宽度例尺高度  
  4.     textColor= Color.BLACK;//比例尺字体颜色  
  5.     text="20公里";//比例尺文本  
  6.     textSize=18;//比例尺宽度  
  7.     scaleSpaceText=8;//比例尺文本与图形的间隔高度  
  8.     mPaint = new Paint();//画笔  
  9. }  

 

 

      重写onMearsure()方法:

 

[java] view plain copy  
  1. @Override  
  2. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
  3.     super.onMeasure(widthMeasureSpec, heightMeasureSpec);  
  4.     int widthSize = getWidthSize(widthMeasureSpec);  
  5.     int heightSize = getHeightSize(heightMeasureSpec);  
  6.     setMeasuredDimension(widthSize, heightSize);  
  7. }  

 

 

      获取自定义View的宽和高:

 

[java] view plain copy  
  1. **  
  2.  * 测量ScaleView的宽度  
  3.  * @param widthMeasureSpec  
  4.  * @return  
  5.  */  
  6. private int getWidthSize(int widthMeasureSpec){  
  7.     return MeasureSpec.getSize(widthMeasureSpec);  
  8. }  
  9.   
  10. /** 
  11.  * 测量ScaleView的高度 
  12.  * @param heightMeasureSpec 
  13.  * @return 
  14.  */  
  15. private int getHeightSize(int heightMeasureSpec){  
  16.     int mode = MeasureSpec.getMode(heightMeasureSpec);  
  17.     int height = 0;  
  18.     switch (mode) {  
  19.         case MeasureSpec.AT_MOST:  
  20.             height = textSize + scaleSpaceText + scaleHeight;  
  21.             break;  
  22.         case MeasureSpec.EXACTLY:{  
  23.             height = MeasureSpec.getSize(heightMeasureSpec);  
  24.             break;  
  25.         }  
  26.         case MeasureSpec.UNSPECIFIED:{  
  27.             height = Math.max(textSize + scaleSpaceText + scaleHeight, MeasureSpec.getSize(heightMeasureSpec));  
  28.             break;  
  29.         }  
  30.     }  
  31.   
  32.     return height;  
  33. }  

 

 

      重写onDraw()方法,绘制比例尺:

 

[java] view plain copy  
  1. **  
  2.  * 绘制上面的文字和下面的比例尺,因为比例尺是.9.png,我们需要利用drawNinepath方法绘制比例尺  
  3.  */  
  4. @SuppressLint("DrawAllocation")  
  5. @Override  
  6. protected void onDraw(Canvas canvas) {  
  7.     super.onDraw(canvas);  
  8.     int width = scaleWidth ;  
  9.     mPaint.setColor(textColor);  
  10.     mPaint.setAntiAlias(true);  
  11.     mPaint.setTextSize(textSize);  
  12.     mPaint.setTypeface(Typeface.DEFAULT_BOLD);  
  13.     float textWidth = mPaint.measureText(text);  
  14.     canvas.drawText(text, (width - textWidth) / 2, textSize, mPaint);  
  15.     Rect scaleRect = new Rect(0, textSize + scaleSpaceText, width, textSize + scaleSpaceText + scaleHeight);  
  16.     drawNinepath(canvas, R.drawable.icon_scale, scaleRect);  
  17. }  

 

 

      绘制.9.PNG图片:

 

[java] view plain copy  
  1. private void drawNinepath(Canvas canvas, int resId, Rect rect){  
  2.     Bitmap bmp= BitmapFactory.decodeResource(getResources(), resId);  
  3.     NinePatch patch = new NinePatch(bmp, bmp.getNinePatchChunk(), null);  
  4.     patch.draw(canvas, rect);  
  5. }  

 

 

      接下来就是根据获取的地图比例,绘制比例尺,更新比例尺的单位以及绘制它的长度,这里我按照2、5、1的进制选取了比例尺的单位:

 

[java] view plain copy  
  1. /** 
  2.  * 根据缩放级别更新ScaleView的文字以及比例尺的长度 
  3.  */  
  4. public void refreshScaleView() {  
  5.     if(mapView == null){  
  6.         throw new NullPointerException("you can call setMapView(MapView mapView) at first");  
  7.     }  
  8.     double scale=this.mapView.getScale()/100;//结果单位米,表示图上1厘米代表*米  
  9.     double ppi=getPPIOfDevice();  
  10.     if(scale>0&&scale<=20){//换算20米  
  11.         String unit = "20米";  
  12.         int scaleWidth=(int)(20*ppi/2.54/scale);//ppi为每英尺像素数,ppi/2.54为1厘米的像素数  
  13.         setText(unit);//更新文字  
  14.         setScaleWidth(scaleWidth);//更新比例尺长度  
  15.     }else if(scale>20&&scale<=50){//换算50米  
  16.         String unit = "50米";  
  17.         int scaleWidth=(int)(50*ppi/2.54/scale);  
  18.         setText(unit);//更新文字  
  19.         setScaleWidth(scaleWidth);//更新比例尺长度  
  20.     }else if(scale>50&&scale<=100){//换算20米  
  21.         String unit = "100米";  
  22.         int scaleWidth=(int)(100*ppi/2.54/scale);  
  23.         setText(unit);//更新文字  
  24.         setScaleWidth(scaleWidth);//更新比例尺长度  
  25.     }else if(scale>100&&scale<=200){//换算20米  
  26.         String unit = "200米";  
  27.         int scaleWidth=(int)(200*ppi/2.54/scale);  
  28.         setText(unit);//更新文字  
  29.         setScaleWidth(scaleWidth);//更新比例尺长度  
  30.     }else if(scale>200&&scale<=500){//换算20米  
  31.         String unit = "500米";  
  32.         int scaleWidth=(int)(500*ppi/2.54/scale);  
  33.         setText(unit);//更新文字  
  34.         setScaleWidth(scaleWidth);//更新比例尺长度  
  35.     }else if(scale>500&&scale<=1000){//换算20米  
  36.         String unit = "1公里";  
  37.         int scaleWidth=(int)(1000*ppi/2.54/scale);  
  38.         setText(unit);//更新文字  
  39.         setScaleWidth(scaleWidth);//更新比例尺长度  
  40.     }else if(scale>1000&&scale<=2000){//换算20米  
  41.         String unit = "2公里";  
  42.         int scaleWidth=(int)(2000*ppi/2.54/scale);  
  43.         setText(unit);//更新文字  
  44.         setScaleWidth(scaleWidth);//更新比例尺长度  
  45.     }else if(scale>2000&&scale<=5000){//换算20米  
  46.         String unit = "5公里";  
  47.         int scaleWidth=(int)(5000*ppi/2.54/scale);  
  48.         setText(unit);//更新文字  
  49.         setScaleWidth(scaleWidth);//更新比例尺长度  
  50.     }else if(scale>5000&&scale<=10000){//换算20米  
  51.         String unit = "10公里";  
  52.         int scaleWidth=(int)(10000*ppi/2.54/scale);  
  53.         setText(unit);//更新文字  
  54.         setScaleWidth(scaleWidth);//更新比例尺长度  
  55.     }else if(scale>10000&&scale<=20000){//换算20米  
  56.         String unit = "20公里";  
  57.         int scaleWidth=(int)(20000*ppi/2.54/scale);  
  58.         setText(unit);//更新文字  
  59.         setScaleWidth(scaleWidth);//更新比例尺长度  
  60.     }else if(scale>20000&&scale<=25000){//换算20米  
  61.         String unit = "25公里";  
  62.         int scaleWidth=(int)(25000*ppi/2.54/scale);  
  63.         setText(unit);//更新文字  
  64.         setScaleWidth(scaleWidth);//更新比例尺长度  
  65.     }else if(scale>25000&&scale<=50000){//换算20米  
  66.         String unit = "50公里";  
  67.         int scaleWidth=(int)(50000*ppi/2.54/scale);  
  68.         setText(unit);//更新文字  
  69.         setScaleWidth(scaleWidth);//更新比例尺长度  
  70.     }else if(scale>50000&&scale<=100000){//换算20米  
  71.         String unit = "100公里";  
  72.         int scaleWidth=(int)(100000*ppi/2.54/scale);  
  73.         setText(unit);//更新文字  
  74.         setScaleWidth(scaleWidth);//更新比例尺长度  
  75.     }else if(scale>100000&&scale<=200000){//换算20米  
  76.         String unit = "200公里";  
  77.         int scaleWidth=(int)(200000*ppi/2.54/scale);  
  78.         setText(unit);//更新文字  
  79.         setScaleWidth(scaleWidth);//更新比例尺长度  
  80.     }else if(scale>200000&&scale<=250000){//换算20米  
  81.         String unit = "250公里";  
  82.         int scaleWidth=(int)(250000*ppi/2.54/scale);  
  83.         setText(unit);//更新文字  
  84.         setScaleWidth(scaleWidth);//更新比例尺长度  
  85.     }else if(scale>250000&&scale<=500000){//换算20米  
  86.         String unit = "500公里";  
  87.         int scaleWidth=(int)(500000*ppi/2.54/scale);  
  88.         setText(unit);//更新文字  
  89.         setScaleWidth(scaleWidth);//更新比例尺长度  
  90.     }else if(scale>500000&&scale<=1000000){//换算20米  
  91.         String unit = "1000公里";  
  92.         int scaleWidth=(int)(1000000*ppi/2.54/scale);  
  93.         setText(unit);//更新文字  
  94.         setScaleWidth(scaleWidth);//更新比例尺长度  
  95.     }  
  96.   
  97.     invalidate();  
  98. }  

 

 

      其中,获取屏幕PPI的方法如下:首先是用android.view包下的Display类里的getRealSize()方法获取屏幕分辨率;其次是用android.util包下有个DisplayMetrics类来获取密度相关的信息,该类里的xdpi和ydpi参数分别表示屏幕X轴和Y轴的点数密度,用X轴和Y轴的像素除以密度得到X轴和Y轴的真实长度,进而求得屏幕对角线的真实长度;最后用屏幕对角线的像素点数除以屏幕对角线的真实长度,得到屏幕的PPI:

 

[java] view plain copy  
  1. private double getPPIOfDevice() {  
  2.     Point point = new Point();  
  3.     Activity activity=(Activity) context;  
  4.     activity.getWindowManager().getDefaultDisplay().getRealSize(point);//获取屏幕的真实分辨率  
  5.     DisplayMetrics dm = getResources().getDisplayMetrics();  
  6.     double x = Math.pow(point.x/ dm.xdpi, 2);//  
  7.     double y = Math.pow(point.y / dm.ydpi, 2);  
  8.     double screenInches = Math.sqrt(x + y);  
  9.     Double ppi=Math.sqrt(Math.pow(point.x, 2)+Math.pow(point.y, 2))/screenInches;  
  10.     return ppi;  
  11. }  

 源码免费下载地址:http://www.jinhusns.com/Products/Download


第三步:写响应事件

 

 

      在ArcGIS的MapView有个监听地图大小变化的方法,叫setOnZoomListener(),在里面写响应事件即可:

 

[java] view plain copy  
  1. mMapView.setOnZoomListener(new OnZoomListener() {  
  2.     @Override  
  3.     public void preAction(float v, float v1, double v2) {  
  4.         //todo  
  5.     }  
  6.   
  7.     @Override  
  8.     public void postAction(float v, float v1, double v2) {  
  9.         mMapScaleView.refreshScaleView();  
  10.     }  
  11. });  

 


      效果图如下:

 

 

发表评论
用户名: 匿名