在给mapbox地图添加比例尺的时候,我没有找到mapbox自带的比例尺,所以就自己写了一个。和其他自定义比例尺原理其实都差不多。首先,加载mapbox地图,这个就不再详细叙述,照着mapbox官网的教程打下来就行了。

定义一个自定义View,MapScaleView,在这里计算每一级比例尺在屏幕上需要绘制的长度。计算比例尺的原理是获取屏幕中心的一点的每像素代表的实际距离,因为在同一纬度上每像素代表的实际距离是相同的。因此在纬度上 实际距离除以屏幕中心的每像素代表的距离就等于在屏幕上需要绘制的像素长度,然后使用画笔画线,长度等于算出的像素长度。

 metersPerPixel = mapboxMap.getProjection().getMetersPerPixelAtLatitude(mapboxMap.getCameraPosition().target.getLatitude());

这个就是在屏幕中心,在纬度上每像素代表的实际距离。

下面是自定义View

package com.geocompass.mapboxscale;import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;import com.mapbox.mapboxsdk.maps.MapboxMap;/*** Created by admin on 2018/8/8.*/public class MapScaleView extends View {private Paint mPaint;private int scaleWidth;private int scaleHeight;private int scaleSpaceText;private int textSize;private String text;private int marginStartX = 20;//距离x轴20px处开始绘制比例尺private int verticalY = 5;//竖线相对横线向上或向下的距离public MapScaleView(Context context) {this(context, null);}public MapScaleView(Context context, AttributeSet attrs) {super(context, attrs);initView();}//这个构造方法是在第二个基础上再传入style的。public MapScaleView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);}private void initView() {mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);setBackgroundColor(getResources().getColor(R.color.transparent));scaleWidth = 360;//比例尺宽度scaleHeight = SystemHelper.dip2px(this.getContext(), 3);//比例尺高度text = "10km";//比例尺文本textSize = SystemHelper.sp2px(this.getContext(), 13);//比例尺字体scaleSpaceText = scaleHeight;//比例尺文本与图形的间隔高度mPaint.setColor(Color.BLACK);mPaint.setAntiAlias(true);mPaint.setStrokeWidth(2f);//设置画笔宽度mPaint.setTextSize(textSize);}/*** 从距离x轴20,y轴画布宽的2/3处开始画线*/@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);//绘制直线canvas.drawLine(marginStartX, 2 * getHeight() / 3 - verticalY, marginStartX, 2 * getHeight() / 3 + verticalY, mPaint);//绘制比例尺左边竖线canvas.drawLine(marginStartX, 2 * getHeight() / 3, marginStartX + scaleWidth, 2 * getHeight() / 3, mPaint);//绘制比例尺可变横线canvas.drawLine(marginStartX + scaleWidth, 2 * getHeight() / 3 - verticalY,marginStartX + scaleWidth, 2 * getHeight() / 3 + verticalY, mPaint);//绘制比例尺右边竖线canvas.drawText(text, marginStartX, textSize, mPaint);//绘制字体}@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 = scaleWidth;if (widthMode == MeasureSpec.AT_MOST) {resultWidth = Math.min(resultWidth, widthSize);}}int heightSize = getHeightSize(heightMeasureSpec) + 20;setMeasuredDimension(resultWidth, heightSize);}/*** 测量ScaleView的高度*/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;}/*** 根据缩放级别更新ScaleView的文字以及比例尺的长度*/double metersPerPixel = 0;public void refreshScaleView(MapboxMap mapboxMap) {if (mapboxMap == null) {return;}metersPerPixel = mapboxMap.getProjection().getMetersPerPixelAtLatitude(mapboxMap.getCameraPosition().target.getLatitude());//获取在纬度上每像素代表的距离(米)int curZoom = (int) Math.round(mapboxMap.getCameraPosition().zoom);switch (curZoom) {case 2:text = "1000km";scaleWidth = (int) (1000000 / metersPerPixel);break;case 3:text = "500km";scaleWidth = (int) (500000 / metersPerPixel);break;case 4:text = "200km";scaleWidth = (int) (200000 / metersPerPixel);break;case 5:text = "100km";scaleWidth = (int) (100000 / metersPerPixel);break;case 6:text = "50km";scaleWidth = (int) (50000 / metersPerPixel);break;case 7:text = "20km";scaleWidth = (int) (20000 / metersPerPixel);break;case 8:text = "10km";scaleWidth = (int) (10000 / metersPerPixel);break;case 9:text = "5km";scaleWidth = (int) (5000 / metersPerPixel);break;case 10:text = "2km";scaleWidth = (int) (2000 / metersPerPixel);break;case 11:text = "1km";scaleWidth = (int) (1000 / metersPerPixel);break;case 12:text = "500m";scaleWidth = (int) (500 / metersPerPixel);break;case 13:text = "200m";scaleWidth = (int) (200 / metersPerPixel);break;case 14:text = "100m";scaleWidth = (int) (100 / metersPerPixel);break;case 15:text = "50m";scaleWidth = (int) (50 / metersPerPixel);break;case 16:text = "20m";scaleWidth = (int) (20 / metersPerPixel);break;case 17:text = "10m";scaleWidth = (int) (10 / metersPerPixel);break;case 18:text = "5m";scaleWidth = (int) (5 / metersPerPixel);break;default:break;}this.postInvalidate();}
}

在MapActivity里面调用下面的代码就可以刷新比例尺。

 /*** 控制比例尺* */mMapboxMap.setOnCameraChangeListener(new MapboxMap.OnCameraChangeListener() {@Overridepublic void onCameraChange(CameraPosition position) {MapScaleView mapScaleView = findViewById(R.id.view_scale_map);mapScaleView.refreshScaleView(mMapboxMap);}});}

源码链接:https://download.csdn.net/download/ymszzu/10594189

Android安卓 自定义mapbox地图比例尺相关推荐

  1. Android 安卓 自定义标题栏+沉浸式状态栏

    Android 安卓 自定义标题栏+沉浸式状态栏 由于Android原生的标题栏单调,简单,并不是很好看,自定义个性化的标题栏可以让app更加美观. Android 4.4以后增加了沉浸式透明状态栏. ...

  2. Android/安卓 自定义Dialog 最简单、最详细解释

    看了很多视频,也在网上找了一些浏览量最多的文章,发现都太难懂或者太复杂,夹杂了很多其他功能,自定义度太高,很繁琐.所以我想写一个基础的自定义Dialog,只涉及基础的自定义,其他复杂的自定义可以在这个 ...

  3. Android安卓仿IOS音量调节-自定义view系列(4)

    Android安卓仿IOS音量调节-自定义view系列 功能简介 主要实现步骤 xml相关属性设置 java代码 Android技术生活交流 更多其他页面-自定义View-实用功能合集:点击查看 Gi ...

  4. android 顶部导航栏 自定义,Android自定义NavigationController - 安卓自定义导航栏 --【WJ】...

    注意: 本文主要介绍安卓自定义顶部导航栏(iOS中成为NavigationBar):写的不尽如人意的地方,请见谅~ 概述如下: 环境 :Android Studio 1.4 for Mac 语言 :如 ...

  5. android如何自定义dialog,安卓dialog的使用+如何自定义dialog

    什么叫dialog 简单来说就是一句话: 弹出一个窗口,提示用户自己去选择,去提示,去分类的一些内容. 安卓自带的dialog有三种: - AlertDialog--普通的提示对话框 - Progre ...

  6. Android微信浏览器标题,企业微信内H5网页分享微信好友ios正常安卓自定义标题、图标、未生效...

    企业微信内H5网页分享微信好友ios正常安卓自定义标题.图标.未生效 问题类型 API/组件名称 终端类型 微信版本 基础库版本 Bug 'onMenuShareWeibo', 'onMenuShar ...

  7. android控件向内弧度_安卓自定义 View 基础:坐标系、角度弧度、颜色

    安卓自定义View基础 - 坐标系 一.屏幕坐标系和数学坐标系的区别 由于移动设备一般定义屏幕左上角为坐标原点,向右为x轴增大方向,向下为y轴增大方向, 所以在手机屏幕上的坐标系与数学中常见的坐标系是 ...

  8. Android怎么自定义充电铃声,安卓手机充电提示音怎么修改?安卓充电提示音怎么设置自定义...

    最近苹果ios14可以自定义充电提示音了,相信很多安卓手机的用户朋友们也想要设置,那么安卓修改充电提示音怎么弄呢?安卓自定义充电提示音在哪设置呢?下面小编就为大家带来相关介绍,感兴趣的朋友们快来一起了 ...

  9. android 自定义弹窗diss,Android中自定义PopupWindow,动态弹窗。

    我的第一篇博客,咱们直奔主题.先上个效果图 在android中自定义PopupWindow: 1.首先定义好你想要显示的窗口的布局文件,再实例化一个View对象:窗口布局可灵活变化,dialog_la ...

  10. 安卓自定义view全解:初始化,onDraw函数,onMeasure函数,用户手势事件

    全栈工程师开发手册 (作者:栾鹏) 安卓教程全解 安卓自定义view全解. view类包含如下函数.可供重写. onFinishInflate() 回调方法,当应用从XML加载该组件并用它构建界面之后 ...

最新文章

  1. com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'rtjhyt' in 'field list'
  2. Spring Annotation Processing: How It Works--转
  3. java常见异常说明汇总
  4. Flask-sqlalchemy外键关系映射
  5. 顺序表的所有基本操作
  6. 移除Java对象中的属性_在java对象中添加和删除属性
  7. 中职计算机组成原理期末,计组期末复习
  8. Intel Core Solo/Duo处理器架构/微架构/流水线 - 前端/数据预取/SSE3
  9. php大量数据库抽象,数据库的数据抽象有几个级别
  10. 想转行做web前端工程师,必学这6大技能
  11. myEclipse-svn的安装使用
  12. 计算机初级技能词,计算机领域英语常用词汇初级.doc
  13. Unity3D mac版汉化教程
  14. php 跨域请求 header 头
  15. Sqlite3相关函数返回值及其含义
  16. 美国物流发展趋势对中国物流的影响
  17. 头部公司的Robotaxi何时能拿掉安全员?
  18. telephony-apps
  19. Keycloak授权服务指南
  20. 性能测试之tcpcopy引流工具介绍

热门文章

  1. 企业工商数据查询接口
  2. 常用URL schemes ✨支付宝 、微信、腾讯、百度、网易、银行 、社交 、音频 、工具大集合
  3. ACM的奇计淫巧_扩栈C++/G++
  4. wps垂直排列标题与文本_如何垂直设置wps文本
  5. Opencv 将GIF格式图片转为JPG、JPEG等格式图片
  6. PC端打开微信公众号文章 图片加载慢的解决方法
  7. PS魔棒工具提示不能完成请求,因为程序错误和不能完成请求,因为没有足够内存以及内存不能为read的处理
  8. 嵌入式linux设置屏幕亮度
  9. 常见的浏览器与内核你知道都有哪些吗?
  10. Chrome谷歌浏览器安装与配置教程