arcgis android 比例尺,ArcGIS for Android 自定义地图比例尺
在我们进行地图相关开发时候,避免不了要绘制比例尺。在百度,高德的地图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 自定义地图比例尺相关推荐
- arcgis android 指南针,Arcgis runtime for Android 100.5 (六) 自定义指南针
Arcgis没有提供指南针控件,如果需要,可以自定义一个,很简单 去阿里图标库下载一个能用的指南针如 指南针 放置在布局文件中 xmlns:fab="http://schemas.andro ...
- 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下 ...
- android小球移动代码,Android自定义圆形View实现小球跟随手指移动效果
本文实例为大家分享了Android实现小球跟随手指移动效果的具体代码,供大家参考,具体内容如下 一. 需求功能 手指在屏幕上滑动,红色的小球始终跟随手指移动. 实现的思路: 1)自定义View,在on ...
- android 画布实现签名,Android 自定义View手写签名并保存图片
1.自定义View--支撑设置画笔色彩,画笔宽度,画板色彩,铲除画板,查看是否有签名,保存画板图片(仿制粘贴可直接使用) /***CreatedbyYyyyQon2020/3/5. *电子签名*/pu ...
- android canvas绘制圆角_Android自定义View撸一个渐变的温度指示器(TmepView)
秦子帅明确目标,每天进步一点点..... 作者 | andy 地址 | blog.csdn.net/Andy_l1/article/details/82910061 1.概述 自定义View对需要 ...
- Android之自定义控件一起制作自定义标签
今天我们要实现的效果如下: 当然列表中的标签显示的个数是可控的,实现个数可控的标签的话,我们就需要自定义View. 我们自定义一个抽象类继承LinearLayout并实现我们定义的接口: BaseTa ...
- 我的Android进阶之旅------Android自定义View来实现解析lrc歌词并同步滚动、上下拖动、缩放歌词的功能...
前言 一LRC歌词文件简介 1什么是LRC歌词文件 2LRC歌词文件的格式 LRC歌词文件的标签类型 1标识标签 2时间标签 二解析LRC歌词 1读取出歌词文件 2解析得到的歌词内容 1表示每行歌词内 ...
- Android WiFi热点完全研究(自定义创建、跳转系统界面设置、读取配置、切换,Android6.0适配)...
前言: WiFi热点设置页面的安全性选项在Android 4.x上有"无"."WPA PSK"."WPA2 PSK"三个选项,在Androi ...
- Android 三种方式实现自定义圆形页面加载中效果的进度条
转载:http://www.eoeandroid.com/forum.php?mod=viewthread&tid=76872 一.通过动画实现 定义res/anim/loading.xml如 ...
- Android学习笔记18:自定义Seekbar拖动条式样
SeekBar拖动条可以由用户控制,进行拖动操作.比如,应用程序中用户需要对音量进行控制,就可以使用拖动条来实现. 1.SeekBar控件的使用 1.1SeekBar常用属性 SeekBar的常用属性 ...
最新文章
- python正则表达式实例教程_Python正则表达式经典入门教程
- Visual Studio提示“无法启动IIS Express Web服务器”的解决方法
- 图解CSS3----5-否定伪类选择器
- LeetCode Algorithm 1566. 重复至少 K 次且长度为 M 的模式
- python中keys是什么意思_python中key指的是什么
- ps cs3怎样能保存html,ps cs3用消失点清理杂物方法介绍
- Mac安装Python我觉得靠谱的方法
- 在EF4.1的DBContext中实现事务处理(BeginTransaction)和直接执行SQL语句的示例
- php mysql修改表单数据_表单修改数据
- 项目在云服务器上的绝对路径,项目在云服务器上的绝对路径
- android 平方常规字体,android - Android将Roboto字体设置为粗体,斜体,常规,…(类似于自定义字体系列) - 堆栈内存溢出...
- Topaz DeNoise AI 2.3.6汉化版|AI智能降噪插件Topaz DeNoise AI 2.3.6中文版
- iphone屏幕镜像如何全屏_苹果投屏有什么方法?使用“屏幕镜像”功能,任意切换大小屏幕...
- 基于C++ Qt实现的红色警戒3修改器
- linux下.dep文件,Linux 安装 golang 和 dep (附错两个误解决方法)
- Tensorflow2.0之语言模型数据集(周杰伦专辑歌词)预处理
- python爬虫(十三)selenium(Selenium入门、chromedriver、Phantomjs)
- Backspace删除键不能够使用的解决办法
- 利用requests库和Xpath爬取猫眼电影榜单【Python】
- zookeeper集群节点个数为什么最好是2n+1