我从业以来,很长有很多时间都在研究gis。不过是开源的还是收费的,多少多会看。现在又看了国内收费的ucmap for android ,说说我的感受吧。目前来说这是我用过接口最奇怪的,怎么说呢。就是跟一般习惯是不一样的。刚开始你会很纳闷,后面我会解释一下。我先声明,只代表个人观点,只是使用者观点。

1,官网

直接百度搜索ucmap即可,打开他们公司官网。下载开发包。

UCMap(V6.6.0)Android.7z:下载开发包,然后是他们公司的官网的论坛,有帖子申请实用码,说是3个月。说起试用码,我就要吐槽了。这个试用码是指定机器的,麻烦。这个码还有问题,我用了不到3个月。demo弹出来的码居然变了,跟我之前申请用的居然不一样了。因为我也做过一些注册码机制类似。这种形式最不好用。说到这里,因为我手机的机器码变了,现在没有码,这篇博客就不贴相关地图的界面,因为会崩溃,也没什么用。

UCMap(V7.0.0)Android.7z:最新版本android的开发包sdk 7.0已经不用试用码(之前的版本都需要)。现在做成跟arcgis 一样,有水印和法律声明。自已下载开发包,里面pdf以及demo,还有接口中文说明都有。这点是比较好的。

这里我就要说一下国内的另外一家超图公司的,那个试用码是3个月,不指定机器。而且是发送到申请邮箱。就是方便。

还有一家arcgis for android。国外的最大型的,开发gis都知道。这个更好,不用码,只不过有水印,还有版权声明。这个形式也挺好的。这个我只是总结现象。

至于开发包就大家自已去下载吧。

2,加载地图

这是一个官方提供的加载地图的形式。我贴一下主要代码:

        mapView = (MapView) findViewById(R.id.mapView);mapView.setListener(new IMapViewListener() {@Overridepublic void onSizeChanged(int w, int h, int oldw, int oldh) {MapControl mapControl = mapView.getMapControl();mapControl.showScaleBar(8, getResources().getDisplayMetrics().xdpi / 2.54f, 10, mapControl.getHeight() - 10, Color.BLACK, Color.RED, 3, 20);if (mapControl.getMap() == null) {String path = Environment.getExternalStorageDirectory().getPath();if (!new File(path + "/" + workspace + "/map.ini").exists())//这里检查是否具有这个地图,没有则新建App.getInstance().createMap(path + "/" + workspace);mapControl.loadMap(path + "/" + workspace + "/map.ini", (byte) 0);//装载地图mapControl.setPanTool();}}});

这是一个离线地图,看以看出这个是加载根目录下面的bj2文件夹下面的map.ini。如果你测试出现崩溃或者没有地图,那么你自已留意吧。

这个数据是shp数据转换出来的数据库。我们看加载文件就知道。map.ini其实是个配置文件,用记事本打开就知道。有点长,下面我就展示部分。

[Map]
labelColor=0,0,0
LabelStyleCount=0
XMin=116.275146484375
YMin=39.864261627197266
XMax=116.45286494082686
YMax=39.97161865234375
LayerCount=23
[FixedShapefileLayer]0  省界_region  5
MinScale=0.0
MaxScale=0.0
Valid=1
Visible=1
Name=省界_region
Selectable=1
ScaleSymbols=0
[SimpleRenderer]
[FillSymbol]
FillColor_255=153,153,0
OutlineWidth=0.0
OutlineColor_255=153,153,0
然后我们可以在这里找到map.dat 。官方开发包里面都有,不要问我哪里来的数据。bj2文件下面。

用一个可视化sqlite工具打开

这里可以看出每一条数据,都是有一个范围xmin,ymin,xmax,ymax。然后是data,这个就是一系列坐标在里面。大家都知道一个线,面都是由很多坐标组成,那么都在里面了。然后外面是个范围。

研究这个呢?一定要对shp数据文件结构比较了解。这个shp里面东西。相当于把shp数据转换成这个表。

还有还有dbf属性文件转换成一张表的。其实在里面都能找到。

2,加载shp

说起加载shp,应该都是gis当中必备基础功能。上面都看到我解释那个map.ini和map.dat 其实就是shp文件转换出来,有桌面端工具转,也可以用java代码直接转。生成那两个东西。

        mapView = (MapView) findViewById(R.id.mapView);mapView.setListener(new IMapViewListener() {@Overridepublic void onSizeChanged(int w, int h, int oldw, int oldh) {MapControl mapControl = mapView.getMapControl();mapControl.showScaleBar(8, getResources().getDisplayMetrics().xdpi / 2.54f, 10, mapControl.getHeight() - 10, Color.BLACK, Color.RED, 3, 20);if (mapControl.getMap() == null) {String path = Environment.getExternalStorageDirectory().getPath();if (!new File(path + "/shape/map.ini").exists())App.getInstance().createMap(path + "/shape");mapControl.loadMap(path + "/shape/map.ini", (byte) 0);String pathname = path + "/shape/DLTB.shp";ShapefileLayer slayer = ShapefileLayer.createFromSHP((short) mapControl.getMap().getLayerCount(),pathname, 100000, 0, true, true, new SimpleRenderer("", "", new FillSymbol(0xFF00FF00, null)), "GBK");if (slayer != null) {mapControl.getMap().addLayer(slayer);mapControl.getDisplay().getDisplayTransformation().setVisibleBounds(mapControl.getFullExtent());mapControl.rewriteIni();mapControl.refresh();}//经测试,这个没有调用是很卡顿的//将当前的地图工具设置为移动地图工具mapControl.setPanTool();}}});

第一次加载和转一定会卡在哪里,要做进度条的。因为那都是耗时。在动一下程序就无响应了。

其实有耐心的人,都看到了这个两个类基本上是一样的。第一个是直接加载转换好的shp,一个是在android端写代码加载。

那为什么分两个类,都是继承mapview这个类呢。这就是难用地方之一。所有加载地图都是这样写的

        mapView.setListener(new IMapViewListener() {@Overridepublic void onSizeChanged(int w, int h, int oldw, int oldh) {MapControl mapControl = mapView.getMapControl();mapControl.showScaleBar(8, getResources().getDisplayMetrics().xdpi / 2.54f, 10, mapControl.getHeight() - 10, Color.BLACK, Color.RED, 3, 20);if (mapControl.getMap() == null) {mapControl.setPanTool();}}});

这个mapcontrol也是很重要的。自已体会吧。

3,加载谷歌在线地图

这个是demo 1里面功能。

public class MyMapView extends MapView {GPSCustomDraw gpsCustomDraw;public MyMapView(Context context, AttributeSet attrs) {super(context, attrs);}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);if (this.isInEditMode()) return;MapControl mapControl=getMapControl();gpsCustomDraw = new GPSCustomDraw(mapControl);//以下代码会在地图窗口的左下角显示一个比例尺符号,具体参数说明请参考doc//getResources().getDisplayMetrics().xdpi 获取了屏幕的横向dpi,乘以2.54可以得到1厘米有多少个像素点mapControl.showScaleBar(8, getResources().getDisplayMetrics().xdpi/2.54f, 10, mapControl.getHeight()-10, Color.BLACK,Color.RED,3,20);if (mapControl.getMap()==null){String path=Environment.getExternalStorageDirectory().getPath();MapLoader.loadMapXML(mapControl, path+"/OpenSourceMap.xml");//MapLoader.loadMapXML(mapControl,Environment.getExternalStorageDirectory().getPath()+"/cache/OpenSourceMapWithLocal.xml",null,1,0.00001f,true);mapControl.setCustomDraw(gpsCustomDraw);mapControl.setPanTool();((OpenSourceMapLayer)mapControl.getMap().getLayer(0)).openZoomInMode();mapControl.refresh();}}public void close() {if(gpsCustomDraw != null){gpsCustomDraw.close();}}
}

activity调用如下:

package cn.creable.android.demo.activity;import java.util.Vector;import cn.creable.android.demo.CopyFileManage;
import cn.creable.android.demo.R;
import cn.creable.android.demo.online.GPSCustomDraw;
import cn.creable.android.demo.online.MyMapView;
import cn.creable.android.demo.online.PathTool;
import cn.creable.android.demo.online.PointTool;
import cn.creable.gridgis.controls.App;
import cn.creable.gridgis.controls.CustomDrawGeometrySelector;
import cn.creable.gridgis.controls.ICustomDraw;
import cn.creable.gridgis.controls.ICustomDrawDataCenter;
import cn.creable.gridgis.controls.MapView;
import cn.creable.gridgis.geometry.IEnvelope;
import cn.creable.gridgis.geometry.IPoint;
import cn.creable.gridgis.geometry.Point;
import cn.creable.ucmap.ILocalSearchListener;
import cn.creable.ucmap.IPathSearchListener;
import cn.creable.ucmap.MapLoader;
import cn.creable.ucmap.OpenSourceMapLayer;
import cn.creable.ucmap.OpenSourceMapLayer.Path;import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;public class MapMainActivity extends Activity {MyMapView mapView;ProgressDialog dlg;Activity act;PathTool pathTool;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);String path = Environment.getExternalStorageDirectory().getPath();CopyFileManage.copyAssetsFiletoDirectory(getAssets(), "xml", path);setContentView(R.layout.map_main);pathTool = null;act = this;mapView = (MyMapView) findViewById(R.id.mapView);}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {menu.add(Menu.NONE, Menu.NONE, 0, "装入地图");menu.add(Menu.NONE, Menu.NONE, 1, "放大地图");menu.add(Menu.NONE, Menu.NONE, 2, "缩小地图");menu.add(Menu.NONE, Menu.NONE, 3, "平移地图");menu.add(Menu.NONE, Menu.NONE, 12, "点击查询坐标");menu.add(Menu.NONE, Menu.NONE, 10, "用代码控制视图");menu.add(Menu.NONE, Menu.NONE, 11, "查看gps点");menu.add(Menu.NONE, Menu.NONE, 4, "关键字查询");menu.add(Menu.NONE, Menu.NONE, 5, "路径查询");menu.add(Menu.NONE, Menu.NONE, 6, "切换地图数据源");menu.add(Menu.NONE, Menu.NONE, 7, "切换地图模式");menu.add(Menu.NONE, Menu.NONE, 8, "退出");return true;}@Overridepublic boolean onOptionsItemSelected(MenuItem item) {switch (item.getItemId()) {case 0:    //装入地图MapLoader.loadMapXML(mapView.getMapControl(), "/sdcard/OpenSourceMap.xml");mapView.getMapControl().setCustomDraw(new GPSCustomDraw(mapView.getMapControl()));mapView.getMapControl().setPanTool();break;case 1:    //放大地图mapView.getMapControl().setZoomInTool();break;case 2:    //缩小地图mapView.getMapControl().setZoomOutTool();break;case 3:    //平移地图mapView.getMapControl().setPanTool();break;case 10://用代码视图控制{mapView.getMapControl().getDisplay().getDisplayTransformation().setZoom(10);//直接设置显示比例尺,实现放大到想要的比例,如果仅仅需要居中,可以注释掉这一行//以下代码实现以(117,30)为中心居中OpenSourceMapLayer oslayer = (OpenSourceMapLayer) mapView.getMapControl().getMap().getLayer(0);Point pt = oslayer.fromLonLat(117, 30);Point offset = oslayer.getOffset(117, 30);pt.setX(pt.getX() + offset.getX());pt.setY(pt.getY() + offset.getY());IEnvelope env = mapView.getMapControl().getExtent();//TODO:注意,如果你需要移动中心点时并setZoom,getExtent必须在setZoom之后调用才行env.centerAt(pt);mapView.getMapControl().refresh(env);break;}case 4:    //关键字查询if (mapView.getMapControl().getMap().getLayerCount() > 0) {OpenSourceMapLayer oslayer = (OpenSourceMapLayer) mapView.getMapControl().getMap().getLayer(0);oslayer.setLocalSearchListener(new ILocalSearchListener() {@Overridepublic void localSearchFinished(Vector pois) {if (pois == null) return;int size = pois.size();StringBuilder sb = new StringBuilder();for (int i = 0; i < size; ++i) {OpenSourceMapLayer.POI poi = (OpenSourceMapLayer.POI) pois.get(i);sb.append(poi.title);sb.append("\n");}sb.deleteCharAt(sb.length() - 1);//利用Toast显示查询到的信息点的名字Bundle b = new Bundle();b.putString("string", sb.toString());Message msg = new Message();msg.what = 1;msg.setData(b);handler.sendMessage(msg);sb = null;}});oslayer.localSearch("南京,中山", 0);//显示等待界面dlg = new ProgressDialog(act);dlg.setProgressStyle(ProgressDialog.STYLE_SPINNER);dlg.setTitle("提示");dlg.setMessage("正在进行关键字查询,请稍后");dlg.setIcon(R.drawable.icon);dlg.setIndeterminate(false);dlg.setCancelable(true);dlg.setButton("取消 ", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {OpenSourceMapLayer oslayer = (OpenSourceMapLayer) mapView.getMapControl().getMap().getLayer(0);oslayer.cancel();}});dlg.show();}break;case 5:    //路径查询if (mapView.getMapControl().getMap().getLayerCount() > 0) {OpenSourceMapLayer oslayer = (OpenSourceMapLayer) mapView.getMapControl().getMap().getLayer(0);if (pathTool == null) {pathTool = new PathTool(mapView.getMapControl(), oslayer, act);mapView.getMapControl().addCustomDraw(pathTool);}mapView.getMapControl().setCurrentTool(pathTool);mapView.getMapControl().refresh();}break;case 6:    //切换地图数据源if (mapView.getMapControl().getMap().getLayerCount() > 0) {OpenSourceMapLayer oslayer = (OpenSourceMapLayer) mapView.getMapControl().getMap().getLayer(0);switch (oslayer.getMapMode()) {case GOOGLE:oslayer.setMapMode(1);break;case BING:oslayer.setMapMode(0);break;}mapView.getMapControl().refresh();}break;case 7:    //切换地图模式if (mapView.getMapControl().getMap().getLayerCount() > 0) {OpenSourceMapLayer oslayer = (OpenSourceMapLayer) mapView.getMapControl().getMap().getLayer(0);switch (oslayer.getMode()) {case 0:oslayer.setMode(1);break;case 1:oslayer.setMode(0);break;}mapView.getMapControl().refresh();}break;case 8:    //退出System.exit(0);break;case 11:ICustomDraw draw = mapView.getMapControl().getCustomDraw();if (draw != null && draw instanceof ICustomDrawDataCenter) {CustomDrawGeometrySelector s = new CustomDrawGeometrySelector(mapView.getMapControl(), (ICustomDrawDataCenter) draw);s.setOffset(0, 60);mapView.getMapControl().setCurrentTool(s);}break;case 12:mapView.getMapControl().setCurrentTool(new PointTool(mapView.getMapControl()));break;}return super.onOptionsItemSelected(item);}private Handler handler = new Handler() {public void handleMessage(Message msg) {switch (msg.what) {case 1://关闭等待界面dlg.cancel();dlg = null;//利用Toast显示查询的结果Toast.makeText(App.getInstance(), msg.getData().getString("string"), Toast.LENGTH_SHORT).show();break;}}};@Overrideprotected void onDestroy(){if(mapView != null && mapView.getMapControl() != null){mapView.getMapControl().closeMap();mapView.close();}super.onDestroy();}
}

自已看怎样放配置文件吧:就是谷歌地址解析的文件。

官方demo 有所说明,怎么放在sd卡存储目录。

还有加载天地图,demo里面没有,暂时不知道怎么实现。

4,demo4 功能

这里面功能主要是对shp转换出来的sql进行编辑了。我写很多注释。

        menuGrid.setOnItemClickListener(new AdapterView.OnItemClickListener(){@Overridepublic void onItemClick(AdapterView<?> adapter, View view, int cmd,long arg3) {menuDialog.dismiss();switch (cmd) {case 0://添加要素{AlertDialog.Builder builder = new AlertDialog.Builder(act);builder.setTitle("请选择图层:");layers.clear();Vector<String> strs = new Vector<String>();//查找当前所有的图层int count = mapView.getMapControl().getMap().getLayerCount();for (int i = 0; i < count; ++i) {ILayer layer = mapView.getMapControl().getMap().getLayer(i);if (layer instanceof ShapefileLayer) {strs.addElement(layer.getName());layers.addElement((ShapefileLayer) layer);}}String[] layerNames = new String[strs.size()];strs.copyInto(layerNames);strs = null;//弹出图层选择的列表对话框builder.setSingleChoiceItems(layerNames, -1, new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {dialog.cancel();//添加要素工具,可以利用该地图工具实现添加点、线、面要素的功能AddFeatureTool tool = new AddFeatureTool(mapView.getMapControl(), layers.elementAt(which));editTool = tool;//设置偏移量,将用户输入的光标从手指下面移动到其他的地方,这样避免光标被用户手指挡住的问题//就是捕捉上面一个按钮tool.setOffset(0, 60);//开启捕捉功能tool.openSnap();//设置编辑监听器 IEditListener 的监听回调editTool.setListener(act);//设置当前地图工具mapView.getMapControl().setCurrentTool(tool);}});AlertDialog dialog = builder.create();dialog.show();break;}case 1: //添加要素 打点{AlertDialog.Builder builder = new AlertDialog.Builder(act);builder.setTitle("请选择图层:");layers.clear();Vector<String> strs = new Vector<String>();//查找当前所有的图层int count = mapView.getMapControl().getMap().getLayerCount();for (int i = 0; i < count; ++i) {ILayer layer = mapView.getMapControl().getMap().getLayer(i);if (layer instanceof ShapefileLayer) {strs.addElement(layer.getName());layers.addElement((ShapefileLayer) layer);}}String[] layerNames = new String[strs.size()];strs.copyInto(layerNames);strs = null;//弹出图层选择的列表对话框builder.setSingleChoiceItems(layerNames, -1, new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {dialog.cancel();//添加要素工具,可以利用该地图工具实现添加点、线、面要素的功能AddFeatureTool2 tool = new AddFeatureTool2(mapView.getMapControl(), layers.elementAt(which), ((BitmapDrawable) App.getInstance().getResources().getDrawable(R.drawable.cross)).getBitmap());editTool = tool;//设置编辑监听器 IEditListener 的监听回调editTool.setListener(act);//设置当前地图工具mapView.getMapControl().setCurrentTool(tool);//重画,将缓冲在内存中的地图再次绘制到屏幕上mapView.getMapControl().repaint();}});AlertDialog dialog = builder.create();dialog.show();break;}case 2: //删除要素{//删除要素工具,利用本工具可以删除矢量地图上的任何要素DeleteFeatureTool tool = new DeleteFeatureTool(mapView.getMapControl());//设置偏移量,将用户输入的光标从手指下面移动到其他的地方,这样避免光标被用户手指挡住的问题//就是捕捉上面一个按钮tool.selector.setOffset(0, 80);editTool = tool;//设置编辑监听器 IEditListener 的监听回调editTool.setListener(act);//设置当前地图工具mapView.getMapControl().setCurrentTool(tool);break;}case 3: //提交编辑{editTool.submit();break;}case 4: //修改节点{//编辑要素工具,使用本工具可以实现对点、线、面地图要素的编辑EditFeatureTool editTool = null;if (mapView.getMapControl().getCurrentTool() != null && mapView.getMapControl().getCurrentTool() instanceof EditFeatureTool) {//获取地图当前的地图工具editTool = (EditFeatureTool) mapView.getMapControl().getCurrentTool();} else {editTool = new EditFeatureTool(mapView.getMapControl());//设置一个编辑要素工具mapView.getMapControl().setCurrentTool(editTool);}//设置偏移量,设置放大镜的偏移量editTool.selector.setOffset(0, 80);//设置编辑类型 Type_MoveNode移动节点editTool.setType(EditFeatureTool.Type_MoveNode);//IEditListener 的监听回调editTool.setListener(act);break;}case 5: //添加节点{//编辑要素工具,使用本工具可以实现对点、线、面地图要素的编辑EditFeatureTool editTool = null;if (mapView.getMapControl().getCurrentTool() != null && mapView.getMapControl().getCurrentTool() instanceof EditFeatureTool) {//获取地图当前的地图工具editTool = (EditFeatureTool) mapView.getMapControl().getCurrentTool();} else {editTool = new EditFeatureTool(mapView.getMapControl());//设置一个编辑要素工具mapView.getMapControl().setCurrentTool(editTool);}//设置偏移量,设置放大镜的偏移量editTool.selector.setOffset(0, 80);//设置编辑类型 Type_AddNode 添加节点editTool.setType(EditFeatureTool.Type_AddNode);break;}case 6: //删除节点{//编辑要素工具,使用本工具可以实现对点、线、面地图要素的编辑EditFeatureTool editTool = null;if (mapView.getMapControl().getCurrentTool() != null && mapView.getMapControl().getCurrentTool() instanceof EditFeatureTool) {//获取地图当前的地图工具editTool = (EditFeatureTool) mapView.getMapControl().getCurrentTool();} else {editTool = new EditFeatureTool(mapView.getMapControl());//设置一个编辑要素工具mapView.getMapControl().setCurrentTool(editTool);}//设置偏移量,设置放大镜的偏移量editTool.selector.setOffset(0, 80);//设置编辑类型 Type_DeleteNode 删除节点editTool.setType(EditFeatureTool.Type_DeleteNode);break;}case 7: //整体移动{//将前三个层设置为不可选择int layerCount = mapView.getMapControl().getMap().getLayerCount();if (layerCount > 3) layerCount = 3;for (int i = 0; i < layerCount; ++i) {ShapefileLayer layer = null;if (mapView.getMapControl().getMap().getLayer(i) instanceof ShapefileLayer)layer = (ShapefileLayer) mapView.getMapControl().getMap().getLayer(i);if (layer != null) {//设置是否可以选择  false不可选择layer.setSelectable(false);}}//编辑要素工具,使用本工具可以实现对点、线、面地图要素的编辑EditFeatureTool tool = new EditFeatureTool(mapView.getMapControl());//设置编辑类型 Type_Move 整体移动tool.setType(EditFeatureTool.Type_Move);//设置当前地图工具mapView.getMapControl().setCurrentTool(tool);break;}case 8: //undo{boolean ret = false;if (mapView.getMapControl().getCurrentTool() != null && mapView.getMapControl().getCurrentTool() instanceof IEditTool)ret = ((IEditTool) (mapView.getMapControl().getCurrentTool())).undo();if (ret == false) {ShapefileLayer.undo();mapView.getMapControl().refresh();}break;}case 9: //redo{boolean ret = false;if (mapView.getMapControl().getCurrentTool() != null && mapView.getMapControl().getCurrentTool() instanceof IEditTool)ret = ((IEditTool) (mapView.getMapControl().getCurrentTool())).redo();if (ret == false) {ShapefileLayer.redo();mapView.getMapControl().refresh();}break;}case 10://修改属性{//编辑属性,只是闪烁EditFeatureAttTool tool = new EditFeatureAttTool(mapView.getMapControl());tool.selector.setOffset(0, 80);editTool = tool;editTool.setListener(act);mapView.getMapControl().setCurrentTool(tool);break;}case 11://地图浏览//将当前的地图工具设置为移动地图工具mapView.getMapControl().setPanTool();break;case 12: //导出地图{AlertDialog.Builder builder = new AlertDialog.Builder(act);builder.setTitle("请选择图层:");layers.clear();Vector<String> strs = new Vector<String>();int count = mapView.getMapControl().getMap().getLayerCount();for (int i = 0; i < count; ++i) {ILayer layer = mapView.getMapControl().getMap().getLayer(i);if (layer instanceof ShapefileLayer) {strs.addElement(layer.getName());layers.addElement((ShapefileLayer) layer);}}String[] layerNames = new String[strs.size()];strs.copyInto(layerNames);strs = null;//对话框对那个图层列表进行选择导出builder.setSingleChoiceItems(layerNames, -1, new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {dialog.cancel();//导出到根目录layers.elementAt(which).outputToShapefile("/sdcard/");Toast.makeText(act, "导出完成!", Toast.LENGTH_LONG).show();}});AlertDialog dialog = builder.create();dialog.show();break;}case 13://开启捕捉if (editTool instanceof AddFeatureTool) {((AddFeatureTool) editTool).openSnap();} else if (mapView.getMapControl().getCurrentTool() != null && mapView.getMapControl().getCurrentTool() instanceof EditFeatureTool) {((EditFeatureTool) mapView.getMapControl().getCurrentTool()).openSnap();}break;case 14://关闭捕捉if (editTool instanceof AddFeatureTool) {((AddFeatureTool) editTool).closeSnap();} else if (mapView.getMapControl().getCurrentTool() != null && mapView.getMapControl().getCurrentTool() instanceof EditFeatureTool) {((EditFeatureTool) mapView.getMapControl().getCurrentTool()).closeSnap();}break;case 15://信息工具//信息工具,用于显示地图要素的详细属性信息//如果是shp文件,那就是dbf属性信息InfoTool tool = new InfoTool(mapView.getMapControl(), new IInfoToolListener() {@Overridepublic void notify(MapControl mapControl, IFeatureLayer flayer,IFeature ft, String[] fields, String[] values) {if (ft.getShape().getGeometryType() == GeometryType.Polygon) {//以下代码实现  仅仅闪烁面要素边框的效果Polygon pg = (Polygon) ft.getShape();LinearRing ring = (LinearRing) pg.getExteriorRing();LineString line = new LineString(ring.getPoints());//根据面的边框构造一个线LineSymbol ls = new LineSymbol(3, 0xFFFF0000);//构造一个线样式Vector<IGeometry> geos = new Vector<IGeometry>();geos.add(line);Vector<ISymbol> syms = new Vector<ISymbol>();syms.add(ls);mapControl.flashFeatures(geos, syms, 10);//调用闪烁接口,并只闪烁10次,如果需要无限制的闪烁,请将10改成-1} elsemapControl.flashFeatures(flayer, ft.getOid());//闪烁被选中的地图要素//显示地图要素的属性StringBuilder sb = new StringBuilder();for (int i = 0; i < fields.length; ++i) {sb.append(fields[i]);sb.append(":");sb.append(values[i]);sb.append("\n");}sb.deleteCharAt(sb.length() - 1);//利用Toast显示地图要素的属性if (myt != null) {myt.cancel();myt = null;}myt = new MyToast(App.getInstance().getApplicationContext());myt.setText(sb.toString());myt.show();//Toast.makeText(App.getInstance(), sb.toString(), Toast.LENGTH_SHORT).show();sb = null;}});tool.selector.setOffset(0, 80);mapView.getMapControl().setCurrentTool(tool);break;case 16://投影变换//这个被注释掉的是大地2000投影的定义//String CGCS2000_3_Degree_GK_Zone_40="+proj=tmerc +lat_0=0 +lon_0=120 +k=1 +x_0=40500000 +y_0=0 +ellps=GRS80 +units=m +no_defs";String proj1 = ProjectFactory.createWGS84();String proj2 = ProjectFactory.createGaussKruger(114, 0, ProjectFactory.ellps_xian1980, 500000, "m");SpatialReference sr = new SpatialReference(proj1, proj2);sr.addPoint(new Point(113.82133, 23.27463));sr.addPoint(new Point(113.82233, 23.27563));sr.addPoint(new Point(113.82333, 23.27663));sr.addPoint(new Point(113.82433, 23.27763));double[] result = sr.pj1Topj2();String msg = String.format("经纬度点(113.82133,23.27463)转换到3度带高斯80坐标系之后的坐标为(%f,%f)", result[0], result[1]);Toast.makeText(App.getInstance(), msg, Toast.LENGTH_LONG).show();break;case 17://测距离MeasureTool mtool = new MeasureTool(mapView.getMapControl(), 0);mtool.setListener(new IMeasureToolListener() {@Overridepublic void notify(int type, double value) {Toast.makeText(App.getInstance(), String.format("距离为:%f米", value), Toast.LENGTH_LONG).show();}});mtool.selector.setOffset(0, 80);mapView.getMapControl().setCurrentTool(mtool);break;case 18://测面积MeasureTool mtool1 = new MeasureTool(mapView.getMapControl(), 1);mtool1.setListener(new IMeasureToolListener() {@Overridepublic void notify(int type, double value) {Toast.makeText(App.getInstance(), String.format("面积为:%f平方米", value), Toast.LENGTH_LONG).show();}});mtool1.selector.setOffset(0, 80);mapView.getMapControl().setCurrentTool(mtool1);break;case 19: //专题图{//缩放到能够看到专题图效果的比例尺mapView.getMapControl().getDisplay().getDisplayTransformation().setZoom(0.00805f);//将第三个图层“县界”的renderer替换为MyRendererIShapefileLayer layer = (IShapefileLayer) mapView.getMapControl().getMap().getLayer(2);MyRenderer renderer = new MyRenderer(layer);IFeatureLayer flayer = (IFeatureLayer) layer;flayer.setRenderer(renderer);mapView.getMapControl().refresh();//刷新地图break;}case 20://图层控制//其实就是图层的筛选而已//遍历当前地图的所有图层int cur = -1;IMap map = mapView.getMapControl().getMap();int size = map.getLayerCount();layers2.clear();//float curZoom=mapView.getMapControl().getDisplay().getDisplayTransformation().getZoom();ILayer layer = null;for (int i = 0; i < size; ++i) {layer = map.getLayer(i);//if (layer.getMinimumScale()<curZoom && curZoom<layer.getMaximumScale())//只有图层的显示比例范围包含了当前显示比例,才可以控制该图层是否可见{layers2.add(layer);}}size = layers2.size();//if (size==0) super.onOptionsItemSelected(item);//将图层的名字和图层是否可见,复制进2个数组里,供显示对话框使用String[] layerNames = new String[size];visible = new boolean[size];for (int i = 0; i < size; ++i) {layer = layers2.get(i);layerNames[i] = layer.getName();visible[i] = layer.getVisible();}//显示一个对话框,供用户控制图层AlertDialog.Builder builder = new AlertDialog.Builder(act);builder.setIcon(R.drawable.icon);builder.setTitle("图层控制");builder.setMultiChoiceItems(layerNames, visible, new DialogInterface.OnMultiChoiceClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which, boolean isChecked) {visible[which] = isChecked;//保存用户的选择}});builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface arg0, int arg1) {int size = visible.length;for (int i = 0; i < size; ++i) {//重新设置每个可以被控制的图层的可见性layers2.get(i).setVisible(visible[i]);}mapView.getMapControl().refresh();//刷新地图立即看到效果}});builder.setNegativeButton("取消", null);//取消按钮什么事都不做builder.create().show();break;case 21:System.exit(0);break;}}});}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {menu.add("menu");return super.onCreateOptionsMenu(menu);}private SimpleAdapter getMenuAdapter(String[] menuNameArray,int[] imageResourceArray) {ArrayList<HashMap<String, Object>> data = new ArrayList<HashMap<String, Object>>();for (int i = 0; i < menuNameArray.length; i++) {HashMap<String, Object> map = new HashMap<String, Object>();map.put("itemImage", imageResourceArray[i]);map.put("itemText", menuNameArray[i]);data.add(map);}SimpleAdapter simperAdapter = new SimpleAdapter(this, data,R.layout.menu_item, new String[]{"itemImage", "itemText"},new int[]{R.id.item_image, R.id.item_text});return simperAdapter;}private Vector<EditText> ets = new Vector<EditText>();private LinearLayout.LayoutParams LP_FF = new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);private LinearLayout.LayoutParams LP_FW = new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);private LinearLayout.LayoutParams LP_WW = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);private void showModifyDialog(String[] fields, String[] values) {ScrollView sv = new ScrollView(this);sv.setLayoutParams(LP_FF);LinearLayout layout = new LinearLayout(this);layout.setOrientation(LinearLayout.VERTICAL);sv.addView(layout);TextView tv;EditText et;RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(400, LayoutParams.WRAP_CONTENT);//lp.setMargins(70, 0, 0, 0);int count = fields.length;ets.clear();for (int i = 0; i < count; ++i) {tv = new TextView(act);tv.setText(fields[i]);tv.setTextAppearance(act, android.R.style.TextAppearance_Medium);layout.addView(tv);et = new EditText(act);et.setLayoutParams(lp);et.setSingleLine(true);et.setTextAppearance(act, android.R.style.TextAppearance_Medium);et.setTextColor(0xFF000000);if (values != null) et.setText(values[i]);layout.addView(et);ets.addElement(et);}AlertDialog.Builder builder = new AlertDialog.Builder(act);builder.setView(sv).setTitle("修改属性").setIcon(R.drawable.icon).setPositiveButton("确定", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {int count = ets.size();String[] values = new String[count];for (int i = 0; i < count; ++i) {values[i] = ets.elementAt(i).getText().toString();}ft.setValues(values);editTool.confirm();}}).setNegativeButton("取消", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {editTool.cancel();}});builder.create().show();}//地图接口回调@Overridepublic void onAddFeature(IFeature ft, ILayer layer) {this.ft = ft;IFeatureLayer flayer = (IFeatureLayer) layer;this.showModifyDialog(flayer.getFeatureClass().getFields(), ft.getValues());}//地图接口回调@Overridepublic void onDeleteFeature(IFeature ft, ILayer layer) {editTool.confirm();    //不提示,直接删除要素}//地图接口回调@Overridepublic void onUpdateFeature(IFeature ft, ILayer layer) {IMapTool mt = mapView.getMapControl().getCurrentTool();if (mt == null) return;if (!(mt instanceof EditFeatureTool)) {this.ft = ft;IFeatureLayer flayer = (IFeatureLayer) layer;this.showModifyDialog(flayer.getFeatureClass().getFields(), ft.getValues());} else {//移动线上的节点之后,这里一起移动点图层上的对应的点要素ILayer lyr = mapView.getMapControl().getMap().getLayer("点");if (lyr != null && lyr instanceof ShapefileLayer) {EditFeatureTool eTool = (EditFeatureTool) mt;ShapefileLayer sLayer = (ShapefileLayer) lyr;//使用selectFeature函数查询点击处的点要素IFeature oldFeature = sLayer.selectFeature(mapView.getMapControl().getDisplay().getDisplayTransformation(), eTool.selector.getX(), eTool.selector.getY(), 10);if (oldFeature == null) return;IFeature newFeature = oldFeature.clone(true, false);//这里仅仅克隆一个具有相同shape的新要素if (eTool.newFeature.getShape() instanceof LineString) {LineString line = (LineString) eTool.newFeature.getShape();IPoint pt = line.getPoint(eTool.nodeIndex);//获取移动之后的节点位置(地图坐标)IPoint newPoint = (IPoint) newFeature.getShape();newPoint.setX(pt.getX());newPoint.setY(pt.getY());//将这个新要素的坐标移动到上述节点位置上sLayer.updateFeature(oldFeature, newFeature, true, false);//更新点要素位置}}}}

怎么编辑,选中图斑,导出shp,查询属性等等。

5,权限

    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /><uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.READ_PHONE_STATE" /><uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /><uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

还有注意你的application一定是这个

 android:name="cn.creable.gridgis.controls.App"

要么你就写一个application继承上面那个。

6,说一下注意事项

如果你的两个界面都是有地图控件,那么销毁界面时候,地图资源记得要释放。不然另外一个地图界面还是一样的数据。

我建议大家下载demo进行运行,然后查看代码,对照接口中文注释,然后看pdf。

大家有没有看过arcgis for android 和超图supmap 的sdk 都是有着版本更新非常大变化。重构幅度很大。

加载shp思路基本都是转换成自已一种格式,进行范围和坐标管理显示。有些是进行R树查询。

其实有个很大难点就是绘制很大的shp文件,怎么做算法查找和显示。

大家对gis这些开发上思路也可以评论一下。

ucmap for android 使用总结相关推荐

  1. 动画 gif_检测GIF是否为动画

    动画 gif If you tweet an animated GIF, you'll notice that Twitter takes it and converts it to an mp4. ...

  2. Unity5.6+ 导出Android 应用程序apk的环境配置及导出过程

    首先下载并安装安卓SDK和java的JDK 安卓sdk下载: http://www.android-studio.org/ 也可以在这下载: 链接:http://pan.baidu.com/s/1bp ...

  3. Android 的NDK的Makefile编写

    Android.mk 是google根据Linux GNU Makefile精简编译脚本.具体来说:这就是GNU Makefile的一小部分. 举一个简单例子: LOCAL_PATH := $(cal ...

  4. Android Animation (安卓动画)概念简介

    Android Animation Android 四种动画分别为逐帧动画和补间动画.属性动画.过渡动画: Frame Animation (逐帧动画) 实现方式:xml 和 Java代码 图片跳转的 ...

  5. 基于Android和SpringBoot的购物App

    (Shopping)购物应用商城 本软件使用Android和SpringBoot.JavaWeb技术实现:并结合百度LBS平台的SDK.支付宝App支付客户端SDK.MobTech的ShareSDK: ...

  6. Android数据持久化:SharePreference

    SharePreference:作为Android数据持久化的一种,具有一定的便捷性,适合存储一些体积小的数据. 存储数据方式:键值对的方式,类似于Map: 利用SharePreference.Edi ...

  7. Android数据持久化:文件存储

    数据持久化: 数据可分为瞬时数据和关键数据.保存在内存之中的数据是瞬时数据,而对于一些关键性数据,后期需要持续使用的,应当保存在存储设备中: 持久化保存方式: 文件存储.SharePreference ...

  8. Android Studio中RecycerView依赖库加载问题

    依赖包导入思考: 参考资料:recycleview导包问题 打开修改本项目中的build.gradle; 切勿着急添加包,应当提前查看其中的版本号(因为加载的v7包要和其版本保持一致性): 例如: 因 ...

  9. Android布局优化之include、merge、ViewStub

    include:引入重复使用的相同布局 merge:减少include布局的层级,将子元素直接添加到merge标签的parent中 ViewStub:其实就是一个宽高都为0的一个View,它默认是不可 ...

最新文章

  1. 收藏:存储知识全面总结
  2. 设计模式:设计模式七大原则
  3. java 文件读写demo
  4. 具体解决VS“滴答数必须介于 DateTime.MinValue.Ticks 和 DateTime.MaxValue.Ticks 之间”奇怪问题...
  5. Eclipse调试Java的10个技巧
  6. 在Jupyter Notebook中实现图像检测服务的调用
  7. 在输入文本框中获取值
  8. python培训班骗局-马哥教育官网-专业Linux培训班,Python培训机构
  9. 【HDU 5033】【经典单调栈问题】Building
  10. wildfly ejb开发环境搭建(一):wildfly安装及数据源配置
  11. inSSIDer无线信号扫描工具
  12. b5纸尺寸_【收藏款】平面设计标准尺寸规范总结
  13. keras实现交叉验证以及K折交叉验证
  14. Win11热键冲突怎么解决?
  15. 多示例学习 (multi-instance learning, MIL)学习路线 (分类)
  16. OSChina 周五乱弹 ——程序员会喜欢的 12 款键盘
  17. vue js樱花飘落背景特效
  18. 12.5米分辨率DEM
  19. 使用howler做一个音频播放器到底有多简单
  20. 微软携手云南打造软件产业高地 签约建立微软IT学院

热门文章

  1. 考研二战日记-第36天——高数6.4二阶常系数线性微分方程
  2. Java乐图下载_Java平台乐图导航地图测评:实时跟踪是亮点
  3. 关于Redis的BigKey
  4. Python例题100道
  5. AUTOjs3.0文档之悬浮窗
  6. 【报错】 ids for this class must be manually assigned before calling save()
  7. vs2017cpu占用过高解决方案
  8. 这几个SpringBoot前后端分离项目(附源码),改改就能换钱。。。
  9. 生产者消费者问题-代码详解(Java多线程)
  10. android调用系统相机并获取图片