Android 百度地图开发(三)
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);
- }
- @Override
- public 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的缩放级别更新缩放button的状态。当达到最大缩放级别,设置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);
- }
- }
- }
这个类封装好了地图的缩放功能,里面主要是两个button,一个button是放大MapView。当放大到了MapView的最大缩放级别,设置此button的Enable为false,还有一个button缩小MapView,当缩小到了MapView最小的缩放级别,设置此button的Enable为false。refreshZoomButtonStatus()方法就是实现了此功能,我们依据MapView的缩放级别来更新button的状态,我们还必须调用setMapView(MapView
mapView)方法来设置ZoomControlView与MapView关联,ZoomControlView的布局文件zoom_controls_layout我就不贴出来了,里面就两个button,然后给button设置背景选择器seletor
ScaleView类的代码例如以下
- <span style="font-family:System;font-size:12px;">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")
- @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, 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的方法。
- */
- @Override
- protected 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/1124244
- return (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();
- }
- }</span>
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.MapView
- android:id="@+id/bmapView"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:clickable="true" />
- <com.example.baidumapdemo.ZoomControlView
- android: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.ScaleView
- android: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;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- //使用地图sdk前需先初始化BMapManager,这个必须在setContentView()先初始化
- mBMapManager = new BMapManager(this);
- //第一个參数是API key,
- //第二个參数是经常使用事件监听,用来处理通常的网络错误,授权验证错误等,你也能够不加入这个回调接口
- mBMapManager.init("CC61ac7527b65c95899608810873b173", new MKGeneralListener() {
- //授权错误的时候调用的回调函数
- @Override
- public void onGetPermissionState(int iError) {
- if (iError == MKEvent.ERROR_PERMISSION_DENIED) {
- Toast.makeText(getApplication(), "API Key错误。请检查。",
- Toast.LENGTH_LONG).show();
- }
- }
- //一些网络状态的错误处理回调函数
- @Override
- public 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() {
- @Override
- public void onMapMoveFinish() {
- refreshScaleAndZoomControl();
- }
- @Override
- public void onMapLoadFinish() {
- }
- /**
- * 动画结束时会回调此消息.我们在此方法里面更新缩放button的状态
- */
- @Override
- public void onMapAnimationFinish() {
- refreshScaleAndZoomControl();
- }
- @Override
- public void onGetCurrentMap(Bitmap arg0) {
- }
- @Override
- public 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(){
- //更新缩放button的状态
- mZoomControlView.refreshZoomButtonStatus(Math.round(mMapView.getZoomLevel()));
- mScaleView.refreshScaleView(Math.round(mMapView.getZoomLevel()));
- }
- @Override
- protected void onResume() {
- //MapView的生命周期与Activity同步,当activity挂起时需调用MapView.onPause()
- mMapView.onResume();
- super.onResume();
- }
- @Override
- protected void onPause() {
- //MapView的生命周期与Activity同步。当activity挂起时需调用MapView.onPause()
- mMapView.onPause();
- super.onPause();
- }
- @Override
- protected 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" />
执行结果
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveGlhYW5taW5n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" width="240" height="400" hspace="10" alt="" style="border:none; max-width:100%">
好了,今天的解说到此结束。有疑问的朋友请在以下留言!
Android 百度地图开发(三)的更多相关文章
- Android 百度地图开发(一)--- 申请API Key和在项目中显示百度地图
标签: Android百度地图API Key 分类: Android 百度地图开发(2) 最近自己想研究下地图,本来想研究google Map,但是申请API key比较坑爹,于是从百度地 ...
- android 百度地图开发实例(转载)
因为在我的寝室google基站定位返回的数据总是为空,所以换成百度地图,发现百度地图开发起来非常方便,提供了许多有用的工具,地图的加载速度也比google地图快许多. 为了加强记忆,写一点androi ...
- C#的百度地图开发(三)依据坐标获取位置、商圈及周边信息
原文:C#的百度地图开发(三)依据坐标获取位置.商圈及周边信息 我们得到了百度坐标,现在依据这一坐标来获取相应的信息.下面是相应的代码 public class BaiduMap { /// < ...
- [android] 百度地图开发 (一).申请AK显示地图及解决显示空白网格问题
近期做android百度地图,可是使用baidumapapi_v2_3_1.jar和libBaiduMapSDK_v2_3_1.so显示百度地图时总是遇到问题--仅仅显示网格而没有显示地图,网 ...
- Android 百度地图开发之一(Hello BaiDu Map)
之前也接触过百度地图的开发,但那是在网上找的案例或代码,而且是比较老的版本.打算重新学习一下百度地图的开发. 本次使用的百度地图的版本是 Android SDK v3.0.0 本篇文章主要讲述百度地图 ...
- [android] 百度地图开发 (两).所在地的城市定位和城市POI搜索
一个. 百度地图城市位置和POI搜索知识 上一篇文章"百度地图开发(一)"中讲述了怎样申请百度APIKey及解决显示空白网格的问题.该篇文章主要讲述怎样定位城市位置.定 ...
- Android百度地图开发(一)之初体验
转载请注明出处:http://blog.csdn.net/crazy1235/article/details/42614603 做关于位置或者定位的app的时候免不了使用地图功能,本人最近由于项目的需 ...
- Android百度地图开发03之地图控制 + 定位
前两篇关于百度地图的blog写的是,一些基本图层的展示 和 覆盖物的添加+地理编码和反地理编码. 接下来,这篇blog主要说一些关于地图控制方面的内容和定位功能. 百度地图提供的关于地图的操作主要有: ...
- Android百度地图开发01之初体验
做关于位置或者定位的app的时候免不了使用地图功能,本人最近由于项目的需求需要使用百度地图的一些功能,所以这几天研究了一下,现写一下blog记录一下,欢迎大家评论指正! 一.申请AK(API Key) ...
随机推荐
- 原生js实现ajax跨域(兼容IE8,IE9)
html设置meta标签兼容360兼容模式和IE怪异模式 <meta http-equiv="X-UA-Compatible" content="IE=9;IE=8 ...
- 使用html+css+js实现弹球游戏
使用html+css+js实现弹球游戏 效果图: 代码如下,复制即可使用: <!doctype html> <head> <style type="text/c ...
- Python PIL: cannot write mode RGBA as BMP(把有四位通道(RGBA)的图片换成有三位通道的(RGA))
图片png结尾的有四个通道RGBA,把四个通道改为三个通道(RGB),如下,bg为修改后的图片 img = Image.open('pic\\find.png')bg = Image.new(&quo ...
- ddmlib问题总结——同步获取设备信息
通过IDevice.getProperty(String name)得到响应的设备属性.在实际的使用过程中发现,我的manufacturer总是获取不到,为null(获取代码如下),而剩下的属性都可以 ...
- 【Java】 大话数据结构(18) 排序算法(5) (直接插入排序)
本文根据<大话数据结构>一书,实现了Java版的直接插入排序. 更多:数据结构与算法合集 基本概念 直接插入排序思路:类似扑克牌的排序过程,从左到右依次遍历,如果遇到一个数小于前一个数,则 ...
- 001 jquery对象与dom对象的转换
1.jQuery对象介绍 2.jQuery对象转换为Dom对象 3.Dom转换为Jquery对象 4.将jquery转换为Dom程序 <!DOCTYPE html> <html> ...
- 如何在Ubuntu 18.04上安装和配置Apache 2 Web服务器(转)
如何在Ubuntu 18.04上安装和配置Apache 2 Web服务器 什么是Apache Web Server? Apache或Apache HTTP服务器是一个免费的开源Web服务器,由Apac ...
- django模型查询操作
一旦创建好了数据模型,Django就会自动为我们提供一个数据库抽象API,允许创建.检索.更新和删除对象操作 下面的示例都是通过下面参考模型来对模型字段进行操作说明: from django.db i ...
- usb3.0 monitor is already started
用360 开机加速里找到这个程序,把它从开机启动中删除掉就好.
- 项目冲刺Second
Second Sprint 1.各个成员今日完成的任务 蔡振翼:完成管理员界面 谢孟轩:完成用户界面 林凯:完成登录界面 肖志豪:完成主界面 吴文清:创建数据库 刘华强:完成连接数据库,编写查询语句 ...
