在我们进行地图相关开发时候,避免不了要绘制比例尺。在百度,高德的地图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()方法:

@Override

protected 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")

@Override

protected 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 android 比例尺,ArcGIS for Android 自定义地图比例尺相关推荐

  1. arcgis android 指南针,Arcgis runtime for Android 100.5 (六) 自定义指南针

    Arcgis没有提供指南针控件,如果需要,可以自定义一个,很简单 去阿里图标库下载一个能用的指南针如 指南针 放置在布局文件中 xmlns:fab="http://schemas.andro ...

  2. ArcGIS API for JavaScript 各个版本的SDK下载和发布 ,ArcGIS Runtime SDK for Android、ArcGIS Runtime SDK for Java等

    ArcGIS API for JS 官网地址:https://developers.arcgis.com/javascript/ ArcGIS API for JavaScript 各个版本的SDK下 ...

  3. android小球移动代码,Android自定义圆形View实现小球跟随手指移动效果

    本文实例为大家分享了Android实现小球跟随手指移动效果的具体代码,供大家参考,具体内容如下 一. 需求功能 手指在屏幕上滑动,红色的小球始终跟随手指移动. 实现的思路: 1)自定义View,在on ...

  4. android 画布实现签名,Android 自定义View手写签名并保存图片

    1.自定义View--支撑设置画笔色彩,画笔宽度,画板色彩,铲除画板,查看是否有签名,保存画板图片(仿制粘贴可直接使用) /***CreatedbyYyyyQon2020/3/5. *电子签名*/pu ...

  5. android canvas绘制圆角_Android自定义View撸一个渐变的温度指示器(TmepView)

    秦子帅明确目标,每天进步一点点..... 作者 |  andy 地址 |  blog.csdn.net/Andy_l1/article/details/82910061 1.概述 自定义View对需要 ...

  6. Android之自定义控件一起制作自定义标签

    今天我们要实现的效果如下: 当然列表中的标签显示的个数是可控的,实现个数可控的标签的话,我们就需要自定义View. 我们自定义一个抽象类继承LinearLayout并实现我们定义的接口: BaseTa ...

  7. 我的Android进阶之旅------Android自定义View来实现解析lrc歌词并同步滚动、上下拖动、缩放歌词的功能...

    前言 一LRC歌词文件简介 1什么是LRC歌词文件 2LRC歌词文件的格式 LRC歌词文件的标签类型 1标识标签 2时间标签 二解析LRC歌词 1读取出歌词文件 2解析得到的歌词内容 1表示每行歌词内 ...

  8. Android WiFi热点完全研究(自定义创建、跳转系统界面设置、读取配置、切换,Android6.0适配)...

    前言: WiFi热点设置页面的安全性选项在Android 4.x上有"无"."WPA PSK"."WPA2 PSK"三个选项,在Androi ...

  9. Android 三种方式实现自定义圆形页面加载中效果的进度条

    转载:http://www.eoeandroid.com/forum.php?mod=viewthread&tid=76872 一.通过动画实现 定义res/anim/loading.xml如 ...

  10. Android学习笔记18:自定义Seekbar拖动条式样

    SeekBar拖动条可以由用户控制,进行拖动操作.比如,应用程序中用户需要对音量进行控制,就可以使用拖动条来实现. 1.SeekBar控件的使用 1.1SeekBar常用属性 SeekBar的常用属性 ...

最新文章

  1. python正则表达式实例教程_Python正则表达式经典入门教程
  2. Visual Studio提示“无法启动IIS Express Web服务器”的解决方法
  3. 图解CSS3----5-否定伪类选择器
  4. LeetCode Algorithm 1566. 重复至少 K 次且长度为 M 的模式
  5. python中keys是什么意思_python中key指的是什么
  6. ps cs3怎样能保存html,ps cs3用消失点清理杂物方法介绍
  7. Mac安装Python我觉得靠谱的方法
  8. 在EF4.1的DBContext中实现事务处理(BeginTransaction)和直接执行SQL语句的示例
  9. php mysql修改表单数据_表单修改数据
  10. 项目在云服务器上的绝对路径,项目在云服务器上的绝对路径
  11. android 平方常规字体,android - Android将Roboto字体设置为粗体,斜体,常规,…(类似于自定义字体系列) - 堆栈内存溢出...
  12. Topaz DeNoise AI 2.3.6汉化版|AI智能降噪插件Topaz DeNoise AI 2.3.6中文版
  13. iphone屏幕镜像如何全屏_苹果投屏有什么方法?使用“屏幕镜像”功能,任意切换大小屏幕...
  14. 基于C++ Qt实现的红色警戒3修改器
  15. linux下.dep文件,Linux 安装 golang 和 dep (附错两个误解决方法)
  16. Tensorflow2.0之语言模型数据集(周杰伦专辑歌词)预处理
  17. python爬虫(十三)selenium(Selenium入门、chromedriver、Phantomjs)
  18. Backspace删除键不能够使用的解决办法
  19. 利用requests库和Xpath爬取猫眼电影榜单【Python】
  20. zookeeper集群节点个数为什么最好是2n+1

热门文章

  1. 道德经和译文_道德经 - 道德经全文及译文 - 道德经全文 - 老子道德经
  2. android app wifi密码,手机WiFi密码显示APP
  3. 怎样高效地自学软件测试
  4. 你的APK安全吗?来WeTest免费测!
  5. 雷达动画在地图显示_本周在我们的雷达上:RebeccaPurple,动画等!
  6. 分数加减乘除混合运算带答案_分数加减乘除混合运算专项训练
  7. 选择阿里云数据库HBase版十大理由
  8. wps word设置级别多级目录标题
  9. PS魔棒工具的使用方法
  10. 聊聊图标和MBE图标