-
Notifications
You must be signed in to change notification settings - Fork 1
Description
MicrosoftTeams-video.mp4
from below code i will get above output that is showing to you in video
class DraggableActivity : AppCompatActivity(), MapboxMap.OnMapClickListener {
companion object {
private const val FILL_LAYER_ID = "fill-layer-id"
private const val FILL_SOURCE_ID = "fill-source-id"
private const val ID_ICON_LOCATION = "location"
private const val ID_ICON_ADD = "add"
private const val ID_ICON_LOCATION_SELECTED = "location_selected"
}
private var lastDraggedMidpointId: String? = null
private lateinit var undofab: FloatingActionButton
private var mapView: MapView? = null
private var symbolOptionsMid: SymbolOptions? = null
private var mapboxMap: MapboxMap? = null
private var fillSource: GeoJsonSource? = null
private lateinit var polyList: ArrayList
private lateinit var midPointList: ArrayList
private var rootSymbolId: String? = null
private var newPolygon: Boolean = false
private lateinit var symbolManager: SymbolManager
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Mapbox.getInstance(this, getString(R.string.mapbox_access_token))
setContentView(R.layout.activity_main)
mapView = findViewById(R.id.mapView)
undofab = findViewById(R.id.undo_fab)
mapView?.onCreate(savedInstanceState)
polyList = ArrayList()
midPointList = ArrayList()
mapView?.getMapAsync { mapboxMap ->
this.mapboxMap = mapboxMap
mapboxMap.setStyle(Style.SATELLITE) { it ->
addMarkerIconStyle(it)
symbolManager = SymbolManager(mapView!!, mapboxMap, mapboxMap.style!!)
symbolManager.addClickListener{ t ->
highlightSymbol(t)
val clickedPoint = polyList.find { it.symbolId == t.id.toString() }
if (clickedPoint != null) {
if (t.id.toString() == rootSymbolId && polyList.size > 2) {
polyList.add(polyList[0])
drawPolygon()
} else {
drawPolygon()
}
}
true
}
symbolManager.addDragListener(object : OnSymbolDragListener {
override fun onAnnotationDragStarted(annotation: Symbol?) {
highlightSymbol(annotation)
symbolManager.update(annotation)
}
override fun onAnnotationDrag(annotation: Symbol?) {
if (annotation == null) return
annotation.let {
val pointLatLng = polyList.find { it.symbolId == annotation.id.toString() }
pointLatLng?.let { it.latLng = annotation.latLng }
drawPolygon()
symbolOptionsMid= null
}
}
override fun onAnnotationDragFinished(annotation: Symbol?) {
if (annotation == null) return
var isSymbolPresent = false
var startLatLng: LatLng? = null
var endLatLng: LatLng? = null
for (i in polyList.indices) {
if (polyList[i].symbolId == annotation.id.toString()) {
isSymbolPresent = true
polyList[i].latLng = annotation.latLng
break
}
}
// If it's not a main polygon symbol, check if it's a midpoint
if (!isSymbolPresent) {
for (i in midPointList.indices) {
if (midPointList[i].symbol.id == annotation.id) {
startLatLng = midPointList[i].latlng1
endLatLng = midPointList[i].latLng2
break
}
}
}
// If a midpoint is dragged, handle the new point insertion and midpoint recalculation
if (!isSymbolPresent && startLatLng != null && endLatLng != null) {
if (lastDraggedMidpointId == annotation.id.toString()) {
if (midPointList.size > 1) {
midPointList.removeAt(midPointList.size - 1) // Remove last midpoint
}
if (midPointList.size > 1) {
midPointList.removeAt(midPointList.size - 1) // Remove second last midpoint
}
} else {
// Find the index of the midpoint being dragged
for (i in polyList.indices) {
if (polyList[i].latLng.latitude == startLatLng.latitude &&
polyList[i].latLng.longitude == startLatLng.longitude) {
// Insert the dragged point into the polyList at the correct position
polyList.add(i + 1, PointLatLng(annotation.id.toString(), annotation.latLng))
// Remove old midpoints for the affected segments
if (midPointList.size > i) {
midPointList.removeAt(i) // Remove first midpoint
}
if (midPointList.size > i) {
midPointList.removeAt(i) // Remove second midpoint
}
// Generate new midpoints after insertion
addNewMidpointsAfterDrag(i, annotation.latLng, startLatLng, endLatLng)
// Update last dragged midpoint ID
lastDraggedMidpointId = annotation.id.toString()
symbolOptionsMid = null
break
}
}
}
} else {
lastDraggedMidpointId = null
}
// Redraw the polygon
drawPolygon()
}
})
fillSource = initFillSource(it)
initFillLayer(it)
mapboxMap.addOnMapClickListener(this)
val position = CameraPosition.Builder()
.target(LatLng(51.50550, -0.07520))
.zoom(8.0)
.build()
mapboxMap.animateCamera(CameraUpdateFactory.newCameraPosition(position), 2000)
}
}
undofab.setOnClickListener {
// Handle undo logic by removing the last point
val lastKey = polyList.last().symbolId
if (polyList.isNotEmpty()) {
val annotations = symbolManager.annotations
for (i in 0 until annotations.size()) {
val key = annotations.keyAt(i)
val value = annotations.valueAt(i)
if (key.toString() == lastKey) {
symbolManager.delete(value) // Delete the symbol with the matching key
}
}
polyList.removeAt(polyList.size - 1) // Remove the last element
drawPolygon()
}
}
}
private fun addNewMidpointsAfterDrag(index: Int, draggedLatLng: LatLng, startLatLng: LatLng, endLatLng: LatLng) {
// Create new midpoints for the new segments
val newMidpoint1 = getMidpoint(
startLatLng.latitude,
startLatLng.longitude,
draggedLatLng.latitude,
draggedLatLng.longitude
)
val symbolOptions1 = SymbolOptions().withLatLng(newMidpoint1)
.withIconImage(ID_ICON_ADD).withDraggable(true)
.withIconSize(1f)
val newSymbol1 = symbolManager.create(symbolOptions1)
midPointList.add(index, AddMarkerPoint(startLatLng, draggedLatLng, newSymbol1))
val newMidpoint2 = getMidpoint(
endLatLng.latitude,
endLatLng.longitude,
draggedLatLng.latitude,
draggedLatLng.longitude
)
val symbolOptions2 = SymbolOptions().withLatLng(newMidpoint2)
.withIconImage(ID_ICON_ADD).withDraggable(true)
.withIconSize(1f)
val newSymbol2 = symbolManager.create(symbolOptions2)
midPointList.add(index + 1, AddMarkerPoint(draggedLatLng, endLatLng, newSymbol2))
}
private fun initFillSource(loadedMapStyle: Style): GeoJsonSource {
val fillFeatureCollection = FeatureCollection.fromFeatures(arrayOf())
val fillGeoJsonSource = GeoJsonSource(FILL_SOURCE_ID, fillFeatureCollection)
loadedMapStyle.addSource(fillGeoJsonSource)
return fillGeoJsonSource
}
private fun initFillLayer(loadedMapStyle: Style) {
val fillLayer = LineLayer(
FILL_LAYER_ID,
FILL_SOURCE_ID
)
fillLayer.setProperties(
PropertyFactory.lineWidth(2.5f),
PropertyFactory.lineColor(Color.parseColor("#ffffff"))
)
loadedMapStyle.addLayerBelow(fillLayer, symbolManager.layerId)
}
fun highlightSymbol(t: Symbol?) {
val symbols = symbolManager.annotations
val lists = ArrayList(symbols.size())
for (i in 0 until symbols.size()) {
val symbol = symbols.valueAt(i)
symbol.iconImage = ID_ICON_LOCATION
lists.add(symbol)
}
symbolManager.update(lists)
t?.iconImage = ID_ICON_LOCATION_SELECTED
symbolManager.update(t)
}
override fun onMapClick(point: LatLng): Boolean {
val symbolOptions = SymbolOptions().withLatLng(point).withIconImage(ID_ICON_LOCATION).withDraggable(true)
.withIconSize(1f)
val symbol = symbolManager.create(symbolOptions)
if (polyList.isEmpty()) {
rootSymbolId = symbol.id.toString()
} else if (newPolygon) {
newPolygon = false
rootSymbolId = symbol.id.toString()
} else {
val midPoints = getMidpoint(
polyList.last().latLng.latitude,
polyList.last().latLng.longitude,
point.latitude,
point.longitude
)
symbolOptionsMid= SymbolOptions()
.withLatLng(midPoints)
.withIconImage(ID_ICON_ADD)
.withDraggable(true)
.withIconSize(1f)
val midSymbol = symbolManager.create(symbolOptionsMid)
symbolManager.iconAllowOverlap = true
midPointList.add(AddMarkerPoint(polyList.last().latLng, point, midSymbol))
}
polyList.add(PointLatLng(symbol.id.toString(), symbol.latLng))
drawPolygon()
return true
}
private fun addMarkerIconStyle(style: Style) {
style.addImage(
ID_ICON_LOCATION,
BitmapUtils.getBitmapFromDrawable(
ContextCompat.getDrawable(
this,
R.drawable.ic_mark
)
)!!,
false
)
style.addImage(
ID_ICON_ADD,
BitmapUtils.getBitmapFromDrawable(
ContextCompat.getDrawable(
this,
R.drawable.ic_add
)
)!!,
false
)
style.addImage(
ID_ICON_LOCATION_SELECTED, BitmapUtils.getBitmapFromDrawable(
ContextCompat.getDrawable(
this,
R.drawable.ic_mark
)
)!!,
false
)
}
private fun drawPolygon() {
val latLngList = polyList.map { it.latLng }
val points = latLngList.map { Point.fromLngLat(it.longitude, it.latitude) }
val fillFeatureList = arrayListOf(Feature.fromGeometry(LineString.fromLngLats(points)))
fillSource?.setGeoJson(FeatureCollection.fromFeatures(fillFeatureList))
}
fun getMidpoint(lat1: Double,
lng1: Double,
lat2: Double,
lng2: Double): LatLng {
return LatLng((lat1 + lat2) / 2, (lng1 + lng2) / 2)
}
}
but from this output i want some changes that if i will drag marker others markers can't detach like show in video all markers should attach