- 浏览: 766934 次
- 性别:
- 来自: 大连
-
文章分类
最新评论
-
xuelj:
我的Android进阶之旅------>Android使用9Patch图片作为不失真背景 -
lBovinl:
,浩瀚~
我的Android进阶之旅------>经典的大客推荐(排名不分先后)!! -
xyy_zero:
看着听犀利的,大神,有demo吗?可以分享下不。我最近需要开发 ...
给android设备增加串口功能
Android 百度地图开发(三)--- 实现比例尺功能和替换自带的缩放组件
转载请注明出处: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); } @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的缩放级别更新缩放按钮的状态,当达到最大缩放级别,设置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")
@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();
}
}
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() { } /** * 动画结束时会回调此消息.我们在此方法里面更新缩放按钮的状态 */ @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(){ //更新缩放按钮的状态 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" />
运行结果
好了,今天的讲解到此结束,有疑问的朋友请在下面留言!
上面的代码有些东西没有贴出来,有兴趣的朋友可以下载源码项目源码,点击下载
相关推荐
在Android开发中,Mapbox是一个强大的地图服务框架,它提供了丰富的自定义功能,使得开发者能够构建出具有个性化设计的地图应用。本教程将详细介绍如何在Mapbox地图中实现自定义比例尺的功能。 首先,我们需要理解...
通过以上步骤,我们实现了在Android应用中监听百度地图缩放事件的功能。这对于实时更新地图上的标记位置或者其他地图相关的交互操作非常有用。在实际开发过程中,可以根据具体需求调整监听器中的逻辑处理,以满足...
通过对"老罗android 百度地图开发源码"的深入学习和实践,我们可以掌握如何在Android应用中有效利用百度地图API,提高应用的功能性和用户体验。同时,这也为我们提供了学习其他地图服务提供商API(如高德地图、谷歌...
在Android平台上进行百度地图开发是一项常见的任务,它涉及到多个技术和组件的集成。下面将详细讲解这一主题的关键知识点。 首先,我们需要了解的是**百度地图API**。这是百度提供的一套服务,允许开发者在其应用中...
在Android应用开发中,百度地图API是一个非常重要的工具,它为开发者提供了丰富的地图功能,包括地图展示、路径规划、地理围栏、公交查询以及经纬度转换等。"百度地图实战开发--老罗源码"是一个专门针对这些功能的...
在Android应用开发中,集成百度地图API是一项常见的需求,它能为用户提供丰富的地图服务功能,如定位、导航、路线规划等。本篇文章将详细介绍如何在Android项目中进行百度地图的开发,以及一些关键的技术点。 首先...
范例使用SuperMap iClient 7C for JavaScript开发模式,通过SuperMap.Layer.TiledDynamicRESTLayer的scales 属性设置地图缩放比例尺。
在Android平台上开发基于百度地图的应用是一项常见的任务,它涉及到Android编程、网络通信、地理信息系统(GIS)以及百度地图API的使用。本项目标题为“基于android的百度地图应用”,其描述指出该应用功能虽简单但...
在Android开发中,百度地图API是一个非常常用的工具,它提供了丰富的地图展示和地理位置服务功能。在标题"百度地图3.0自定义缩放按钮"中,我们关注的是如何个性化地图应用,具体来说就是如何替换百度地图SDK默认的...
本项目"Android-仿百度地图抽屉拖拽效果"旨在实现一个类似的功能,让用户在自己的Android应用中也能添加这一特性。 抽屉效果通常通过Android的SlidingPaneLayout或者NavigationView来实现,但在这个项目中,开发者...
"高德地图定位缩放比例尺添加marker的Demo"是一个很好的示例,它展示了如何在Android应用中集成高德地图,并实现一些核心功能,如用户定位、比例尺显示、Marker的添加以及自定义Marker和缩放操作。下面我们将详细...
通过设置其属性,你可以调整地图的显示样式、比例尺、缩放级别等。然后,在对应的Activity或Fragment中初始化MapView,并使用API密钥进行认证。 为了加载天地图,你需要调用SDK提供的方法,设置地图的初始位置、...
在Android应用开发中,模拟微信发送位置功能通常涉及到集成百度地图API来实现精确的定位服务。这个过程包括了用户的位置获取、地图展示以及位置信息的分享。以下将详细阐述实现这个功能所需的关键知识点: 1. **...
在Android开发中,高德地图是一个广泛使用的地图API,提供了丰富的地图展示和定位服务。然而,在处理大量 Marker(地图上的标记点)时,如果直接在地图上显示,可能会导致地图过于拥挤,影响用户体验。为了解决这个...
二次封装的el-image-viewer组件,具有移动端双指缩放和单指拖拽功能。
在Android开发中,有时我们需要为用户提供更丰富的视频观看体验,比如允许他们自由缩放视频视图。`Android-ScalableVideoView`就是一个专为此目的设计的库,它扩展了Android原生的`VideoView`类,增加了视频的可缩放...
"Android-MapScaleView-GoogleMapsAndroidAPI的比例尺"这个项目专注于一个特定的组件——MapScaleView,它是Google Maps SDK的一个扩展,用于在地图上显示比例尺。比例尺在地图应用中至关重要,因为它提供了关于地图...
本示例“Android开发--仿景点通景区地图SurfaceView实现”聚焦于使用SurfaceView来创建一个交互式地图应用,提供了双击放大、多点触摸缩放、地图拖拽以及添加地图标记等功能。下面将详细阐述这些知识点: 1. **...
在Android开发中,百度地图API是一个非常重要的工具,它提供了丰富的功能,如定位、地图展示、路线规划等。本文将详细解析"Android 百度地图API-定位周边搜索POI源码"的相关知识点。 首先,我们需要理解POI(Point ...