Adding static pin at the center of the map

This commit is contained in:
Maxime Naturel 2022-03-04 15:32:36 +01:00
parent 9256b5671b
commit a1d155df71
8 changed files with 67 additions and 17 deletions

View File

@ -123,7 +123,7 @@ class LocationPreviewFragment @Inject constructor(
views.mapView.render( views.mapView.render(
MapState( MapState(
zoomOnlyOnce = true, zoomOnlyOnce = true,
pinLocationData = location, userLocationData = location,
pinId = args.locationOwnerId ?: DEFAULT_PIN_ID, pinId = args.locationOwnerId ?: DEFAULT_PIN_ID,
pinDrawable = pinDrawable pinDrawable = pinDrawable
) )

View File

@ -16,6 +16,7 @@
package im.vector.app.features.location package im.vector.app.features.location
import android.graphics.drawable.Drawable
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
@ -52,6 +53,7 @@ class LocationSharingFragment @Inject constructor(
private var mapView: WeakReference<MapView>? = null private var mapView: WeakReference<MapView>? = null
private var hasRenderedUserAvatar = false private var hasRenderedUserAvatar = false
private var hasUpdatedPin = false
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentLocationSharingBinding { override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentLocationSharingBinding {
return FragmentLocationSharingBinding.inflate(inflater, container, false) return FragmentLocationSharingBinding.inflate(inflater, container, false)
@ -116,7 +118,11 @@ class LocationSharingFragment @Inject constructor(
override fun invalidate() = withState(viewModel) { state -> override fun invalidate() = withState(viewModel) { state ->
updateMap(state) updateMap(state)
updateUserAvatar(state.userItem) updateUserAvatar(state.userItem)
views.shareLocationGpsLoading.isGone = state.lastKnownLocation != null if(!hasUpdatedPin && state.pinDrawable != null) {
hasUpdatedPin = true
updateStaticPin(state.pinDrawable)
}
views.shareLocationGpsLoading.isGone = state.lastKnownUserLocation != null
} }
private fun handleLocationNotAvailableError() { private fun handleLocationNotAvailableError() {
@ -132,10 +138,14 @@ class LocationSharingFragment @Inject constructor(
private fun initOptionsPicker() { private fun initOptionsPicker() {
// TODO // TODO
// move pin creation into the Fragment
// create a useCase to compare pinnedLocation and userLocation
// change the pin dynamically depending on the current chosen location: cf. LocationPinProvider // change the pin dynamically depending on the current chosen location: cf. LocationPinProvider
// make the pin stay at the center of the map: selected location is the center of the map // reset map to user location when clicking on reset icon
// need changes in the event sent when this is a pin drop location? // need changes in the event sent when this is a pin drop location?
// need changes in the parsing of events when receiving pin drop location?: should it be shown with user avatar or with pin? // need changes in the parsing of events when receiving pin drop location?: should it be shown with user avatar or with pin?
// set no option at start
views.shareLocationOptionsPicker.render()
views.shareLocationOptionsPicker.optionPinned.debouncedClicks { views.shareLocationOptionsPicker.optionPinned.debouncedClicks {
// TODO // TODO
} }
@ -148,8 +158,10 @@ class LocationSharingFragment @Inject constructor(
} }
private fun updateMap(state: LocationSharingViewState) { private fun updateMap(state: LocationSharingViewState) {
// first update the options view // first, update the options view
if (state.isUserLocation) { // TODO compute distance between userLocation and location at center of map
val isUserLocation = true
if (isUserLocation) {
// TODO activate USER_LIVE option when implemented // TODO activate USER_LIVE option when implemented
views.shareLocationOptionsPicker.render( views.shareLocationOptionsPicker.render(
LocationSharingOption.USER_CURRENT LocationSharingOption.USER_CURRENT
@ -159,10 +171,13 @@ class LocationSharingFragment @Inject constructor(
LocationSharingOption.PINNED LocationSharingOption.PINNED
) )
} }
val mapState = state // then, update the map using the height of the options view after it has been rendered
.toMapState() views.shareLocationOptionsPicker.post {
.copy(logoMarginBottom = views.shareLocationOptionsPicker.height) val mapState = state
views.mapView.render(mapState) .toMapState()
.copy(logoMarginBottom = views.shareLocationOptionsPicker.height)
views.mapView.render(mapState)
}
} }
private fun updateUserAvatar(userItem: MatrixItem.UserItem?) { private fun updateUserAvatar(userItem: MatrixItem.UserItem?) {
@ -174,4 +189,8 @@ class LocationSharingFragment @Inject constructor(
views.shareLocationOptionsPicker.optionUserCurrent.setIconBackgroundTint(tintColor) views.shareLocationOptionsPicker.optionUserCurrent.setIconBackgroundTint(tintColor)
} }
} }
private fun updateStaticPin(drawable: Drawable) {
views.shareLocationPin.setImageDrawable(drawable)
}
} }

View File

@ -76,7 +76,7 @@ class LocationSharingViewModel @AssistedInject constructor(
} }
private fun handleShareLocation() = withState { state -> private fun handleShareLocation() = withState { state ->
state.lastKnownLocation?.let { location -> state.lastKnownUserLocation?.let { location ->
room.sendLocation( room.sendLocation(
latitude = location.latitude, latitude = location.latitude,
longitude = location.longitude, longitude = location.longitude,
@ -90,7 +90,7 @@ class LocationSharingViewModel @AssistedInject constructor(
override fun onLocationUpdate(locationData: LocationData) { override fun onLocationUpdate(locationData: LocationData) {
setState { setState {
copy(lastKnownLocation = locationData) copy(lastKnownUserLocation = locationData)
} }
} }

View File

@ -30,9 +30,9 @@ enum class LocationSharingMode(@StringRes val titleRes: Int) {
data class LocationSharingViewState( data class LocationSharingViewState(
val roomId: String, val roomId: String,
val mode: LocationSharingMode, val mode: LocationSharingMode,
val isUserLocation: Boolean = false,
val userItem: MatrixItem.UserItem? = null, val userItem: MatrixItem.UserItem? = null,
val lastKnownLocation: LocationData? = null, val lastKnownUserLocation: LocationData? = null,
// TODO move pin drawable creation into the view?
val pinDrawable: Drawable? = null val pinDrawable: Drawable? = null
) : MavericksState { ) : MavericksState {
@ -44,7 +44,7 @@ data class LocationSharingViewState(
fun LocationSharingViewState.toMapState() = MapState( fun LocationSharingViewState.toMapState() = MapState(
zoomOnlyOnce = true, zoomOnlyOnce = true,
pinLocationData = lastKnownLocation, userLocationData = lastKnownUserLocation,
pinId = DEFAULT_PIN_ID, pinId = DEFAULT_PIN_ID,
pinDrawable = pinDrawable pinDrawable = pinDrawable
) )

View File

@ -21,7 +21,7 @@ import androidx.annotation.Px
data class MapState( data class MapState(
val zoomOnlyOnce: Boolean, val zoomOnlyOnce: Boolean,
val pinLocationData: LocationData? = null, val userLocationData: LocationData? = null,
val pinId: String, val pinId: String,
val pinDrawable: Drawable? = null, val pinDrawable: Drawable? = null,
@Px val logoMarginBottom: Int = 0 @Px val logoMarginBottom: Int = 0

View File

@ -70,6 +70,9 @@ class MapTilerMapView @JvmOverloads constructor(
safeMapRefs.map.uiSettings.setLogoMargins(0, 0, 0, state.logoMarginBottom) safeMapRefs.map.uiSettings.setLogoMargins(0, 0, 0, state.logoMarginBottom)
// TODO display a dot pin for userLocation instead of pinDrawable
// TODO add reset to user location button
// TODO check conflict of rendering with preview location in timeline
state.pinDrawable?.let { pinDrawable -> state.pinDrawable?.let { pinDrawable ->
if (!safeMapRefs.style.isFullyLoaded || if (!safeMapRefs.style.isFullyLoaded ||
safeMapRefs.style.getImage(state.pinId) == null) { safeMapRefs.style.getImage(state.pinId) == null) {
@ -77,7 +80,7 @@ class MapTilerMapView @JvmOverloads constructor(
} }
} }
state.pinLocationData?.let { locationData -> state.userLocationData?.let { locationData ->
if (!initZoomDone || !state.zoomOnlyOnce) { if (!initZoomDone || !state.zoomOnlyOnce) {
zoomToLocation(locationData.latitude, locationData.longitude) zoomToLocation(locationData.latitude, locationData.longitude)
initZoomDone = true initZoomDone = true
@ -100,4 +103,13 @@ class MapTilerMapView @JvmOverloads constructor(
.zoom(INITIAL_MAP_ZOOM_IN_PREVIEW) .zoom(INITIAL_MAP_ZOOM_IN_PREVIEW)
.build() .build()
} }
fun getLocationOfMapCenter(): LocationData? =
mapRefs?.map?.cameraPosition?.target?.let { target ->
LocationData(
latitude = target.latitude,
longitude = target.longitude,
uncertainty = null
)
}
} }

View File

@ -10,12 +10,30 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="0dp" android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:mapbox_renderTextureMode="true" app:mapbox_renderTextureMode="true"
tools:background="#4F00" /> tools:background="#4F00" />
<ImageView
android:id="@+id/shareLocationPin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/a11y_location_share_pin_on_map"
app:layout_constraintBottom_toTopOf="@id/shareLocationMapCenter"
app:layout_constraintEnd_toEndOf="@id/mapView"
app:layout_constraintStart_toStartOf="@id/mapView" />
<ViewStub
android:id="@+id/shareLocationMapCenter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="@id/mapView"
app:layout_constraintEnd_toEndOf="@id/mapView"
app:layout_constraintStart_toStartOf="@id/mapView"
app:layout_constraintTop_toTopOf="@id/mapView" />
<im.vector.app.features.location.option.LocationSharingOptionPickerView <im.vector.app.features.location.option.LocationSharingOptionPickerView
android:id="@+id/shareLocationOptionsPicker" android:id="@+id/shareLocationOptionsPicker"
android:layout_width="0dp" android:layout_width="0dp"

View File

@ -2929,6 +2929,7 @@
<string name="a11y_static_map_image">Map</string> <string name="a11y_static_map_image">Map</string>
<!-- TODO delete --> <!-- TODO delete -->
<string name="location_share" tools:ignore="UnusedResources">Share location</string> <string name="location_share" tools:ignore="UnusedResources">Share location</string>
<string name="a11y_location_share_pin_on_map">Pin of selected location on map</string>
<string name="location_share_option_user_current">Share my current location</string> <string name="location_share_option_user_current">Share my current location</string>
<string name="a11y_location_share_option_user_current_icon">Share my current location</string> <string name="a11y_location_share_option_user_current_icon">Share my current location</string>
<string name="location_share_option_user_live">Share live location</string> <string name="location_share_option_user_live">Share live location</string>