现在一提到地图很多人就会想到百度地图高德地图等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 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 getMap_details() {
return map_details;
}
public void setMap_details(ArrayList 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;
}
}
原谅我无法提供源码下载,因为涉及的东西有点多,至于导航、定位功能我会在下篇博客讲。