转载请注明出处:http://blog.csdn.net/xiaanming/article/details/11821523

貌似有些天没有写博客了,前段时间在忙找工作的事,面试了几家公司,表示反响还不错,过完国庆节去新公司报道,期待新的公司,新的同事,而且新公司还有很多女孩子,哈哈,我可是一年多没和女孩子一起工作过了,之前的公司全是男的,你没听错,真的全是男的,我还以为我自己不会在爱了,现在Android市场还可以,想要跳槽换工作的赶紧,过了这个村就没这个店了,还有就是恭喜自己成了博客专家了,很开心也很感谢CSDN给我这份荣誉,我会继续写出对大家有用的博文,感谢大家的支持,今天继续给大家带来百度地图开发系列三 ,实现比例尺功能和替换自带的缩放组件,先看下项目工程结构

ScaleView是比例尺控件,ZoomControlView是缩放控件,MainActivity就是我们的主界面了

先看下ZoomControlView类,代码如下

package com.example.baidumapdemo;import com.baidu.mapapi.map.MapView;import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.view.View.OnClickListener;public class ZoomControlView extends RelativeLayout implements OnClickListener{private Button mButtonZoomin;private Button mButtonZoomout;private MapView mapView;private int maxZoomLevel;private int minZoomLevel;public ZoomControlView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public ZoomControlView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);init();}private void init() {View view = LayoutInflater.from(getContext()).inflate(R.layout.zoom_controls_layout, null);mButtonZoomin = (Button) view.findViewById(R.id.zoomin);mButtonZoomout = (Button) view.findViewById(R.id.zoomout);mButtonZoomin.setOnClickListener(this);mButtonZoomout.setOnClickListener(this);addView(view);}@Overridepublic void onClick(View v) {if(mapView == null){throw new NullPointerException("you can call setMapView(MapView mapView) at first");}switch (v.getId()) {case R.id.zoomin:{mapView.getController().zoomIn();break;}case R.id.zoomout:{mapView.getController().zoomOut();break;}}}/*** 与MapView设置关联* @param mapView*/public void setMapView(MapView mapView) {this.mapView = mapView;// 获取最大的缩放级别maxZoomLevel = mapView.getMaxZoomLevel();// 获取最大的缩放级别minZoomLevel = mapView.getMinZoomLevel();}/*** 根据MapView的缩放级别更新缩放按钮的状态,当达到最大缩放级别,设置mButtonZoomin* 为不能点击,反之设置mButtonZoomout* @param level*/public void refreshZoomButtonStatus(int level){if(mapView == null){throw new NullPointerException("you can call setMapView(MapView mapView) at first");}if(level > minZoomLevel && level < maxZoomLevel){if(!mButtonZoomout.isEnabled()){mButtonZoomout.setEnabled(true);}if(!mButtonZoomin.isEnabled()){ mButtonZoomin.setEnabled(true);}}else if(level == minZoomLevel ){mButtonZoomout.setEnabled(false);}else if(level == maxZoomLevel){mButtonZoomin.setEnabled(false);}}}

这个类封装好了地图的缩放功能,里面主要是两个按钮,一个按钮是放大MapView,当放大到了MapView的最大缩放级别,设置此按钮的Enable为false,另一个按钮缩小MapView,当缩小到了MapView最小的缩放级别,设置此按钮的Enable为false,refreshZoomButtonStatus()方法就是实现了此功能,我们根据MapView的缩放级别来更新按钮的状态,我们还必须调用setMapView(MapView mapView)方法来设置ZoomControlView与MapView关联,ZoomControlView的布局文件zoom_controls_layout我就不贴出来了,里面就两个按钮,然后给按钮设置背景选择器seletor

ScaleView类的代码如下

package com.example.baidumapdemo;import com.baidu.mapapi.map.MapView;
import com.baidu.platform.comapi.basestruct.GeoPoint;import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.NinePatch;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.view.View;public class ScaleView extends View {private Paint mPaint;/*** 比例尺的宽度*/private int scaleWidth;/*** 比例尺的高度*/private int scaleHeight = 4;/*** 比例尺上面字体的颜色*/private int textColor = Color.BLACK;/*** 比例尺上边的字体*/private String text;/*** 字体大小*/private int textSize = 16;/*** 比例尺与字体间的距离*/private int scaleSpaceText = 8;/*** 百度地图最大缩放级别*/private static final int MAX_LEVEL = 19;/*** 各级比例尺分母值数组*/private static final int[] SCALES = {20, 50, 100, 200, 500, 1000, 2000,5000, 10000, 20000, 25000, 50000, 100000, 200000, 500000, 1000000,2000000 };/*** 各级比例尺上面的文字数组*/private static final String[] SCALE_DESCS = { "20米", "50米", "100米", "200米","500米", "1公里", "2公里", "5公里", "10公里", "20公里", "25公里", "50公里","100公里", "200公里", "500公里", "1000公里", "2000公里" };private MapView mapView;/*** 与MapView设置关联* @param mapView*/public void setMapView(MapView mapView) {this.mapView = mapView;}public ScaleView(Context context) {this(context, null);}public ScaleView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public ScaleView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);mPaint = new Paint();}/*** 绘制上面的文字和下面的比例尺,因为比例尺是.9.png,我们需要利用drawNinepath方法绘制比例尺*/@SuppressLint("DrawAllocation")@Overrideprotected 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, scaleWidth, textSize + scaleSpaceText + scaleHeight);drawNinepath(canvas, R.drawable.icon_scale, scaleRect);}/*** 手动绘制.9.png图片* @param canvas* @param resId* @param rect*/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);  }/*** 测量ScaleView的方法,*/@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);int widthSize = getWidthSize(widthMeasureSpec);int heightSize = getHeightSize(heightMeasureSpec);setMeasuredDimension(widthSize, heightSize);}/*** 测量ScaleView的宽度* @param widthMeasureSpec* @return*/private int getWidthSize(int widthMeasureSpec){return MeasureSpec.getSize(widthMeasureSpec);}/*** 测量ScaleView的高度* @param widthMeasureSpec* @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;}/*** 根据缩放级别,得到对应比例尺在SCALES数组中的位置(索引)* @param zoomLevel* @return*/private static int getScaleIndex(int zoomLevel) {return MAX_LEVEL - zoomLevel;}/*** 根据缩放级别,得到对应比例尺* * @param zoomLevel* @return*/public static int getScale(int zoomLevel) {return SCALES[getScaleIndex(zoomLevel)];}/***  根据缩放级别,得到对应比例尺文字* @param zoomLevel* @return*/public static String getScaleDesc(int zoomLevel) {return SCALE_DESCS[getScaleIndex(zoomLevel)];}/*** 根据地图当前中心位置的纬度,当前比例尺,得出比例尺图标应该显示多长(多少像素)* @param map* @param scale* @return*/public static int meterToPixels(MapView map, int scale) {// 得到当前中心位置对象GeoPoint geoPoint = map.getMapCenter();// 得到当前中心位置纬度double latitude = geoPoint.getLatitudeE6() / 1E6;// 得到象素数,比如当前比例尺是1/10000,比如scale=10000,对应在该纬度应在地图中绘多少象素// 参考http://rainbow702.iteye.com/blog/1124244return (int) (map.getProjection().metersToEquatorPixels(scale) / (Math.cos(Math.toRadians(latitude))));}/*** 设置比例尺的宽度* @param scaleWidth*/public  void setScaleWidth(int scaleWidth) {this.scaleWidth = scaleWidth;}/*** 设置比例尺的上面的 text 例如 200公里* @param text*/private void setText(String text) {this.text = text;}/*** 设置字体大小* @param textSize*/public void setTextSize(int textSize) {this.textSize = textSize;invalidate();}/*** 根据缩放级别更新ScaleView的文字以及比例尺的长度* @param level*/public void refreshScaleView(int level) {if(mapView == null){throw new NullPointerException("you can call setMapView(MapView mapView) at first");}setText(getScaleDesc(level));setScaleWidth(meterToPixels(mapView, getScale(level)));invalidate();}}

ScaleView是比例尺控件类,主要是提供比例尺的绘制功能,在onDraw(Canvas canvas)的方法中绘制上面的距离和下面的比例尺长度,这里面要说下drawNinepath()方法,因为我们的比例尺图片是.9.png格式的,保证图片拉伸状态下不变形,如果用平常绘制一般图片的方法会报ClassCastException,所以我们可以利用drawNinepath()来手动绘制.9.png格式的图片,我们比例尺的长度是变化的,我们需要将以米为计量单位的距离(沿赤道)在当前缩放水平下转换到一个以像素(水平)为计量单位的距离,meterToPixels()方法根据我们MapView当前的缩放级别,得出比例尺图标应该显示多长,refreshScaleView()是用来更新ScaleView的,更新上面的字符串和下面比例尺的长度,当然我们也必须调用setMapView(MapView mapView)方法来设置ScaleView与MapView关联

接下来我们就来使用我们的比例尺控件和缩放控件了,先看下布局

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="fill_parent"android:layout_height="fill_parent" ><com.baidu.mapapi.map.MapViewandroid:id="@+id/bmapView"android:layout_width="fill_parent"android:layout_height="fill_parent"android:clickable="true" /><com.example.baidumapdemo.ZoomControlViewandroid:id="@+id/ZoomControlView"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentBottom="true"android:layout_alignParentRight="true"android:layout_marginBottom="20.0dip"android:layout_marginRight="5.0dip"/><com.example.baidumapdemo.ScaleViewandroid:id="@+id/scaleView"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentBottom="true"android:layout_alignParentLeft="true"android:layout_marginBottom="40dp"android:layout_marginLeft="20dp" /></RelativeLayout>

主界面MainActivity的代码如下

package com.example.baidumapdemo;import android.app.Activity;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.widget.Toast;import com.baidu.mapapi.BMapManager;
import com.baidu.mapapi.MKGeneralListener;
import com.baidu.mapapi.map.MKEvent;
import com.baidu.mapapi.map.MKMapViewListener;
import com.baidu.mapapi.map.MapController;
import com.baidu.mapapi.map.MapPoi;
import com.baidu.mapapi.map.MapView;
import com.baidu.platform.comapi.basestruct.GeoPoint;public class MainActivity extends Activity{private BMapManager mBMapManager;/*** MapView 是地图主控件*/private MapView mMapView = null;/*** 用MapController完成地图控制*/private MapController mMapController = null;private ScaleView mScaleView;private ZoomControlView mZoomControlView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);//使用地图sdk前需先初始化BMapManager,这个必须在setContentView()先初始化mBMapManager = new BMapManager(this);//第一个参数是API key,//第二个参数是常用事件监听,用来处理通常的网络错误,授权验证错误等,你也可以不添加这个回调接口mBMapManager.init("CC61ac7527b65c95899608810873b173", new MKGeneralListener() {//授权错误的时候调用的回调函数@Overridepublic void onGetPermissionState(int iError) {if (iError ==  MKEvent.ERROR_PERMISSION_DENIED) {Toast.makeText(getApplication(), "API Key错误,请检查!",Toast.LENGTH_LONG).show();}}//一些网络状态的错误处理回调函数@Overridepublic void onGetNetworkState(int iError) {if (iError == MKEvent.ERROR_NETWORK_CONNECT) {Toast.makeText(getApplication(), "您的网络出错啦!",Toast.LENGTH_LONG).show();}}});setContentView(R.layout.activity_main);mMapView = (MapView) findViewById(R.id.bmapView);//隐藏自带的地图缩放控件mMapView.setBuiltInZoomControls(false);mScaleView = (ScaleView) findViewById(R.id.scaleView);mScaleView.setMapView(mMapView);mZoomControlView = (ZoomControlView) findViewById(R.id.ZoomControlView);mZoomControlView.setMapView(mMapView);//地图显示事件监听器。 该接口监听地图显示事件,用户需要实现该接口以处理相应事件。mMapView.regMapViewListener(mBMapManager, new MKMapViewListener() {@Overridepublic void onMapMoveFinish() {refreshScaleAndZoomControl();}@Overridepublic void onMapLoadFinish() {}/*** 动画结束时会回调此消息.我们在此方法里面更新缩放按钮的状态*/@Overridepublic void onMapAnimationFinish() {refreshScaleAndZoomControl();}@Overridepublic void onGetCurrentMap(Bitmap arg0) {}@Overridepublic void onClickMapPoi(MapPoi arg0) {}});//获取地图控制器mMapController = mMapView.getController();//设置地图是否响应点击事件  .mMapController.enableClick(true);//设置地图缩放级别mMapController.setZoom(14);refreshScaleAndZoomControl();//保存精度和纬度的类,GeoPoint p = new GeoPoint((int)(22.547923 * 1E6), (int)(114.067368 * 1E6));//设置p地方为中心点mMapController.setCenter(p);}private void refreshScaleAndZoomControl(){//更新缩放按钮的状态mZoomControlView.refreshZoomButtonStatus(Math.round(mMapView.getZoomLevel()));mScaleView.refreshScaleView(Math.round(mMapView.getZoomLevel()));}@Overrideprotected void onResume() {//MapView的生命周期与Activity同步,当activity挂起时需调用MapView.onPause()mMapView.onResume();super.onResume();}@Overrideprotected void onPause() {//MapView的生命周期与Activity同步,当activity挂起时需调用MapView.onPause()mMapView.onPause();super.onPause();}@Overrideprotected void onDestroy() {//MapView的生命周期与Activity同步,当activity销毁时需调用MapView.destroy()mMapView.destroy();//退出应用调用BMapManager的destroy()方法if(mBMapManager != null){mBMapManager.destroy();mBMapManager = null;}super.onDestroy();}}

主界面的代码还是比较简单的,主要是利用MapView的regMapViewListener()来注册地图显示事件监听器。 该接口监听地图显示事件,用户需要实现该接口以处理相应事件,分别在回调方法onMapAnimationFinish()和onMapMoveFinish()来更新ZoomControlView和ScaleView的一些状态

在运行之前需要在Manifest中加入相对应的权限问题

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />  <uses-permission android:name="android.permission.INTERNET" />  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />  <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />  <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />  <uses-permission android:name="android.permission.READ_PHONE_STATE" />

运行结果

好了,今天的讲解到此结束,有疑问的朋友请在下面留言!

上面的代码有些东西没有贴出来,有兴趣的朋友可以下载源码项目源码,点击下载

Android 百度地图开发(三)--- 实现比例尺功能和替换自带的缩放组件相关推荐

  1. [android] 百度地图开发 (三).定位当前位置及getLastKnownLocation获取location总为空问题

           前一篇百度地图开发讲述"(二).定位城市位置和城市POI搜索",主要通过监听对象MKSearchListener类实现城市兴趣点POI(Point of Intere ...

  2. Android百度地图开发(二)定位之自动定位及标注(及定位几日内瓦或坐标4.9E-324问题)

    接上篇Android百度地图开发(一)之Hello BaiduMap 1.环境配置: 新增权限如下 <!-- 这个权限用于进行网络定位--> <uses-permission and ...

  3. 超详细的Android百度地图开发:在APP上定位并显示出来

    超详细的Android百度地图开发:在APP上定位并显示出来 一 写在前面 二 注册百度开发者账户.申请API KEY 三.代码实现 四.问题 五.总结 一 写在前面 由于项目所需,我需要在手机APP ...

  4. Android studio百度地图SDK开发 2020最新超详细的Android 百度地图开发讲解(3) 路线规划步行骑行驾车路线规划

    2020最新超详细的Android 百度地图开发讲解(3) 路线规划步行骑行驾车路线规划 开发前配置,显示基本地图,实时定位等查看之前代码,此博客紧接上一博客:https://blog.csdn.ne ...

  5. Android百度地图开发入门教程

    Android百度地图开发入门教程 1.平台注册登录 2.创建应用 3.Android studio配置 4.代码编写 5.最终效果(建议真机) 1.平台注册登录 登录百度地图开放平台网站注册并登录 ...

  6. android百度地图开发

    android百度地图开发 使用android开发百度地图需要事先在百度地图开发者平台上注册账号并下载百度地图相关的工具包,之后配置到自己的程序中,具体可参考https://lbsyun.baidu. ...

  7. android 百度地图开发 别人用不了,Android百度地图开发的那些不足之处

    Android百度地图开发的那些不足之处,最近做的项目中百度地图是很重要的一个模块,其中实现了定位.自定义Marker图标.线路规划.SuggestionSearch检索.地图截图以及导航等功能.因为 ...

  8. Android 百度地图开发(二)

    前面我们一起了解了百度地图的申请与集成Android 百度地图开发(一),今天我们接着来学习百度地图. 今天主要来了解如下问题: 1.百度地图的生命周期控制 上一篇张我们已经在布局文件里增加了mapV ...

  9. [android] 百度地图开发 (一).申请AK显示地图及解决显示空白网格问题

        最近做android百度地图,但是使用baidumapapi_v2_3_1.jar和libBaiduMapSDK_v2_3_1.so显示百度地图时总是遇到问题--只显示网格而没有显示地图,网络 ...

最新文章

  1. MySQL server PID file could not be found!
  2. curl命令的超时时间
  3. 25个关键技术点,带你熟悉Python
  4. Div+CSS教程----DivCSS布局绝对定位和浮动
  5. linux内存管理(八)-不连续页分配和页表
  6. 没有php5.sowenjian_(转)LINUX下PHP编译添加相应的动态扩展模块so(不需要重新编译PHP,以openssl.so为例...
  7. 如何自定义python语法.
  8. 通过doi可以检索到文献_什么是DOI?如何获取文献的DOI?
  9. CSS相对定位和绝对定位
  10. 计算机专业软件工程专业学科排名2015,软件工程专业排名
  11. 单样本学习(One shot learning)和孪生网络(Siamese Network)简介
  12. python lncrna_[转载]lncrna分析流程
  13. 摩托车新手驾驶教程[3]
  14. Android4.0的StatusBar和NavigationBar
  15. 丁香园开源接口管理系统 - API Mocker
  16. 《人性的弱点》经典语录
  17. 【小程序】微信小程序集成环信im
  18. 写论文要学python的哪些部分组成_一篇完整的论文由哪几个部分组成
  19. 用户管理系统功能测试报告
  20. mysql自动备份脚本下载+简单解读

热门文章

  1. 宣城市加快运用大数据推动全域旅游发展
  2. SQL 增删改查(具体)
  3. IDEA用maven整合ssh框架
  4. andriod创建用户界面(1)
  5. Uva_11235_Frequent values
  6. 这里90%的程序员根本就不算程序员。
  7. Glomosim安装和ParseC的使用等相关链接
  8. Linux下怎么使用任务管理器和真人接口源码出售进程管理
  9. 小程序 Serverless: 解放生产力,驱动研发效能提升
  10. Linux常用正则表达式