上一篇我们已经初步的搭建起arcgis-android:100.13.0了,这一篇我们来研究如何在arcgis中绘制点,线,面图形来获得geometry对象,以方便我们后续篇章来将geometry对象存储另存为kml,shp,geojson,也或者是存储在arcgis server服务端。

在开始前我稍微改造了一下上一篇章的程序,我将默认各位会编写任意安卓布局,这一点我将忽略讲述

言归正传、要绘制点,线,面,要素图形我们需要用到arcgis提供的SketchEditor工具类,用它即可快速完成绘制。

点击右下工具箱,绘制按钮弹窗选择类型

 1、选择完毕要素类型后确定SketchEditor即可进入绘制状态,点击屏幕它会自动放置点在mapView中,在弹窗方法的时候做了个限制,一次只能开启一个绘制,如果已经是绘制状态了再点击绘制就不允许。

2、在屏幕点击的时候可能绘制错了,就可以调用undo,redo来前进和后退一个点,这样就可以重新画点了。但是这样会有个弊端,就是我们手指操作起来误操作点击太大了,这个就需要使用按钮来代替我们手指点击,辅助点击放置点能大大提高点击精准度,代码就是drawPointToMapView方法,该方法会放置一个点在屏幕的中心,使用的时候你需要先将中心点红色标记移动到要标记的地方然后点击按钮即可帮你自动放点

3、如何取消当前绘制的要素图形?sketchEditor.stop即可。完成绘制也是一样的调用stop。但是这里有个比较重要的点,调用stop之前要先获取geometry不然会被清空掉。这个geometry就是我们刚才在屏幕中绘制的图形了,类型就取决于你的SketchCreationMode是什么。

4、点击完成的时候我们还对geometry做了一次图形校验,成功后我们就顺利得到了geometry图形几何对象,然后交给addTempGeometryToMapView临时展示在mapView中

private fun initViewEvent(){
	//点击按钮往屏幕中心放置一个点
	binding.drawPointToMapView.setOnClickListener {
		drawPointToMapView()
	}

	//绘制完成
	binding.finish.setOnClickListener {
		/**
		 * 在绘制完成之前需要经过一次校验,例如绘制一根线,你最起码需要2个点才能形成线。绘制面最起码需要3个点才能形成面。如果
		 * 不加校验直接获取geometry,那么你得到的geometry将很可能是错误的,你拿错误的geometry进行存储这会造成潜在的脏数据
		 */
		if(sketchEditor.isSketchValid){
			//通过校验即可得到正确的geometry,后续将会拿它进行各种神奇的操作
			val geometry = sketchEditor.geometry
			val toJson = geometry.toJson()
			Toast.makeText(requireContext(),toJson,Toast.LENGTH_SHORT).show()

			//临时添加到mapView中显示出来
			addTempGeometryToMapView(geometry)

			sketchEditor.stop()
			//停止绘制,隐藏菜单
			hiddenDrawMenu()
		} else {
			Toast.makeText(requireContext(),"图形格式不正确,请校验",Toast.LENGTH_SHORT).show()
		}
	}
	//停止绘制
	binding.stopDraw.setOnClickListener {
		MaterialAlertDialogBuilder(requireContext())
			.setTitle(resources.getString(R.string.title))
			.setMessage("是否取消绘制图形?")
			.setNeutralButton(resources.getString(R.string.cancel)) { dialog, which -> }
			.setPositiveButton(resources.getString(R.string.ok)) { dialog, which ->
				sketchEditor.stop()
				//停止绘制,隐藏菜单
				hiddenDrawMenu()
			}
			.show()
	}
	//撤回一个点
	binding.undo.setOnClickListener { sketchEditor.undo() }
	//恢复一个点
	binding.redo.setOnClickListener { sketchEditor.redo() }

	//点击绘制按钮,选择将要绘制的类型
	binding.openDrawDialog.setOnClickListener {
		//判断是否已经是绘制状态了,如果是则不可再次弹窗
		val tag = binding.openDrawDialog.tag
		if(tag != null && tag == true){
			Toast.makeText(requireContext(),"已经是绘制状态",Toast.LENGTH_SHORT).show()
			return@setOnClickListener
		}
		val singleItems = arrayOf(POINT, POLYLINE, POLYGON)
		var checkedItem = 0
		MaterialAlertDialogBuilder(requireContext())
			.setTitle(resources.getString(R.string.title))
			.setNeutralButton(resources.getString(R.string.cancel)) { dialog, which -> }
			.setPositiveButton(resources.getString(R.string.ok)) { dialog, which ->
				//根据选中的类型,得到不同的SketchCreationMode,然后调用sketchEditor.start(sketchCreationMode)即可点击屏幕绘制
				when(singleItems[checkedItem]) {
					POINT -> { sketchCreationMode = SketchCreationMode.POINT }
					POLYLINE -> { sketchCreationMode = SketchCreationMode.POLYLINE }
					POLYGON -> { sketchCreationMode = SketchCreationMode.POLYGON }
				}
				//开启绘制
				sketchEditor.start(sketchCreationMode)

				//显示菜单
				showDrawMenu()
			}
			.setSingleChoiceItems(singleItems, checkedItem) { dialog, which -> checkedItem = which }
			.show()
	}
}



/**
 * 隐藏绘制菜单
 */
private fun hiddenDrawMenu(){
	binding.drawMenu.visibility = View.GONE
	binding.openDrawDialog.tag = null
	binding.drawPointToMapView.visibility = View.GONE
}

/**
 * 显示绘制菜单
 */
private fun showDrawMenu() {
	binding.drawMenu.visibility = View.VISIBLE
	binding.openDrawDialog.tag = true
	binding.drawPointToMapView.visibility = View.VISIBLE
}
/**
 * 如果不想手动添加,可以模拟点击触摸事件添加一个点到mapView
 */
private fun drawPointToMapView(){
	val mapView = binding.mapView
	val measuredWidth = mapView.measuredWidth
	val measuredHeight = mapView.measuredHeight
	val x = (measuredWidth * 0.5).toFloat()
	val y = (measuredHeight * 0.5).toFloat()
	mapView.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN, x, y, 0));
	mapView.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, x, y, 0));
}

在finish方法中顺利得到了geometry,怎么样才能将geometry图形真正添加进入mapView中呢?这里就可以使用 GraphicsOverlay+Graphic+Symbol+LabelDefinition 组合来完成,到此绘制功能就做好了

GraphicsOverlay+Graphic 图形组
Symbol 符号化
LabelDefinition 标签表达式

本篇章初略的讲述了如何使用 SketchEditor 来绘制图形,和如何将SketchEditor绘制完成得到的geometry初步的符号化+标注化 临时的添加进入了mapView中。

/**
 * 添加一个临时的geometry图形到mapView中,后续会把geometry持久化成为各种文件,
 * 例如kml,shp,geojson,arcgis server。。。
 *
 * 这里会用到标注,特别实用的功能,很多新人不知道怎么使用它
 */
private fun addTempGeometryToMapView(geometry: Geometry){
	var labelValue:String? = null
	val geometrySymbol = when(geometry.geometryType){
		GeometryType.POINT -> {
			labelValue = "我是点"
			SimpleMarkerSymbol(SimpleMarkerSymbol.Style.CIRCLE, Color.RED, 12F)
		}
		GeometryType.POLYLINE -> {
			labelValue = "我是线"
			SimpleLineSymbol(SimpleLineSymbol.Style.SOLID, Color.YELLOW, 2F)
		}
		GeometryType.POLYGON -> {
			labelValue = "我是面"
			val lineSymbol = SimpleLineSymbol(SimpleLineSymbol.Style.SOLID, Color.BLUE, 2F)
			SimpleFillSymbol(SimpleFillSymbol.Style.SOLID, Color.GREEN, lineSymbol)
		}
		else -> null
	}

	val textSymbol = TextSymbol().apply {
		size = 11f
		color = Color.BLUE
		outlineColor = Color.WHITE
		haloColor = Color.WHITE
		haloWidth = 2f
	}
	val labelDefinition = LabelDefinition(SimpleLabelExpression("[label]"), textSymbol).apply {
		isUseCodedValues = true
		placement = LabelingPlacement.AUTOMATIC
	}
	val graphicsOverlay = GraphicsOverlay()
	val attribute = mutableMapOf<String, Any>()
	attribute["label"] = labelValue!!
	val boundary = Graphic(geometry, attribute, geometrySymbol)
	graphicsOverlay.graphics.add(boundary)
	graphicsOverlay.labelDefinitions.add(labelDefinition)
	//开启标注
	graphicsOverlay.isLabelsEnabled = true
	binding.mapView.graphicsOverlays.apply {
		add(graphicsOverlay)
	}
}

https://gitee.com/tanqidi/ArcgisAndroidhttps://gitee.com/tanqidi/ArcgisAndroid

 

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐