实现比例尺功能和替换自带的缩放组件

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;
-
}
-
}
-
}
-
-
-
-
-
-
public void setMapView(MapView mapView) {
-
this.mapView = mapView;
-
-
maxZoomLevel = mapView.getMaxZoomLevel();
-
-
minZoomLevel = mapView.getMinZoomLevel();
-
}
-
-
-
-
-
-
-
-
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类的代码如下
-
<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;
-
-
-
-
-
-
-
-
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();
-
}
-
-
-
-
-
-
@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);
-
}
-
-
-
-
-
-
-
-
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);
-
}
-
-
-
-
-
-
-
@Override
-
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-
int widthSize = getWidthSize(widthMeasureSpec);
-
int heightSize = getHeightSize(heightMeasureSpec);
-
setMeasuredDimension(widthSize, heightSize);
-
}
-
-
-
-
-
-
-
private int getWidthSize(int widthMeasureSpec){
-
return MeasureSpec.getSize(widthMeasureSpec);
-
}
-
-
-
-
-
-
-
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;
-
}
-
-
-
-
-
-
-
private static int getScaleIndex(int zoomLevel) {
-
return MAX_LEVEL - zoomLevel;
-
}
-
-
-
-
-
-
-
-
public static int getScale(int zoomLevel) {
-
return SCALES[getScaleIndex(zoomLevel)];
-
}
-
-
-
-
-
-
-
public static String getScaleDesc(int zoomLevel) {
-
return SCALE_DESCS[getScaleIndex(zoomLevel)];
-
}
-
-
-
-
-
-
-
-
-
public static int meterToPixels(MapView map, int scale) {
-
-
GeoPoint geoPoint = map.getMapCenter();
-
-
double latitude = geoPoint.getLatitudeE6() / 1E6;
-
-
-
return (int) (map.getProjection().metersToEquatorPixels(scale) / (Math
-
.cos(Math.toRadians(latitude))));
-
-
-
}
-
-
-
-
-
-
public void setScaleWidth(int scaleWidth) {
-
this.scaleWidth = scaleWidth;
-
}
-
-
-
-
-
-
private void setText(String text) {
-
this.text = text;
-
}
-
-
-
-
-
-
public void setTextSize(int textSize) {
-
this.textSize = textSize;
-
invalidate();
-
}
-
-
-
-
-
-
-
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的代码如下
主界面的代码还是比较简单的,主要是利用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 百度地图开发(三)
原文:http://blog.csdn.net/littleyearyear/article/details/41307791