现在一提到地图很多人就会想到百度地图高德地图等SDK,但是公司遇到个项目要做到室内导航,现在的第三方用GPS定位又不准,所以使用了一个自定义的ImageView去实现地图的功能。该地图有导航、定位、分级显示、点击查看位置详细信息的功能。今天我们先说下基础地图数据的显示及分级显示。
先说下思路,一、地图的底图先要画好(交给UI画吧),画出各个区域,如下图(忽略那些文字吧,地图原稿找不到)没有那些文字的,只有那些有颜色的小格;
二、服务器先将每个需要画名字或者区域的的坐标标出来存起来,然后下发给APP;
三、APP加载完地图地图后(记住一定要按比例来)按照服务端拿下来的数据把名字画上去。
四、根据手指放大缩小的缩放比例分成三个级别,实现分级别显示,就像百度地图那样放大了才能显示更详细的信息。
没有缩放时显示的内容:
放大一个级别之后显示的内容:
放大到最大级别显示的内容:
接下来上代码
服务器地图区域数据的模型
public class MapInfo implements Serializable {
/**
* 地图数据模型
*/
private static final long serialVersionUID = 4667341137172521648L;
private String map_id; //地图ID
private String map_WH; //地图的宽高
private String map_route; //定位线段
private String map_img; //地图底图的地址
private String show_exit; //出入口
private ArrayList<MapDetail> map_details; //地图区域数据
@Override
public String toString() {
return "MapInfo [map_id=" + map_id + ", map_WH=" + map_WH
+ ", map_route=" + map_route + ", map_img=" + map_img
+ ", map_details=" + map_details + "]";
}
public String getShow_exit() {
return show_exit;
}
public void setShow_exit(String show_exit) {
this.show_exit = show_exit;
}
public static long getSerialversionuid() {
return serialVersionUID;
}
public String getMap_id() {
return map_id;
}
public void setMap_id(String map_id) {
this.map_id = map_id;
}
public String getMap_WH() {
return map_WH;
}
public void setMap_WH(String map_WH) {
this.map_WH = map_WH;
}
public String getMap_route() {
return map_route;
}
public void setMap_route(String map_route) {
this.map_route = map_route;
}
public String getMap_img() {
return map_img;
}
public void setMap_img(String map_img) {
this.map_img = map_img;
}
public ArrayList<MapDetail> getMap_details() {
return map_details;
}
public void setMap_details(ArrayList<MapDetail> map_details) {
this.map_details = map_details;
}
public class MapDetail implements Serializable {
/**
*
*/
private static final long serialVersionUID = -7211436420618576335L;
private String D_id; //区域ID
private String D_location; //区域坐标
private String D_status; //区域的状态
private String map_id; //地图的ID
private String point_type; //坐标的类型
private String point_xy; //定位的坐标
private String show_id; //展会的ID
private String user_id; //用户ID
private String user_nicename; //用户名
private String gradeid; //等级
public String getGradeid() {
return gradeid;
}
public void setGradeid(String gradeid) {
this.gradeid = gradeid;
}
public String getD_id() {
return D_id;
}
public void setD_id(String d_id) {
D_id = d_id;
}
public String getD_location() {
return D_location;
}
public void setD_location(String d_location) {
D_location = d_location;
}
public String getD_status() {
return D_status;
}
public void setD_status(String d_status) {
D_status = d_status;
}
public String getMap_id() {
return map_id;
}
public void setMap_id(String map_id) {
this.map_id = map_id;
}
public String getPoint_type() {
return point_type;
}
public void setPoint_type(String point_type) {
this.point_type = point_type;
}
public String getPoint_xy() {
return point_xy;
}
public void setPoint_xy(String point_xy) {
this.point_xy = point_xy;
}
public String getShow_id() {
return show_id;
}
public void setShow_id(String show_id) {
this.show_id = show_id;
}
public String getUser_id() {
return user_id;
}
public void setUser_id(String user_id) {
this.user_id = user_id;
}
public String getUser_nicename() {
return user_nicename;
}
public void setUser_nicename(String user_nicename) {
this.user_nicename = user_nicename;
}
@Override
public String toString() {
return "MapDetail [D_id=" + D_id + ", D_location=" + D_location
+ ", D_status=" + D_status + ", map_id=" + map_id
+ ", point_type=" + point_type + ", point_xy=" + point_xy
+ ", show_id=" + show_id + ", user_id=" + user_id
+ ", user_nicename=" + user_nicename + ",gradeid="+gradeid+"]";
}
}
}
地图加载完成后开始画区域名(我使用的是ImageLoader刚好有监听方法)
//加载地图
private void loadMapImage() {
ImageLoader.getInstance().displayImage(
ApiClient.BASE_IMAGE + mapInfo.getMap_img(), mIndoorMapView,
appContext.getOptions(), new ImageLoadingListener() {
@Override
public void onLoadingStarted(String arg0, View arg1) {
}
@Override
public void onLoadingFailed(String arg0, View arg1,
FailReason arg2) {
}
@Override
public void onLoadingComplete(String arg0, View arg1,
Bitmap arg2) {
mIndoorMapView.setMapInfo(mapInfo);
//System.out.println(mapInfo);
int oriImageWidth = 0;
int oriImageHeight = 0;
try {
oriImageWidth = Integer.parseInt(mapInfo
.getMap_WH().split(",")[0]);
oriImageHeight = Integer.parseInt(mapInfo
.getMap_WH().split(",")[1]);
} catch (NumberFormatException e) {
e.printStackTrace();
}
int width = arg2.getWidth();
int height = arg2.getHeight();
Log.d(TAG, "" + width + "---" + height);
Bitmap tempBitmap = arg2;
if (width < (oriImageWidth / 2)) {
tempBitmap = BitmapManager.zoomBitmap(arg2,
oriImageWidth / 2, oriImageHeight / 2);
}
mIndoorMapView.setImageBitmap(tempBitmap);
if(mIndoorMapView.getFirstbgbitmap()==null){
mIndoorMapView.setFirstbgbitmap(((BitmapDrawable) mIndoorMapView.getDrawable()).getBitmap());
}
// The MAGIC happens here!
mAttacher = new PhotoViewAttacher(mIndoorMapView);
//存储最开始的图片比例
if(firstZoom>=8){
RectF rect=mAttacher.getDisplayRect();
firstZoom=(float) Math.sqrt(((rect.height()*rect.height())+(rect.width()*rect.width())));
}
mIndoorMapView.drawMerchant();
if(StringUtils.isEmpty(startPoint)){
mIndoorMapView.setStartPointLoc(StringUtils.pointFromString(startPoint));
startPoint=null;
}
mIndoorMapView.drawPointAndNavLine();
//监听地图的点击 点击展位区域,跳转到展会的详情页面
//mAttacher.setOnPhotoTapListener(mapOnPhotoTapListener);
setZoomChang();
}
@Override
public void onLoadingCancelled(String arg0, View arg1) {
}
});
}
加载完成后画出区域名字的方法
public synchronized void drawMerchant() {
/**
* 加载地图后的初始化工作
*/
endBitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.indoormap_end);
startBitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.indoormap_start);
astar = new AStar();
backBitmap = createMerchantInfoMapBitmap();
}
//画展位名称
public Bitmap createMerchantInfoMapBitmap() {
Bitmap myBitmap =firstbgbitmap;
Bitmap bmpTemp = Bitmap.createBitmap(myBitmap.getWidth(),
myBitmap.getHeight(), Bitmap.Config.RGB_565);
Canvas canvas = new Canvas(bmpTemp);
Paint p = new Paint();
p.setColor(Color.rgb(105, 126, 151));
p.setTextAlign(Paint.Align.CENTER);
p.setAntiAlias(true);
// 让画出的图形是空心的
p.setStyle(Paint.Style.FILL);
// 设置画出的线的 粗细程度
p.setStrokeWidth(3);
String familyName = "宋体";
Typeface font = Typeface.create(familyName, Typeface.BOLD);
p.setTypeface(font);
canvas.drawBitmap(myBitmap, 0, 0, p);
if (mapInfo != null && mapInfo.getMap_details() != null) {
for (int i = 0; i < mapInfo.getMap_details().size(); i++) {
MapInfo.MapDetail mapDetail = mapInfo.getMap_details().get(i);
if (StringUtils.isEmpty(mapDetail.getPoint_xy())) {
continue;
}
String[] xyArray = mapDetail.getPoint_xy().split(",");
if (xyArray.length == 8) {
// 设置字体大小
if ((Integer.parseInt(xyArray[2]) / 2 - Integer
.parseInt(xyArray[0]) / 2) > 40) {
p.setTextSize(20);
} else {
p.setTextSize(14);
}
float x = Integer.parseInt(xyArray[0])
/ 2
+ (Integer.parseInt(xyArray[2]) / 2 - Integer
.parseInt(xyArray[0]) / 2) / 2;
float y = Integer.parseInt(xyArray[1])
/ 2
+ (Integer.parseInt(xyArray[5]) / 2 - Integer
.parseInt(xyArray[1]) / 2) / 2;
x += 6;
y += 12;
if (((Integer.parseInt(xyArray[2]) / 2 - Integer
.parseInt(xyArray[0]) / 2)) < ((Integer
.parseInt(xyArray[5]) / 2 - Integer
.parseInt(xyArray[1]) / 2))
&& !StringUtils.isEmpty(mapDetail
.getUser_nicename())
&& mapDetail.getUser_nicename().length() > 3) {
//根据显示等级显示展位名称
//System.out.println("当前显示等级"+AppConfig.getAppConfig(context).getShowName_Type());
if(Integer.parseInt(mapDetail.getGradeid())>=AppConfig.getAppConfig(context).getShowName_Type()){
canvas.rotate(-90, x, y);
canvas.drawText(mapDetail.getUser_nicename(), x, y, p);
canvas.rotate(90, x, y);
}
} else {
//根据显示等级显示展位名称
if(Integer.parseInt(mapDetail.getGradeid())>=AppConfig.getAppConfig(context).getShowName_Type()){
canvas.rotate(0, x, y);
if (!StringUtils.isEmpty(mapDetail.getUser_nicename())) {
canvas.drawText(mapDetail.getUser_nicename(), x, y,
p);
}
}
}
}
}
}
canvas.save(Canvas.ALL_SAVE_FLAG);
canvas.restore();
//如果有导航就重画
if(startPointLoc!=null&&endPoint!=null){
backBitmap=bmpTemp;
this.setImageDrawable(new BitmapDrawable(getResources(), bmpTemp));
return drawPointAndNavLine();
}else{
this.setImageDrawable(new BitmapDrawable(getResources(), bmpTemp));
return bmpTemp;
}
}
以上我那么就实现了地图基础数据的显示以及根据不同的缩放比例显示不同的区域名,差不多相当于最原始的百度地图,思路是不是超级简单呢?
原谅我无法提供源码下载,因为涉及的东西有点多,至于导航、定位功能我会在下篇博客讲。