polish location map and move to native view bindings

Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
This commit is contained in:
Andy Scherzinger 2021-06-10 00:29:03 +02:00
parent 9f8a98ba07
commit 73e0b4e719
No known key found for this signature in database
GPG Key ID: 6CADC7E3523C308B
4 changed files with 103 additions and 124 deletions

View File

@ -32,43 +32,39 @@ import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.text.InputType import android.text.InputType
import android.util.Log import android.util.Log
import android.view.LayoutInflater
import android.view.Menu import android.view.Menu
import android.view.MenuInflater import android.view.MenuInflater
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.EditorInfo import android.view.inputmethod.EditorInfo
import android.widget.LinearLayout
import android.widget.TextView
import android.widget.Toast import android.widget.Toast
import androidx.appcompat.widget.SearchView import androidx.appcompat.widget.SearchView
import androidx.cardview.widget.CardView
import androidx.core.content.PermissionChecker import androidx.core.content.PermissionChecker
import androidx.core.content.res.ResourcesCompat import androidx.core.content.res.ResourcesCompat
import androidx.core.view.MenuItemCompat import androidx.core.view.MenuItemCompat
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import autodagger.AutoInjector import autodagger.AutoInjector
import butterknife.BindView
import com.bluelinelabs.conductor.RouterTransaction import com.bluelinelabs.conductor.RouterTransaction
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler
import com.nextcloud.talk.R import com.nextcloud.talk.R
import com.nextcloud.talk.api.NcApi import com.nextcloud.talk.api.NcApi
import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.application.NextcloudTalkApplication
import com.nextcloud.talk.controllers.base.BaseController import com.nextcloud.talk.controllers.base.NewBaseController
import com.nextcloud.talk.controllers.util.viewBinding
import com.nextcloud.talk.databinding.ControllerLocationBinding
import com.nextcloud.talk.models.json.generic.GenericOverall import com.nextcloud.talk.models.json.generic.GenericOverall
import com.nextcloud.talk.utils.ApiUtils import com.nextcloud.talk.utils.ApiUtils
import com.nextcloud.talk.utils.DisplayUtils import com.nextcloud.talk.utils.DisplayUtils
import com.nextcloud.talk.utils.bundle.BundleKeys import com.nextcloud.talk.utils.bundle.BundleKeys
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ROOM_TOKEN import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ROOM_TOKEN
import com.nextcloud.talk.utils.database.user.UserUtils import com.nextcloud.talk.utils.database.user.UserUtils
import com.nextcloud.talk.utils.preferences.AppPreferences
import fr.dudie.nominatim.client.JsonNominatimClient import fr.dudie.nominatim.client.JsonNominatimClient
import fr.dudie.nominatim.model.Address import fr.dudie.nominatim.model.Address
import io.reactivex.Observer import io.reactivex.Observer
import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers import io.reactivex.schedulers.Schedulers
import kotlinx.android.synthetic.main.controller_location.view.*
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -87,7 +83,6 @@ import org.osmdroid.events.ScrollEvent
import org.osmdroid.events.ZoomEvent import org.osmdroid.events.ZoomEvent
import org.osmdroid.tileprovider.tilesource.TileSourceFactory import org.osmdroid.tileprovider.tilesource.TileSourceFactory
import org.osmdroid.util.GeoPoint import org.osmdroid.util.GeoPoint
import org.osmdroid.views.MapView
import org.osmdroid.views.overlay.CopyrightOverlay import org.osmdroid.views.overlay.CopyrightOverlay
import org.osmdroid.views.overlay.mylocation.GpsMyLocationProvider import org.osmdroid.views.overlay.mylocation.GpsMyLocationProvider
import org.osmdroid.views.overlay.mylocation.MyLocationNewOverlay import org.osmdroid.views.overlay.mylocation.MyLocationNewOverlay
@ -95,10 +90,14 @@ import javax.inject.Inject
@AutoInjector(NextcloudTalkApplication::class) @AutoInjector(NextcloudTalkApplication::class)
class LocationPickerController(args: Bundle) : class LocationPickerController(args: Bundle) :
BaseController(args), NewBaseController(
R.layout.controller_location,
args
),
SearchView.OnQueryTextListener, SearchView.OnQueryTextListener,
LocationListener, LocationListener,
GeocodingController.GeocodingResultListener { GeocodingController.GeocodingResultListener {
private val binding: ControllerLocationBinding by viewBinding(ControllerLocationBinding::bind)
@Inject @Inject
lateinit var ncApi: NcApi lateinit var ncApi: NcApi
@ -106,34 +105,6 @@ class LocationPickerController(args: Bundle) :
@Inject @Inject
lateinit var userUtils: UserUtils lateinit var userUtils: UserUtils
@Inject
@JvmField
var appPreferences: AppPreferences? = null
@Inject
@JvmField
var context: Context? = null
@BindView(R.id.map)
@JvmField
var map: MapView? = null
@BindView(R.id.ic_center_map)
@JvmField
var btCenterMap: CardView? = null
@BindView(R.id.share_location)
@JvmField
var shareLocation: LinearLayout? = null
@BindView(R.id.place_name)
@JvmField
var placeName: TextView? = null
@BindView(R.id.share_location_description)
@JvmField
var shareLocationDescription: TextView? = null
var nominatimClient: JsonNominatimClient? = null var nominatimClient: JsonNominatimClient? = null
var roomToken: String? var roomToken: String?
@ -160,10 +131,6 @@ class LocationPickerController(args: Bundle) :
roomToken = args.getString(KEY_ROOM_TOKEN) roomToken = args.getString(KEY_ROOM_TOKEN)
} }
override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
return inflater.inflate(R.layout.controller_location, container, false)
}
override fun onAttach(view: View) { override fun onAttach(view: View) {
super.onAttach(view) super.onAttach(view)
initMap() initMap()
@ -188,20 +155,20 @@ class LocationPickerController(args: Bundle) :
override fun onPrepareOptionsMenu(menu: Menu) { override fun onPrepareOptionsMenu(menu: Menu) {
super.onPrepareOptionsMenu(menu) super.onPrepareOptionsMenu(menu)
hideSearchBar() showToolbar()
actionBar.setIcon(ColorDrawable(resources!!.getColor(android.R.color.transparent))) actionBar?.setIcon(ColorDrawable(resources!!.getColor(android.R.color.transparent)))
actionBar.title = context!!.getString(R.string.nc_share_location) actionBar?.title = context!!.getString(R.string.nc_share_location)
} }
override fun onViewBound(view: View) { override fun onViewBound(view: View) {
setLocationDescription(false, receivedChosenGeocodingResult) setLocationDescription(false, receivedChosenGeocodingResult)
shareLocation?.isClickable = false binding.shareLocation.isClickable = false
shareLocation?.setOnClickListener { binding.shareLocation.setOnClickListener {
if (readyToShareLocation) { if (readyToShareLocation) {
shareLocation( shareLocation(
map?.mapCenter?.latitude, binding.map.mapCenter?.latitude,
map?.mapCenter?.longitude, binding.map.mapCenter?.longitude,
placeName?.text.toString() binding.placeName.text.toString()
) )
} else { } else {
Log.w(TAG, "readyToShareLocation was false while user tried to share location.") Log.w(TAG, "readyToShareLocation was false while user tried to share location.")
@ -214,14 +181,14 @@ class LocationPickerController(args: Bundle) :
val searchManager = activity!!.getSystemService(Context.SEARCH_SERVICE) as SearchManager val searchManager = activity!!.getSystemService(Context.SEARCH_SERVICE) as SearchManager
if (searchItem != null) { if (searchItem != null) {
searchView = MenuItemCompat.getActionView(searchItem) as SearchView searchView = MenuItemCompat.getActionView(searchItem) as SearchView
searchView?.setMaxWidth(Int.MAX_VALUE) searchView?.maxWidth = Int.MAX_VALUE
searchView?.setInputType(InputType.TYPE_TEXT_VARIATION_FILTER) searchView?.inputType = InputType.TYPE_TEXT_VARIATION_FILTER
var imeOptions = EditorInfo.IME_ACTION_DONE or EditorInfo.IME_FLAG_NO_FULLSCREEN var imeOptions = EditorInfo.IME_ACTION_DONE or EditorInfo.IME_FLAG_NO_FULLSCREEN
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && appPreferences!!.isKeyboardIncognito) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && appPreferences!!.isKeyboardIncognito) {
imeOptions = imeOptions or EditorInfo.IME_FLAG_NO_PERSONALIZED_LEARNING imeOptions = imeOptions or EditorInfo.IME_FLAG_NO_PERSONALIZED_LEARNING
} }
searchView?.setImeOptions(imeOptions) searchView?.imeOptions = imeOptions
searchView?.setQueryHint(resources!!.getString(R.string.nc_search)) searchView?.queryHint = resources!!.getString(R.string.nc_search)
searchView?.setSearchableInfo(searchManager.getSearchableInfo(activity!!.componentName)) searchView?.setSearchableInfo(searchManager.getSearchableInfo(activity!!.componentName))
searchView?.setOnQueryTextListener(this) searchView?.setOnQueryTextListener(this)
} }
@ -251,9 +218,9 @@ class LocationPickerController(args: Bundle) :
requestFineLocationPermission() requestFineLocationPermission()
} }
map?.setTileSource(TileSourceFactory.MAPNIK) binding.map.setTileSource(TileSourceFactory.MAPNIK)
map?.onResume() binding.map.onResume()
locationManager = activity!!.getSystemService(Context.LOCATION_SERVICE) as LocationManager locationManager = activity!!.getSystemService(Context.LOCATION_SERVICE) as LocationManager
try { try {
@ -262,19 +229,19 @@ class LocationPickerController(args: Bundle) :
} }
val copyrightOverlay = CopyrightOverlay(context) val copyrightOverlay = CopyrightOverlay(context)
map?.overlays?.add(copyrightOverlay) binding.map.overlays?.add(copyrightOverlay)
map?.setMultiTouchControls(true) binding.map.setMultiTouchControls(true)
map?.isTilesScaledToDpi = true binding.map.isTilesScaledToDpi = true
locationOverlay = MyLocationNewOverlay(GpsMyLocationProvider(context), map) locationOverlay = MyLocationNewOverlay(GpsMyLocationProvider(context), binding.map)
locationOverlay.enableMyLocation() locationOverlay.enableMyLocation()
locationOverlay.setPersonHotspot(20.0F,20.0F) locationOverlay.setPersonHotspot(20.0F,20.0F)
locationOverlay.setPersonIcon( locationOverlay.setPersonIcon(
DisplayUtils.getBitmap(ResourcesCompat.getDrawable(resources!!, R.drawable.current_location_circle, null))) DisplayUtils.getBitmap(ResourcesCompat.getDrawable(resources!!, R.drawable.current_location_circle, null)))
map?.overlays?.add(locationOverlay) binding.map.overlays?.add(locationOverlay)
val mapController = map?.controller val mapController = binding.map.controller
if (receivedChosenGeocodingResult) { if (receivedChosenGeocodingResult) {
mapController?.setZoom(14.0) mapController?.setZoom(14.0)
@ -297,25 +264,29 @@ class LocationPickerController(args: Bundle) :
mapController?.setCenter(GeoPoint(geocodedLat, geocodedLon)) mapController?.setCenter(GeoPoint(geocodedLat, geocodedLon))
} }
btCenterMap?.setOnClickListener { binding.centerMapButton.setOnClickListener {
mapController?.animateTo(myLocation) mapController?.animateTo(myLocation)
moveToCurrentLocationWasClicked = true moveToCurrentLocationWasClicked = true
} }
map?.addMapListener( binding.map.addMapListener(
DelayedMapListener( DelayedMapListener(
object : MapListener { object : MapListener {
override fun onScroll(paramScrollEvent: ScrollEvent): Boolean { override fun onScroll(paramScrollEvent: ScrollEvent): Boolean {
if (moveToCurrentLocationWasClicked) { when {
setLocationDescription(true, false) moveToCurrentLocationWasClicked -> {
moveToCurrentLocationWasClicked = false setLocationDescription(isGpsLocation = true, isGeocodedResult = false)
} else if (receivedChosenGeocodingResult) { moveToCurrentLocationWasClicked = false
shareLocation?.isClickable = true }
setLocationDescription(false, true) receivedChosenGeocodingResult -> {
receivedChosenGeocodingResult = false binding.shareLocation.isClickable = true
} else { setLocationDescription(isGpsLocation = false, isGeocodedResult = true)
shareLocation?.isClickable = true receivedChosenGeocodingResult = false
setLocationDescription(false, false) }
else -> {
binding.shareLocation.isClickable = true
setLocationDescription(isGpsLocation = false, isGeocodedResult = false)
}
} }
readyToShareLocation = true readyToShareLocation = true
return true return true
@ -331,19 +302,19 @@ class LocationPickerController(args: Bundle) :
private fun setLocationDescription(isGpsLocation: Boolean, isGeocodedResult: Boolean) { private fun setLocationDescription(isGpsLocation: Boolean, isGeocodedResult: Boolean) {
when { when {
isGpsLocation -> { isGpsLocation -> {
shareLocationDescription?.text = context!!.getText(R.string.nc_share_current_location) binding.shareLocationDescription.text = context!!.getText(R.string.nc_share_current_location)
placeName?.visibility = View.GONE binding.placeName.visibility = View.GONE
placeName?.text = "" binding.placeName.text = ""
} }
isGeocodedResult -> { isGeocodedResult -> {
shareLocationDescription?.text = context!!.getText(R.string.nc_share_this_location) binding.shareLocationDescription.text = context!!.getText(R.string.nc_share_this_location)
placeName?.visibility = View.VISIBLE binding.placeName.visibility = View.VISIBLE
placeName?.text = geocodedName binding.placeName.text = geocodedName
} }
else -> { else -> {
shareLocationDescription?.text = context!!.getText(R.string.nc_share_this_location) binding.shareLocationDescription.text = context!!.getText(R.string.nc_share_this_location)
placeName?.visibility = View.GONE binding.placeName.visibility = View.GONE
placeName?.text = "" binding.placeName.text = ""
} }
} }
} }
@ -351,7 +322,7 @@ class LocationPickerController(args: Bundle) :
private fun shareLocation(selectedLat: Double?, selectedLon: Double?, locationName: String?) { private fun shareLocation(selectedLat: Double?, selectedLon: Double?, locationName: String?) {
if (selectedLat != null || selectedLon != null) { if (selectedLat != null || selectedLon != null) {
var name = locationName val name = locationName
if (name.isNullOrEmpty()) { if (name.isNullOrEmpty()) {
initGeocoder() initGeocoder()
searchPlaceNameForCoordinates(selectedLat!!, selectedLon!!) searchPlaceNameForCoordinates(selectedLat!!, selectedLon!!)

View File

@ -3,6 +3,8 @@
~ Nextcloud Talk application ~ Nextcloud Talk application
~ ~
~ @author Marcel Hibbe ~ @author Marcel Hibbe
~ @author Andy Scherzinger
~ Copyright (C) 2021 Andy Scherzinger <info@andy-scherzinger.de>
~ Copyright (C) 2021 Marcel Hibbe <dev@mhibbe.de> ~ Copyright (C) 2021 Marcel Hibbe <dev@mhibbe.de>
~ ~
~ This program is free software: you can redistribute it and/or modify ~ This program is free software: you can redistribute it and/or modify
@ -32,29 +34,32 @@
android:layout_height="0dp" android:layout_height="0dp"
android:layout_weight="1"> android:layout_weight="1">
<org.osmdroid.views.MapView android:id="@+id/map" <org.osmdroid.views.MapView
android:id="@+id/map"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="fill_parent" /> android:layout_height="fill_parent" />
<androidx.cardview.widget.CardView <com.google.android.material.button.MaterialButton
android:id="@+id/ic_center_map" android:id="@+id/centerMapButton"
android:layout_alignParentTop="true" style="@style/Widget.AppTheme.Button.IconButton"
android:layout_alignParentEnd="true"
android:layout_width="50dp" android:layout_width="50dp"
android:layout_height="50dp" android:layout_height="50dp"
android:layout_margin="5dp" android:layout_alignParentTop="true"
android:elevation="10dp" android:layout_alignParentEnd="true"
app:cardCornerRadius="25dp" android:layout_margin="8dp"
app:cardBackgroundColor="@color/appbar"> android:insetLeft="0dp"
android:insetTop="0dp"
<ImageView android:insetRight="0dp"
android:id="@+id/roundedImageView" android:insetBottom="0dp"
android:layout_width="25dp" android:padding="0dp"
android:layout_height="25dp" app:backgroundTint="@color/bg_default_semitransparent"
android:src="@drawable/ic_baseline_gps_fixed_24" app:cornerRadius="@dimen/button_corner_radius"
android:layout_gravity="center" app:elevation="0dp"
/> app:icon="@drawable/ic_baseline_gps_fixed_24"
</androidx.cardview.widget.CardView> app:iconGravity="textStart"
app:iconPadding="0dp"
app:iconSize="24dp"
app:iconTint="@color/high_emphasis_text" />
<View <View
android:id="@+id/locationpicker_anchor" android:id="@+id/locationpicker_anchor"
@ -65,42 +70,43 @@
<ImageView <ImageView
android:layout_width="30dp" android:layout_width="30dp"
android:layout_height="50dp" android:layout_height="50dp"
android:src="@drawable/ic_baseline_location_on_red_24" android:layout_above="@id/locationpicker_anchor"
android:layout_centerHorizontal="true" android:layout_centerHorizontal="true"
android:layout_marginBottom="-10dp" android:layout_marginBottom="-10dp"
android:layout_above="@id/locationpicker_anchor" android:contentDescription="@string/nc_location_current_position_description"
android:contentDescription="@string/nc_location_current_position_description"> android:src="@drawable/ic_baseline_location_on_red_24" />
</ImageView>
</RelativeLayout> </RelativeLayout>
<LinearLayout <LinearLayout
android:id="@+id/share_location" android:id="@+id/share_location"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="60dp" android:layout_height="72dp"
android:orientation="horizontal"> android:orientation="horizontal">
<ImageView <ImageView
android:layout_width="wrap_content" android:id="@+id/roundedImageView"
android:layout_height="match_parent" android:layout_width="@dimen/avatar_size"
android:height="60dp" android:layout_height="@dimen/avatar_size"
android:minWidth="50dp" android:layout_gravity="top"
android:padding="10dp" android:layout_margin="@dimen/standard_margin"
android:textAlignment="textStart" android:contentDescription="@null"
app:srcCompat="@drawable/ic_baseline_location_on_24"> android:src="@drawable/ic_circular_location" />
</ImageView>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:layout_gravity="center_vertical"
android:layout_gravity="center_vertical"> android:orientation="vertical">
<TextView <TextView
android:id="@+id/share_location_description" android:id="@+id/share_location_description"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="0dp"
android:layout_weight="1" android:layout_weight="1"
android:textSize="20sp" android:textColor="@color/high_emphasis_text"
tools:text="Share this location"> android:textSize="16sp"
</TextView> tools:text="Share this location" />
<TextView <TextView
android:id="@+id/place_name" android:id="@+id/place_name"
android:layout_width="match_parent" android:layout_width="match_parent"
@ -108,11 +114,11 @@
android:layout_weight="1" android:layout_weight="1"
android:ellipsize="end" android:ellipsize="end"
android:maxLines="1" android:maxLines="1"
tools:text="Brandenburg, Germany"> android:textColor="@color/medium_emphasis_text"
</TextView> android:textSize="14sp"
tools:text="Brandenburg, Germany" />
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>

View File

@ -39,6 +39,7 @@
<color name="low_emphasis_text">#61ffffff</color> <color name="low_emphasis_text">#61ffffff</color>
<color name="bg_default">#121212</color> <color name="bg_default">#121212</color>
<color name="bg_default_semitransparent">#99121212</color>
<color name="bg_inverse">@color/grey950</color> <color name="bg_inverse">@color/grey950</color>
<color name="fg_default">#FFFFFF</color> <color name="fg_default">#FFFFFF</color>

View File

@ -67,6 +67,7 @@
<color name="fg_inverse">#FFFFFF</color> <color name="fg_inverse">#FFFFFF</color>
<color name="bg_default">#FFFFFF</color> <color name="bg_default">#FFFFFF</color>
<color name="bg_default_semitransparent">#99FFFFFF</color>
<color name="bg_inverse">@color/grey950</color> <color name="bg_inverse">@color/grey950</color>
<color name="bg_dark_mention_chips">#333333</color> <color name="bg_dark_mention_chips">#333333</color>