androidMain.tech.skot.libraries.map.SKMapView.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of viewlegacy Show documentation
Show all versions of viewlegacy Show documentation
viewlegacy module for SK-Map skot library
The newest version!
package tech.skot.libraries.map
import android.Manifest
import android.annotation.SuppressLint
import android.content.Context
import android.content.pm.PackageManager
import android.content.res.Resources
import android.graphics.Bitmap
import androidx.collection.LruCache
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import com.google.android.gms.location.FusedLocationProviderClient
import com.google.android.gms.location.LocationServices
import com.google.android.gms.maps.CameraUpdateFactory
import com.google.android.gms.maps.GoogleMap
import com.google.android.gms.maps.MapView
import com.google.android.gms.maps.model.BitmapDescriptor
import com.google.android.gms.maps.model.BitmapDescriptorFactory
import com.google.android.gms.maps.model.LatLngBounds
import tech.skot.core.components.SKActivity
import tech.skot.core.components.SKComponentView
import com.google.android.gms.maps.model.LatLng as LatLngGMap
class SKMapView(
override val proxy: SKMapViewProxy,
activity: SKActivity,
fragment: Fragment?,
val mapView: MapView
) : SKComponentView(proxy, activity, fragment, mapView), SKMapRAI {
private var mapInteractionHelper: MapInteractionHelper? = null
private val memoryCache: LruCache
private var fusedLocationClient: FusedLocationProviderClient =
LocationServices.getFusedLocationProviderClient(context)
/**
* use it to create BitmapDescriptor in case of [CustomMarker][SKMapVC.CustomMarker] use
*/
@Suppress("unused")
var onCreateCustomMarkerIcon: ((SKMapVC.CustomMarker, selected: Boolean) -> Bitmap)? = null
set(value) {
field = value
mapInteractionHelper?.onCreateCustomMarkerIcon = value
}
@Suppress("unused")
var getMarkerAnchor : ((SKMapVC.Marker, selected: Boolean) -> Pair?)? = null
set(value) {
field = value
mapInteractionHelper?.getMarkerAnchor = value
}
init {
lifecycleOwner.lifecycle.addObserver(object : DefaultLifecycleObserver {
override fun onDestroy(owner: LifecycleOwner) {
super.onDestroy(owner)
mapView.onDestroy()
}
override fun onCreate(owner: LifecycleOwner) {
super.onCreate(owner)
mapView.onCreate(null)
}
override fun onPause(owner: LifecycleOwner) {
super.onPause(owner)
mapView.onPause()
}
override fun onResume(owner: LifecycleOwner) {
super.onResume(owner)
mapView.onResume()
}
override fun onStart(owner: LifecycleOwner) {
super.onStart(owner)
mapView.onStart()
}
override fun onStop(owner: LifecycleOwner) {
super.onStop(owner)
mapView.onStop()
}
})
val maxMemory = (Runtime.getRuntime().maxMemory()).toInt()
val cacheSize = maxMemory / 8
memoryCache =
object : LruCache(cacheSize) {
override fun sizeOf(
key: String,
bitmap: BitmapDescriptorContainer
): Int {
return bitmap.size
}
}
// mapInteractionHelper = when (val settings = proxy.mapInteractionSettings) {
// is SKMapVC.MapClusteringInteractionSettings -> {
// GMapClusteringInteractionHelper(activity, mapView, memoryCache, settings)
// }
// is SKMapVC.MapNormalInteractionSettings -> {
// GMapInteractionHelper(activity, mapView, memoryCache)
// }
// is SKMapVC.MapCustomInteractionSettings -> {
// mapRefCustomInteractionHelper[settings.customRef]?.invoke(
// activity,
// mapView,
// memoryCache,
// settings.data
// )
// ?: throw NotImplementedError("With MapCustomInteractionSettings you must provide a CustomInteractionHelper with ref ${settings.customRef} in mapRefCustomInteractionHelper ")
// }
// }.apply {
// this.onCreateCustomMarkerIcon = [email protected]
// }
}
override fun onSelectedMarker(selectedMarker: SKMapVC.Marker?) {
mapInteractionHelper?.onSelectedMarker(selectedMarker)
}
override fun onMarkers(markers: List) {
mapInteractionHelper?.addMarkers(markers)
}
override fun onLines(polylines: List) {
mapInteractionHelper?.addLines(polylines)
}
override fun onPolygons(polygons: List) {
mapInteractionHelper?.addPolygons(polygons)
}
override fun onMapType(mapType : MapType) {
mapView.getMapAsync {
when(mapType){
MapType.NORMAL -> it.mapType = GoogleMap.MAP_TYPE_NORMAL
MapType.SATELLITE -> it.mapType = GoogleMap.MAP_TYPE_SATELLITE
MapType.HYBRID -> it.mapType = GoogleMap.MAP_TYPE_HYBRID
MapType.TERRAIN -> it.mapType = GoogleMap.MAP_TYPE_TERRAIN
MapType.NONE -> it.mapType = GoogleMap.MAP_TYPE_NONE
else -> it.mapType = GoogleMap.MAP_TYPE_NORMAL
}
}
}
override fun onOnMapClicked(onMapClicked: ((LatLng) -> Unit)?) {
mapView.getMapAsync {
if (onMapClicked != null) {
it.setOnMapClickListener {
onMapClicked.invoke(it.latitude to it.longitude)
}
} else {
it.setOnMapClickListener(null)
}
}
}
override fun onOnMapLongClicked(onMapLongClicked: ((LatLng) -> Unit)?) {
mapView.getMapAsync {
if (onMapLongClicked != null) {
it.setOnMapLongClickListener {
onMapLongClicked.invoke(it.latitude to it.longitude)
}
} else {
it.setOnMapClickListener(null)
}
}
}
override fun onOnMarkerClick(onMarkerClick: ((SKMapVC.Marker) -> Unit)?) {
mapInteractionHelper?.onMarkerClick = onMarkerClick
}
override fun onMapInteractionSettings(mapInteractionSettings: SKMapVC.MapInteractionSettings) {
mapView.getMapAsync { googleMap ->
googleMap.clear()
mapInteractionHelper = null
mapInteractionHelper = when (mapInteractionSettings) {
is SKMapVC.MapClusteringInteractionSettings -> {
GMapClusteringInteractionHelper(
context = activity,
mapView = mapView,
memoryCache = memoryCache,
mapInteractionSettings
)
}
is SKMapVC.MapNormalInteractionSettings -> {
GMapInteractionHelper(activity, mapView, memoryCache)
}
is SKMapVC.MapCustomInteractionSettings -> {
mapRefCustomInteractionHelper[mapInteractionSettings.customRef]?.invoke(
activity,
mapView,
memoryCache,
mapInteractionSettings.data
)
?: throw NotImplementedError("With MapCustomInteractionSettings you must provide a CustomInteractionHelper with ref ${mapInteractionSettings.customRef} in mapRefCustomInteractionHelper ")
}
}.apply {
this.onCreateCustomMarkerIcon = [email protected]
this.getMarkerAnchor = [email protected]
this.onOnMapBoundsChange(proxy.onMapBoundsChange)
this.onMarkerClick = proxy.onMarkerClicked
this.onSelectedMarker(proxy.selectedMarker)
this.addMarkers(proxy.markers)
this.addLines(proxy.polylines)
}
}
}
override fun onShowLog(show: Boolean) {
MapLoggerView.enabled = show
}
override fun getCurrentLocation(onResult: (LatLng) -> Unit) {
if (ActivityCompat.checkSelfPermission(
context,
Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
context,
Manifest.permission.ACCESS_COARSE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
return
}
fusedLocationClient.lastLocation.addOnSuccessListener {
onResult(LatLng(it.latitude, it.longitude))
}
}
override fun setCameraPosition(
position: LatLng,
zoomLevel: Float,
animate: Boolean
) {
mapView.getMapAsync {
it.setOnMapLoadedCallback {
val cameraUpdate =
CameraUpdateFactory.newLatLngZoom(
com.google.android.gms.maps.model.LatLng(position.first, position.second),
zoomLevel
)
if (animate) {
it.animateCamera(cameraUpdate)
} else {
it.moveCamera(cameraUpdate)
}
}
}
}
override fun centerOnPositions(positions: List) {
if (positions.isNotEmpty()) {
mapView.getMapAsync {
it.setOnMapLoadedCallback {
val latLngBoundsBuilder = LatLngBounds.builder()
positions.forEach {
latLngBoundsBuilder.include(LatLngGMap(it.first, it.second))
}
val latLngBound = CameraUpdateFactory.newLatLngBounds(
latLngBoundsBuilder.build(),
(16 * Resources.getSystem().displayMetrics.density).toInt()
)
it.animateCamera(latLngBound)
}
}
}
}
override fun getMapBounds(onResult: (SKMapVC.LatLngBounds) -> Unit) {
mapView.getMapAsync {
it.projection.visibleRegion.latLngBounds.let {
onResult(
SKMapVC.LatLngBounds(
it.northeast.latitude to it.northeast.longitude,
it.southwest.latitude to it.southwest.longitude
)
)
}
}
}
override fun onOnMapBoundsChange(onMapBoundsChange: ((SKMapVC.LatLngBounds) -> Unit)?) {
mapInteractionHelper?.onOnMapBoundsChange(onMapBoundsChange)
}
override fun setCameraZoom(zoomLevel: Float, animate: Boolean) {
mapView.getMapAsync {
CameraUpdateFactory.zoomTo(zoomLevel).let { cameraUpdate ->
if (animate) {
it.animateCamera(cameraUpdate)
} else {
it.moveCamera(cameraUpdate)
}
}
}
}
@SuppressLint("MissingPermission")
override fun showMyLocationButton(
show: Boolean,
onPermissionError: (() -> Unit)?
) {
mapView.getMapAsync {
if (ContextCompat.checkSelfPermission(
context,
android.Manifest.permission.ACCESS_COARSE_LOCATION
) == PackageManager.PERMISSION_GRANTED ||
ContextCompat.checkSelfPermission(
context,
android.Manifest.permission.ACCESS_FINE_LOCATION
) == PackageManager.PERMISSION_GRANTED
) {
MapLoggerView.d("enabled myLocationButton :$show")
it.isMyLocationEnabled = show
it.uiSettings.isMyLocationButtonEnabled = true
} else {
MapLoggerView.d("permission error :$show")
onPermissionError?.invoke()
}
}
}
@SuppressLint("MissingPermission")
override fun showMyLocation(
show: Boolean,
onPermissionError: (() -> Unit)?
) {
mapView.getMapAsync {
if (ContextCompat.checkSelfPermission(
context,
android.Manifest.permission.ACCESS_COARSE_LOCATION
) == PackageManager.PERMISSION_GRANTED ||
ContextCompat.checkSelfPermission(
context,
android.Manifest.permission.ACCESS_FINE_LOCATION
) == PackageManager.PERMISSION_GRANTED
) {
MapLoggerView.d("enabled myLocationButton :$show")
it.isMyLocationEnabled = show
} else {
MapLoggerView.d("permission error :$show")
onPermissionError?.invoke()
}
}
}
class BitmapDescriptorContainer(bitmap: Bitmap) {
val bitmapDescriptor: BitmapDescriptor = BitmapDescriptorFactory.fromBitmap(bitmap)
val size: Int = bitmap.byteCount
}
companion object {
val mapRefCustomInteractionHelper: MutableMap, data: Any?) -> MapInteractionHelper> =
mutableMapOf()
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy