Skip to content

Commit

Permalink
Improve vector map integration
Browse files Browse the repository at this point in the history
  • Loading branch information
bubelov committed Jan 9, 2025
1 parent fb1e4cd commit 03c75d8
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 79 deletions.
1 change: 1 addition & 0 deletions app/src/androidMain/kotlin/area/AreaAdapter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ class AreaAdapter(
it.initStyle(binding.root.context)
it.showPolygons(item.polygons, item.paddingPx)
}
binding.mapClickHandler.setOnClickListener { listener.onMapClick() }
}

if (item is Item.Description && binding is ItemAreaDescriptionBinding) {
Expand Down
3 changes: 2 additions & 1 deletion app/src/androidMain/kotlin/element/ElementFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import android.widget.Toast
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.net.toUri
import androidx.core.view.ViewCompat
Expand Down Expand Up @@ -93,7 +94,7 @@ class ElementFragment : Fragment() {

binding.mapContainer.isVisible = true

binding.mapContainer.setOnClickListener {
binding.mapClickHandler.setOnClickListener {
resultModel.element.update { element }
findNavController().navigate(R.id.action_elementFragment_to_mapFragment)
}
Expand Down
142 changes: 65 additions & 77 deletions app/src/androidMain/kotlin/map/MapFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import android.Manifest
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Matrix
import android.graphics.Paint
import android.net.Uri
import android.os.Bundle
Expand Down Expand Up @@ -37,6 +39,7 @@ import androidx.navigation.fragment.findNavController
import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.LinearLayoutManager
import area.AreaResultModel
import area.polygons
import com.google.android.material.bottomsheet.BottomSheetBehavior
import element.ElementFragment
import element.ElementsCluster
Expand All @@ -58,9 +61,8 @@ import org.maplibre.android.annotations.MarkerOptions
import org.maplibre.android.camera.CameraUpdateFactory
import org.maplibre.android.geometry.LatLng
import org.maplibre.android.geometry.LatLngBounds
import org.maplibre.android.gestures.MoveGestureDetector
import org.maplibre.android.maps.MapLibreMap
import org.maplibre.android.maps.MapLibreMap.OnMoveListener
import org.maplibre.android.maps.MapLibreMap.OnCameraIdleListener
import org.osmdroid.config.Configuration
import org.osmdroid.util.BoundingBox
import org.osmdroid.util.GeoPoint
Expand Down Expand Up @@ -140,6 +142,10 @@ class MapFragment : Fragment() {
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
binding.map.getMapAsync {
it.addOnCameraIdleListener(onCameraIdleListener)
}

emptyClusterBitmap = null

val markersRepo = MapMarkersRepo(requireContext())
Expand Down Expand Up @@ -296,42 +302,30 @@ class MapFragment : Fragment() {
it.cluster.comments,
)
}

val newBitmap = Bitmap.createBitmap(
icon.bitmap.width,
icon.bitmap.height * 2,
Bitmap.Config.ARGB_8888
)
val canvas = Canvas(newBitmap)
canvas.drawBitmap(icon.bitmap, Matrix(), null)
marker.icon(
IconFactory.getInstance(requireContext())
.fromBitmap(icon.bitmap)
.fromBitmap(newBitmap)
)
marker.snippet(it.cluster.id.toString())
// TODO marker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM)
} else {
val icon = createClusterIcon(it.cluster).toDrawable(resources)
marker.icon(
IconFactory.getInstance(requireContext())
.fromBitmap(icon.bitmap)
)
// TODO marker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_CENTER)
}

visibleElements += map.addMarker(marker)
}

is MapModel.MapItem.Meetup -> {
// TODO
// val marker = Marker(binding.map)
// marker.position = GeoPoint(it.meetup.lat, it.meetup.lon)
// marker.icon = markersRepo.meetupMarker
// marker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM)
// marker.setOnMarkerClickListener { _, _ ->
// findNavController().navigate(
// resId = R.id.areaFragment,
// args = bundleOf("area_id" to it.meetup.areaId),
// )
//
// true
// }
// visibleElements += marker
// binding.map.overlays += marker
}
is MapModel.MapItem.Meetup -> {}
}
}
}
Expand All @@ -357,49 +351,47 @@ class MapFragment : Fragment() {
areaResultModel.area.update { null }

if (pickedPlace != null) {
// TODO
// binding.map.addViewportListener()
// val mapController = binding.map.controller
// mapController.setZoom(16.toDouble())
// val startPoint =
// GeoPoint(pickedPlace.lat, pickedPlace.lon)
// mapController.setCenter(startPoint)
// binding.map.post {
// mapController.zoomTo(19.0)
// }
// model.selectElement(pickedPlace.id, true)
binding.map.getMapAsync {
model.selectElement(pickedPlace.id, true)
it.moveCamera(
CameraUpdateFactory.newLatLngZoom(
LatLng(
model.selectedElement.value!!.lat,
model.selectedElement.value!!.lon
), 16.0
)
)
}
return@repeatOnLifecycle
}

if (pickedArea != null) {
// TODO
// binding.map.addViewportListener()
// val boundingBox = boundingBox(pickedArea.tags.polygons())
// val boundingBoxPaddingPx = TypedValue.applyDimension(
// TypedValue.COMPLEX_UNIT_DIP,
// 16f,
// resources.displayMetrics,
// ).toInt()
// binding.map.zoomToBoundingBox(boundingBox, false, boundingBoxPaddingPx)
binding.map.getMapAsync {
val boundingBox = boundingBox(pickedArea.tags.polygons())
val boundingBoxPaddingPx = TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
16f,
resources.displayMetrics,
).toInt()
it.moveCamera(
CameraUpdateFactory.newLatLngBounds(
boundingBox.toLatLngBounds(),
boundingBoxPaddingPx
)
)
}
return@repeatOnLifecycle
}

val firstBoundingBox =
model.mapViewport.firstOrNull()?.boundingBox?.toLatLngBounds()!!

binding.map.getMapAsync {
it.addViewportListener()
it.moveCamera(
CameraUpdateFactory.newLatLngBounds(
firstBoundingBox, 0
)
)
model.setMapViewport(
MapModel.MapViewport(
zoom = it.cameraPosition.zoom,
boundingBox = it.projection.visibleRegion.latLngBounds.toBoundingBox(),
)
)
}
}
}
Expand All @@ -409,13 +401,16 @@ class MapFragment : Fragment() {
binding.searchView.hide()

model.selectElement(row.element.id, true)
// TODO
// val mapController = binding.map.controller
// mapController.setZoom(16.toDouble())
// val startPoint =
// GeoPoint(model.selectedElement.value!!.lat, model.selectedElement.value!!.lon)
// mapController.setCenter(startPoint)
// mapController.zoomTo(19.0)
binding.map.getMapAsync {
it.moveCamera(
CameraUpdateFactory.newLatLngZoom(
LatLng(
model.selectedElement.value!!.lat,
model.selectedElement.value!!.lon
), 16.0
)
)
}
}

binding.searchResults.layoutManager = LinearLayoutManager(requireContext())
Expand Down Expand Up @@ -451,6 +446,7 @@ class MapFragment : Fragment() {

override fun onDestroyView() {
super.onDestroyView()
binding.map.getMapAsync { it.removeOnCameraIdleListener(onCameraIdleListener) }
_binding = null
}

Expand Down Expand Up @@ -486,28 +482,20 @@ class MapFragment : Fragment() {
}
}

private fun MapLibreMap.addViewportListener() {
addOnMoveListener(object : OnMoveListener {
override fun onMoveBegin(p0: MoveGestureDetector) {
}

override fun onMove(p0: MoveGestureDetector) {
}

override fun onMoveEnd(p0: MoveGestureDetector) {
model.setMapViewport(
MapModel.MapViewport(
zoom = cameraPosition.zoom,
boundingBox = projection.visibleRegion.latLngBounds.toBoundingBox(),
)
private val onCameraIdleListener = OnCameraIdleListener {
binding.map.getMapAsync { map ->
model.setMapViewport(
MapModel.MapViewport(
zoom = map.cameraPosition.zoom,
boundingBox = map.projection.visibleRegion.latLngBounds.toBoundingBox(),
)
searchModel.setLocation(
GeoPoint(
cameraPosition.target!!.latitude, cameraPosition.target!!.longitude
)
)
searchModel.setLocation(
GeoPoint(
map.cameraPosition.target!!.latitude, map.cameraPosition.target!!.longitude
)
}
})
)
}
}

private fun BottomSheetBehavior<*>.addSlideCallback() {
Expand Down
6 changes: 6 additions & 0 deletions app/src/androidMain/res/layout/fragment_element.xml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@
android:id="@+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent" />

<View
android:id="@+id/mapClickHandler"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true" />
</FrameLayout>

<ImageView
Expand Down
6 changes: 6 additions & 0 deletions app/src/androidMain/res/layout/item_map.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,10 @@
android:layout_width="match_parent"
android:layout_height="192dp" />

<View
android:id="@+id/mapClickHandler"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true" />

</FrameLayout>
2 changes: 1 addition & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[versions]
# https://developer.android.com/build/releases/gradle-plugin
agp = "8.7.1"
agp = "8.7.3"
# https://github.com/JetBrains/kotlin/releases
kotlin = "1.9.25"
# Allows suspending functions
Expand Down

0 comments on commit 03c75d8

Please sign in to comment.