mirror of
https://github.com/ev-map/EVMap.git
synced 2026-05-19 04:16:24 -04:00
use AnyMaps to make the map view able to use OSM maps
This commit is contained in:
@@ -33,13 +33,15 @@ import androidx.recyclerview.widget.DividerItemDecoration
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.transition.TransitionInflater
|
||||
import androidx.transition.TransitionManager
|
||||
import com.car2go.maps.AnyMap
|
||||
import com.car2go.maps.MapFragment
|
||||
import com.car2go.maps.OnMapReadyCallback
|
||||
import com.car2go.maps.model.LatLng
|
||||
import com.car2go.maps.model.Marker
|
||||
import com.car2go.maps.model.MarkerOptions
|
||||
import com.car2go.maps.osm.MapsConfiguration
|
||||
import com.google.android.gms.location.FusedLocationProviderClient
|
||||
import com.google.android.gms.location.LocationServices
|
||||
import com.google.android.libraries.maps.CameraUpdateFactory
|
||||
import com.google.android.libraries.maps.GoogleMap
|
||||
import com.google.android.libraries.maps.OnMapReadyCallback
|
||||
import com.google.android.libraries.maps.SupportMapFragment
|
||||
import com.google.android.libraries.maps.model.*
|
||||
import com.google.android.libraries.places.api.model.Place
|
||||
import com.google.android.libraries.places.widget.Autocomplete
|
||||
import com.google.android.libraries.places.widget.model.AutocompleteActivityMode
|
||||
@@ -83,7 +85,7 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac
|
||||
}
|
||||
})
|
||||
private val galleryVm: GalleryViewModel by activityViewModels()
|
||||
private var map: GoogleMap? = null
|
||||
private var map: AnyMap? = null
|
||||
private lateinit var fusedLocationClient: FusedLocationProviderClient
|
||||
private lateinit var bottomSheetBehavior: BottomSheetBehaviorGoogleMapsLike<View>
|
||||
private lateinit var detailAppBarBehavior: MergedAppBarLayoutBehavior
|
||||
@@ -116,6 +118,11 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
MapsConfiguration.getInstance().initialize(context)
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
@@ -127,8 +134,6 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac
|
||||
|
||||
fusedLocationClient = LocationServices.getFusedLocationProviderClient(requireContext())
|
||||
clusterIconGenerator = ClusterIconGenerator(requireContext())
|
||||
chargerIconGenerator = ChargerIconGenerator(requireContext())
|
||||
animator = MarkerAnimator(chargerIconGenerator)
|
||||
|
||||
setHasOptionsMenu(true)
|
||||
postponeEnterTransition()
|
||||
@@ -153,7 +158,7 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
val mapFragment = childFragmentManager.findFragmentById(R.id.map) as SupportMapFragment
|
||||
val mapFragment = childFragmentManager.findFragmentById(R.id.map) as MapFragment
|
||||
mapFragment.getMapAsync(this)
|
||||
bottomSheetBehavior = BottomSheetBehaviorGoogleMapsLike.from(binding.bottomSheet)
|
||||
detailAppBarBehavior = MergedAppBarLayoutBehavior.from(binding.detailAppBar)
|
||||
@@ -344,33 +349,33 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac
|
||||
vm.favorites.observe(viewLifecycleOwner, Observer {
|
||||
updateFavoriteToggle()
|
||||
})
|
||||
vm.searchResult.observe(viewLifecycleOwner, Observer { place ->
|
||||
/* TODO: vm.searchResult.observe(viewLifecycleOwner, Observer { place ->
|
||||
val map = this.map ?: return@Observer
|
||||
searchResultMarker?.remove()
|
||||
searchResultMarker = null
|
||||
|
||||
if (place != null) {
|
||||
if (place.viewport != null) {
|
||||
map.animateCamera(CameraUpdateFactory.newLatLngBounds(place.viewport, 0))
|
||||
map.animateCamera(map.cameraUpdateFactory.newLatLngBounds(AnyMapAdapter.adapt(place.viewport), 0))
|
||||
} else {
|
||||
map.animateCamera(CameraUpdateFactory.newLatLngZoom(place.latLng, 12f))
|
||||
map.animateCamera(map.cameraUpdateFactory.newLatLngZoom(AnyMapAdapter.adapt(place.latLng), 12f))
|
||||
}
|
||||
|
||||
searchResultMarker = map.addMarker(MarkerOptions().position(place.latLng!!))
|
||||
searchResultMarker = map.addMarker(MarkerOptions().position(AnyMapAdapter.adapt(place.latLng!!))).anchor(0.5f, 1f)
|
||||
}
|
||||
|
||||
updateBackPressedCallback()
|
||||
})
|
||||
})*/
|
||||
vm.layersMenuOpen.observe(viewLifecycleOwner, Observer { open ->
|
||||
binding.fabLayers.visibility = if (open) View.GONE else View.VISIBLE
|
||||
binding.layersSheet.visibility = if (open) View.VISIBLE else View.GONE
|
||||
updateBackPressedCallback()
|
||||
})
|
||||
vm.mapType.observe(viewLifecycleOwner, Observer {
|
||||
map?.mapType = it
|
||||
map?.setMapType(it)
|
||||
})
|
||||
vm.mapTrafficEnabled.observe(viewLifecycleOwner, Observer {
|
||||
map?.isTrafficEnabled = it
|
||||
map?.setTrafficEnabled(it)
|
||||
})
|
||||
|
||||
updateBackPressedCallback()
|
||||
@@ -528,11 +533,13 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac
|
||||
}.show()
|
||||
}
|
||||
|
||||
override fun onMapReady(map: GoogleMap) {
|
||||
override fun onMapReady(map: AnyMap) {
|
||||
this.map = map
|
||||
map.uiSettings.isTiltGesturesEnabled = false
|
||||
map.isIndoorEnabled = false
|
||||
map.uiSettings.isIndoorLevelPickerEnabled = false
|
||||
chargerIconGenerator = ChargerIconGenerator(requireContext(), map.bitmapDescriptorFactory)
|
||||
animator = MarkerAnimator(chargerIconGenerator)
|
||||
map.uiSettings.setTiltGesturesEnabled(false)
|
||||
map.setIndoorEnabled(false)
|
||||
map.uiSettings.setIndoorLevelPickerEnabled(false)
|
||||
map.setOnCameraIdleListener {
|
||||
vm.mapPosition.value = MapPosition(
|
||||
map.projection.visibleRegion.latLngBounds, map.cameraPosition.zoom
|
||||
@@ -546,7 +553,12 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac
|
||||
}
|
||||
in clusterMarkers -> {
|
||||
val newZoom = map.cameraPosition.zoom + 2
|
||||
map.animateCamera(CameraUpdateFactory.newLatLngZoom(marker.position, newZoom))
|
||||
map.animateCamera(
|
||||
map.cameraUpdateFactory.newLatLngZoom(
|
||||
marker.position,
|
||||
newZoom
|
||||
)
|
||||
)
|
||||
true
|
||||
}
|
||||
else -> false
|
||||
@@ -563,11 +575,12 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac
|
||||
map.setPadding(0, binding.toolbarContainer.height, 0, 0)
|
||||
|
||||
val mode = resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
|
||||
/* TODO:
|
||||
map.setMapStyle(
|
||||
if (mode == Configuration.UI_MODE_NIGHT_YES) {
|
||||
MapStyleOptions.loadRawResourceStyle(context, R.raw.maps_night_mode)
|
||||
} else null
|
||||
)
|
||||
)*/
|
||||
|
||||
|
||||
val position = vm.mapPosition.value
|
||||
@@ -577,12 +590,12 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac
|
||||
|
||||
if (position != null) {
|
||||
val cameraUpdate =
|
||||
CameraUpdateFactory.newLatLngZoom(position.bounds.center, position.zoom)
|
||||
map.cameraUpdateFactory.newLatLngZoom(position.bounds.center, position.zoom)
|
||||
map.moveCamera(cameraUpdate)
|
||||
positionSet = true
|
||||
} else if (lat != null && lon != null) {
|
||||
// show given position
|
||||
val cameraUpdate = CameraUpdateFactory.newLatLngZoom(LatLng(lat, lon), 16f)
|
||||
val cameraUpdate = map.cameraUpdateFactory.newLatLngZoom(LatLng(lat, lon), 16f)
|
||||
map.moveCamera(cameraUpdate)
|
||||
|
||||
// show charger detail after chargers were loaded
|
||||
@@ -609,7 +622,8 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac
|
||||
}
|
||||
if (!positionSet) {
|
||||
// center the camera on Europe
|
||||
val cameraUpdate = CameraUpdateFactory.newLatLngZoom(LatLng(50.113388, 9.252536), 3.5f)
|
||||
val cameraUpdate =
|
||||
map.cameraUpdateFactory.newLatLngZoom(LatLng(50.113388, 9.252536), 3.5f)
|
||||
map.moveCamera(cameraUpdate)
|
||||
}
|
||||
|
||||
@@ -621,14 +635,14 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac
|
||||
@SuppressLint("MissingPermission")
|
||||
private fun enableLocation(moveTo: Boolean, animate: Boolean) {
|
||||
val map = this.map ?: return
|
||||
map.isMyLocationEnabled = true
|
||||
map.setMyLocationEnabled(true)
|
||||
vm.myLocationEnabled.value = true
|
||||
map.uiSettings.isMyLocationButtonEnabled = false
|
||||
map.uiSettings.setMyLocationButtonEnabled(false)
|
||||
if (moveTo) {
|
||||
fusedLocationClient.lastLocation.addOnSuccessListener { location ->
|
||||
if (location != null) {
|
||||
val latLng = LatLng(location.latitude, location.longitude)
|
||||
val camUpdate = CameraUpdateFactory.newLatLngZoom(latLng, 13f)
|
||||
val camUpdate = map.cameraUpdateFactory.newLatLngZoom(latLng, 13f)
|
||||
if (animate) {
|
||||
map.animateCamera(camUpdate)
|
||||
} else {
|
||||
@@ -697,7 +711,16 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac
|
||||
val marker = map.addMarker(
|
||||
MarkerOptions()
|
||||
.position(LatLng(charger.coordinates.lat, charger.coordinates.lng))
|
||||
.visible(false)
|
||||
.icon(
|
||||
chargerIconGenerator.getBitmapDescriptor(
|
||||
tint,
|
||||
0,
|
||||
255,
|
||||
highlight,
|
||||
fault
|
||||
)
|
||||
)
|
||||
.anchor(0.5f, 1f)
|
||||
)
|
||||
animator.animateMarkerAppear(marker, tint, highlight, fault)
|
||||
markers[marker] = charger
|
||||
@@ -709,7 +732,14 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac
|
||||
map.addMarker(
|
||||
MarkerOptions()
|
||||
.position(LatLng(cluster.coordinates.lat, cluster.coordinates.lng))
|
||||
.icon(BitmapDescriptorFactory.fromBitmap(clusterIconGenerator.makeIcon(cluster.clusterCount.toString())))
|
||||
.icon(
|
||||
map.bitmapDescriptorFactory.fromBitmap(
|
||||
clusterIconGenerator.makeIcon(
|
||||
cluster.clusterCount.toString()
|
||||
)
|
||||
)
|
||||
)
|
||||
.anchor(0.5f, 0.5f)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,8 +11,8 @@ import androidx.annotation.ColorRes
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.graphics.drawable.DrawableCompat
|
||||
import androidx.core.widget.TextViewCompat
|
||||
import com.google.android.libraries.maps.model.BitmapDescriptor
|
||||
import com.google.android.libraries.maps.model.BitmapDescriptorFactory
|
||||
import com.car2go.maps.BitmapDescriptorFactory
|
||||
import com.car2go.maps.model.BitmapDescriptor
|
||||
import com.google.maps.android.ui.IconGenerator
|
||||
import com.google.maps.android.ui.SquareTextView
|
||||
import net.vonforst.evmap.R
|
||||
@@ -41,7 +41,7 @@ class ClusterIconGenerator(context: Context) : IconGenerator(context) {
|
||||
}
|
||||
|
||||
|
||||
class ChargerIconGenerator(val context: Context) {
|
||||
class ChargerIconGenerator(val context: Context, val factory: BitmapDescriptorFactory) {
|
||||
data class BitmapData(
|
||||
val tint: Int,
|
||||
val scale: Int,
|
||||
@@ -94,7 +94,7 @@ class ChargerIconGenerator(val context: Context) {
|
||||
cachedImg
|
||||
} else {
|
||||
val bitmap = generateBitmap(data)
|
||||
val bmd = BitmapDescriptorFactory.fromBitmap(bitmap)
|
||||
val bmd = factory.fromBitmap(bitmap)
|
||||
cache.put(data, bmd)
|
||||
bmd
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import android.view.animation.BounceInterpolator
|
||||
import androidx.core.animation.addListener
|
||||
import androidx.interpolator.view.animation.FastOutLinearInInterpolator
|
||||
import androidx.interpolator.view.animation.LinearOutSlowInInterpolator
|
||||
import com.google.android.libraries.maps.model.Marker
|
||||
import com.car2go.maps.model.Marker
|
||||
import net.vonforst.evmap.R
|
||||
import net.vonforst.evmap.api.goingelectric.ChargeLocation
|
||||
import kotlin.math.max
|
||||
@@ -22,7 +22,7 @@ fun getMarkerTint(
|
||||
}
|
||||
|
||||
class MarkerAnimator(val gen: ChargerIconGenerator) {
|
||||
private val animatingMarkers = hashMapOf<String, ValueAnimator>()
|
||||
private val animatingMarkers = hashMapOf<Marker, ValueAnimator>()
|
||||
|
||||
fun animateMarkerAppear(
|
||||
marker: Marker,
|
||||
@@ -30,9 +30,9 @@ class MarkerAnimator(val gen: ChargerIconGenerator) {
|
||||
highlight: Boolean,
|
||||
fault: Boolean
|
||||
) {
|
||||
animatingMarkers[marker.id]?.let {
|
||||
animatingMarkers[marker]?.let {
|
||||
it.cancel()
|
||||
animatingMarkers.remove(marker.id)
|
||||
animatingMarkers.remove(marker)
|
||||
}
|
||||
|
||||
val anim = ValueAnimator.ofInt(0, 20).apply {
|
||||
@@ -48,15 +48,14 @@ class MarkerAnimator(val gen: ChargerIconGenerator) {
|
||||
fault = fault
|
||||
)
|
||||
)
|
||||
marker.isVisible = true
|
||||
}
|
||||
addListener(onEnd = {
|
||||
animatingMarkers.remove(marker.id)
|
||||
animatingMarkers.remove(marker)
|
||||
}, onCancel = {
|
||||
animatingMarkers.remove(marker.id)
|
||||
animatingMarkers.remove(marker)
|
||||
})
|
||||
}
|
||||
animatingMarkers[marker.id] = anim
|
||||
animatingMarkers[marker] = anim
|
||||
anim.start()
|
||||
}
|
||||
|
||||
@@ -66,9 +65,9 @@ class MarkerAnimator(val gen: ChargerIconGenerator) {
|
||||
highlight: Boolean,
|
||||
fault: Boolean
|
||||
) {
|
||||
animatingMarkers[marker.id]?.let {
|
||||
animatingMarkers[marker]?.let {
|
||||
it.cancel()
|
||||
animatingMarkers.remove(marker.id)
|
||||
animatingMarkers.remove(marker)
|
||||
}
|
||||
|
||||
val anim = ValueAnimator.ofInt(20, 0).apply {
|
||||
@@ -87,28 +86,28 @@ class MarkerAnimator(val gen: ChargerIconGenerator) {
|
||||
}
|
||||
addListener(onEnd = {
|
||||
marker.remove()
|
||||
animatingMarkers.remove(marker.id)
|
||||
animatingMarkers.remove(marker)
|
||||
}, onCancel = {
|
||||
marker.remove()
|
||||
animatingMarkers.remove(marker.id)
|
||||
animatingMarkers.remove(marker)
|
||||
})
|
||||
}
|
||||
animatingMarkers[marker.id] = anim
|
||||
animatingMarkers[marker] = anim
|
||||
anim.start()
|
||||
}
|
||||
|
||||
fun deleteMarker(marker: Marker) {
|
||||
animatingMarkers[marker.id]?.let {
|
||||
animatingMarkers[marker]?.let {
|
||||
it.cancel()
|
||||
animatingMarkers.remove(marker.id)
|
||||
animatingMarkers.remove(marker)
|
||||
}
|
||||
marker.remove()
|
||||
}
|
||||
|
||||
fun animateMarkerBounce(marker: Marker) {
|
||||
animatingMarkers[marker.id]?.let {
|
||||
animatingMarkers[marker]?.let {
|
||||
it.cancel()
|
||||
animatingMarkers.remove(marker.id)
|
||||
animatingMarkers.remove(marker)
|
||||
}
|
||||
|
||||
val anim = ValueAnimator.ofFloat(0f, 1f).apply {
|
||||
@@ -119,12 +118,12 @@ class MarkerAnimator(val gen: ChargerIconGenerator) {
|
||||
marker.setAnchor(0.5f, 1.0f + t)
|
||||
}
|
||||
addListener(onEnd = {
|
||||
animatingMarkers.remove(marker.id)
|
||||
animatingMarkers.remove(marker)
|
||||
}, onCancel = {
|
||||
animatingMarkers.remove(marker.id)
|
||||
animatingMarkers.remove(marker)
|
||||
})
|
||||
}
|
||||
animatingMarkers[marker.id] = anim
|
||||
animatingMarkers[marker] = anim
|
||||
anim.start()
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,8 @@ package net.vonforst.evmap.viewmodel
|
||||
|
||||
import android.app.Application
|
||||
import androidx.lifecycle.*
|
||||
import com.google.android.libraries.maps.GoogleMap
|
||||
import com.google.android.libraries.maps.model.LatLngBounds
|
||||
import com.car2go.maps.AnyMap
|
||||
import com.car2go.maps.model.LatLngBounds
|
||||
import com.google.android.libraries.places.api.model.Place
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
@@ -156,9 +156,9 @@ class MapViewModel(application: Application, geApiKey: String) : AndroidViewMode
|
||||
MutableLiveData<Place>()
|
||||
}
|
||||
|
||||
val mapType: MutableLiveData<Int> by lazy {
|
||||
MutableLiveData<Int>().apply {
|
||||
value = GoogleMap.MAP_TYPE_NORMAL
|
||||
val mapType: MutableLiveData<AnyMap.Type> by lazy {
|
||||
MutableLiveData<AnyMap.Type>().apply {
|
||||
value = AnyMap.Type.NORMAL
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,7 +177,7 @@ class MapViewModel(application: Application, geApiKey: String) : AndroidViewMode
|
||||
}
|
||||
}
|
||||
|
||||
fun setMapType(type: Int) {
|
||||
fun setMapType(type: AnyMap.Type) {
|
||||
mapType.value = type
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user