高德地图有提供自带的比例尺,但是不能改变位置,只能固定在屏幕右下角,做项目时,有些需求非要在某个位置,那就只能自定义了。

用高德自带的比例尺测试过,同一缩放等级,不同经纬度,比例尺也可能是不一样的,所以不能根据缩放等级处理。

好在高德地图有提供相应api

比例尺数据:AMap. getScalePerPixel()可以获取当前地图级别下1像素点对应的距离长度(米),然后可自定义比例尺长度(如100像素)。

效果图如下。

完整代码:

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;import com.amap.api.maps.AMap;
import com.autonavi.amap.mapcore.DPoint;
import com.autonavi.amap.mapcore.IPoint;
import com.autonavi.amap.mapcore.VirtualEarthProjection;/*** @author gcz* blog https://blog.csdn.net/z19980115/article/details/78795329*/
public final class MapScaleView extends View {private static final float a = 0.9F;//最大宽度,超过该宽度就向下一级转换private static final int maxWidth = 150;//比例尺文本private String text = "";//比例尺宽度private int lineWidth = 50;//视图高度private int viewHeight;//比例尺线条画笔private Paint linePaint;//比例尺文本画笔private Paint textPaint;//文本的区域private Rect rect;private IPoint point;//1dp转px后的值private float dp1 = 0.0F;private final int[] level = new int[]{10000000, 5000000, 2000000, 1000000, 500000, 200000, 100000, 50000, 30000, 20000, 10000, 5000, 2000, 1000, 500, 200, 100, 50, 25, 10, 5};public MapScaleView(Context context) {this(context, null);}public MapScaleView(Context context, @Nullable AttributeSet attrs) {this(context, attrs, 0);}public MapScaleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init(context);}private void init(Context context) {this.rect = new Rect(0, 0, 0, 10);this.linePaint = new Paint();this.linePaint.setAntiAlias(true);this.linePaint.setColor(Color.WHITE);this.linePaint.setStrokeWidth(2.0F * a);this.linePaint.setStyle(Paint.Style.STROKE);this.textPaint = new Paint();this.textPaint.setAntiAlias(true);this.textPaint.setColor(Color.WHITE);this.textPaint.setTextSize(20.0F * a);this.dp1 = (float) getDp1(context);this.point = new IPoint();}public void destroy() {this.linePaint = null;this.textPaint = null;this.rect = null;this.text = null;this.point = null;}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);if (this.text != null && !this.text.equals("") && this.lineWidth != 0) {this.textPaint.getTextBounds(this.text, 0, this.text.length(), this.rect);int x = 1;int y = viewHeight - this.rect.height() + 5;canvas.drawText(this.text, (this.lineWidth - this.rect.width()) / 2, y, this.textPaint);y += this.rect.height() - 5;//左竖线canvas.drawLine(x, y - 3.0F * this.dp1, x, y + a, this.linePaint);//横线canvas.drawLine(x, y - x, this.lineWidth, y - x, this.linePaint);//右竖线canvas.drawLine(this.lineWidth, y - 3.0F * this.dp1, this.lineWidth, y + a, this.linePaint);}}public void refreshScaleView(AMap aMap) {if (aMap == null) return;try {float zoom = aMap.getCameraPosition().zoom;//获取地图中心坐标aMap.getP20MapCenter(this.point);if (this.point != null) {DPoint dPoint = VirtualEarthProjection.PixelsToLatLong((long) this.point.x, (long) this.point.y, 20);float var3 = 1;//屏幕上1像素点对应的地图上距离长度,单位米,等同于aMap.getScalePerPixel();double scalePerPixel = (double) ((float) (Math.cos(dPoint.y * 3.141592653589793D / 180.0D) * 2.0D * 3.141592653589793D * 6378137.0D / (256.0D * Math.pow(2.0D, (double) zoom))));//比例尺宽度int lineWidth = (int) ((double) this.level[(int) zoom] / (scalePerPixel * (double) var3));String lineText = formatDistance(this.level[(int) zoom]);//如果超过最大宽度,则向下一级转换while (lineWidth > maxWidth && zoom < 19) {zoom++;lineWidth = (int) ((double) this.level[(int) zoom] / (scalePerPixel * (double) var3));lineText = formatDistance(this.level[(int) zoom]);}this.lineWidth = lineWidth;this.text = lineText;dPoint.recycle();this.requestLayout();this.invalidate();}} catch (Throwable throwable) {throwable.printStackTrace();}}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {int widthSize = MeasureSpec.getSize(widthMeasureSpec);int widthMode = MeasureSpec.getMode(widthMeasureSpec);int resultWidth;if (widthMode == MeasureSpec.EXACTLY) {//精确模式,写死宽度的情况resultWidth = widthSize;} else {resultWidth = Math.max(lineWidth, rect.width()) + 2;if (widthMode == MeasureSpec.AT_MOST) {//最大模式,父容器给的最大空间resultWidth = Math.min(resultWidth, widthSize);}}int heightSize = getHeightSize(heightMeasureSpec);viewHeight = heightSize;setMeasuredDimension(resultWidth, heightSize);}/*** 测量ScaleView的高度*/private int getHeightSize(int heightMeasureSpec) {int mode = MeasureSpec.getMode(heightMeasureSpec);int height = 0;switch (mode) {case MeasureSpec.AT_MOST:height = (int) (rect.height() + 5 + 3F * this.dp1 + a);break;case MeasureSpec.EXACTLY: {height = MeasureSpec.getSize(heightMeasureSpec);break;}case MeasureSpec.UNSPECIFIED: {height = Math.max((int) (rect.height() + 5 + 3F * this.dp1 + a), MeasureSpec.getSize(heightMeasureSpec));break;}}return height;}public static String formatDistance(int m) {String distance;if (m < 1000) {distance = m + "m";} else {distance = m / 1000 + "km";}return distance;}/*** 1dp转px*/public static int getDp1(Context var0) {float var1 = var0.getResources().getDisplayMetrics().density;return (int) (1.0F * var1 + 0.5F);}
}

使用方法: 和正常view一样添加到layout中,注意 修改包名

<com.xxx.xxx.MapScaleViewandroid:id="@+id/blc"android:layout_width="wrap_content"android:layout_height="wrap_content" />

OnCameraChangeListeneronCameraChange中调用比例尺的refreshScaleView()

override fun onCameraChange(p0: CameraPosition?) {if (p0 == null) returnblc.refreshScaleView(mMap)
}

参考资料:
如何自定义指南针、缩放按钮、比例尺控件、定位按钮?
ArcGIS for Android 自定义地图比例尺

Android 自定义高德地图比例尺相关推荐

  1. Android自定义导览地图组件(一)

    丨版权说明 : <Android自定义导览地图组件(一)>于当前CSDN博客和乘月网属同一原创,转载请说明出处,谢谢.          鉴于Android关于自定义导览地图的相关资料以及 ...

  2. Android自定义ViewGroup基本步骤

    1.自定义属性,获取自定义属性,可参考 ​ Android自定义View基本步骤 ​ 2.onMeasure() 方法,for循环测量子View,根据子View的宽高来计算自己的宽 高 3.onDra ...

  3. Android自定义View —— TypedArray

    在上一篇中Android 自定义View Canvas -- Bitmap写到了TypedArray 这个属性 下面也简单的说一下TypedArray的使用 TypedArray 的作用: 用于从该结 ...

  4. Android 自定义View —— Canvas

    上一篇在android 自定义view Paint 里面 说了几种常见的Point 属性 绘制图形的时候下面总有一个canvas ,Canvas 是是画布 上面可以绘制点,线,正方形,圆,等等,需要和 ...

  5. android 自定义loading,Android自定义动画-StarLoadingView

    今天来分享第二个自定义loading的动画,起了个名字叫 蹦跶的星星 ,还是老规矩先介绍,后上图. 实现效果在最后,GIF有点大,手机流量慎重. 介绍 首先声明做这个动画的初衷是为了学习和分享,所以从 ...

  6. android自定义view获取控件,android 自定义控件View在Activity中使用findByViewId得到结果为null...

    转载:http://blog.csdn.net/xiabing082/article/details/48781489 1.  大家常常自定义view,,然后在xml 中添加该view 组件..如果在 ...

  7. android 自定义命名空间,Android自定义ActionBar实例

    本文实例讲述了android自定义actionbar的实现方法.分享给大家供大家参考.具体实现方法如下: android 3.0及以上已经有了actionbar的api,可以通过引入support p ...

  8. Android自定义View:ViewGroup(三)

    自定义ViewGroup本质是什么? 自定义ViewGroup本质上就干一件事--layout. layout 我们知道ViewGroup是一个组合View,它与普通的基本View(只要不是ViewG ...

  9. Android自定义视图四:定制onMeasure强制显示为方形

    这个系列是老外写的,干货!翻译出来一起学习.如有不妥,不吝赐教! Android自定义视图一:扩展现有的视图,添加新的XML属性 Android自定义视图二:如何绘制内容 Android自定义视图三: ...

  10. android自定义滑块解锁,android 滑动解锁

    通过android自定义View实现横向的滑动解锁,1.滑动到中间会自动返回到原始的位置,2.滑动到底部会自动解锁,会触发解锁的回调:首先看效果图如下: 实现以上部分一共分为三部分: 其中背景通过sh ...

最新文章

  1. python中数据类型为list_python_数据类型_list
  2. 西安java招聘_西安招聘 | 陕西安控科技公司招聘(员工宿舍、节日福利、餐补)...
  3. http的方式调用接口
  4. 动态输出html一些效果失效的处理
  5. ACdream 1431 Sum vs Product
  6. CentOS如何挂载硬盘
  7. .NET Core 小程序开发零基础系列(1)——开发者启用并牵手成功
  8. Linux统治超级计算领域的九个理由
  9. python数据分析的步骤排序_Python数据分析
  10. u盘pe无人值守linux,从U盘无人值守安装linux操作系统(纯实践笔记
  11. 使用SVG绘制湖南地图
  12. 组合导航:中海达iNAV2产品描述及接口描述
  13. JAVA微信小程序医院预约挂号小程序系统毕业设计 开题报告
  14. M2BEV:采用统一BEV表征的多摄像头联合3D检测分割
  15. Python脚本调用谷歌浏览器的谷歌翻译
  16. 中间件小师妹 de 年度工作总结
  17. 7月23日09点,上海,PMCamp的产品经理大会
  18. 迅软科技协助化妆行业从根本上解决敏感数据泄露问题!
  19. 【技术美术百人计划】美术 1.1 美术理论基础
  20. 小白投资必备:主板、创业板、科创板、新三板区别与联系

热门文章

  1. 机器学习/深度学习算法学习心得
  2. 数据应用系统的压力测试方案
  3. 搞定从mac把超过4G的文件拷入U盘
  4. 知识图谱—知识存储—仅用neo4j搭建简单的金融知识图谱
  5. bp神经网络综合评价例题,bp神经网络综合评价法
  6. 今日头条推荐算法研究
  7. 计算机软件毕业论文周记,毕业论文写作周记范文共12周
  8. H5标签 marquee 滚动字幕
  9. 这40个自学网站,一年让你“白捡”十几万,快点收藏
  10. python爬取必应的壁纸