map node zooming works better

1.2-legacy
geeksville 2020-04-07 12:13:50 -07:00
rodzic 58e6f840ea
commit 7af7ec0843
4 zmienionych plików z 103 dodań i 78 usunięć

Wyświetl plik

@ -134,10 +134,7 @@ class MainActivity : AppCompatActivity(), Logging,
"Messages",
R.drawable.ic_twotone_message_24,
ComposeFragment("Messages", 1) { MessagesContent() }),
TabInfo(
"Settings",
R.drawable.ic_twotone_settings_applications_24,
ComposeFragment("Settings", 2) { SettingsContent() }),
TabInfo(
"Users",
R.drawable.ic_twotone_people_24,
@ -150,7 +147,11 @@ class MainActivity : AppCompatActivity(), Logging,
"Map",
R.drawable.ic_twotone_map_24,
MapFragment()
)
),
TabInfo(
"Settings",
R.drawable.ic_twotone_settings_applications_24,
BTScanFragment("Settings", 2) { SettingsContent() })
)
private
@ -301,7 +302,7 @@ class MainActivity : AppCompatActivity(), Logging,
val pager = findViewById<ViewPager2>(R.id.pager)
pager.adapter = tabsAdapter
TabLayoutMediator(tab_layout, pager) { tab, position ->
tab.text = tabInfos[position].text
// tab.text = tabInfos[position].text // I think it looks better with icons only
tab.icon = getDrawable(tabInfos[position].icon)
}.attach()
}
@ -539,7 +540,6 @@ class MainActivity : AppCompatActivity(), Logging,
}
override fun onStop() {
ScanState.stopScan()
unregisterMeshReceiver() // No point in receiving updates while the GUI is gone, we'll get them when the user launches the activity
unbindMeshService()

Wyświetl plik

@ -65,6 +65,15 @@ data class BTScanEntry(val name: String, val macAddress: String, val bonded: Boo
}
class BTScanFragment(screenName: String, id: Int, private val content: @Composable() () -> Unit) :
ComposeFragment(screenName, id, content) {
override fun onStop() {
ScanState.stopScan()
super.onStop()
}
}
@Composable
fun BTScanScreen() {
val context = ContextAmbient.current
@ -146,11 +155,6 @@ fun BTScanScreen() {
ScanState.callback = scanCallback
}
}
onDispose {
ScanState.debug("BTScan component deactivated")
ScanState.stopScan()
}
}
Column {

Wyświetl plik

@ -7,7 +7,6 @@ import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.compose.Composable
import androidx.ui.core.setContent
import com.geeksville.android.Logging
fun androidx.fragment.app.Fragment.setComposable(
id: Int,
@ -27,9 +26,12 @@ fun androidx.fragment.app.Fragment.setComposable(
}
class ComposeFragment(screenName: String, id: Int, private val content: @Composable() () -> Unit) :
ScreenFragment(screenName),
Logging {
open class ComposeFragment(
screenName: String,
id: Int,
private val content: @Composable() () -> Unit
) :
ScreenFragment(screenName) {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?

Wyświetl plik

@ -17,6 +17,7 @@ import com.mapbox.mapboxsdk.camera.CameraUpdateFactory
import com.mapbox.mapboxsdk.geometry.LatLng
import com.mapbox.mapboxsdk.geometry.LatLngBounds
import com.mapbox.mapboxsdk.maps.MapView
import com.mapbox.mapboxsdk.maps.MapboxMap
import com.mapbox.mapboxsdk.maps.Style
import com.mapbox.mapboxsdk.style.expressions.Expression
import com.mapbox.mapboxsdk.style.layers.Property
@ -28,7 +29,81 @@ import com.mapbox.mapboxsdk.style.sources.GeoJsonSource
class MapFragment : ScreenFragment("Map"), Logging {
private val nodeSourceId = "node-positions"
private val nodeLayerId = "node-layer"
private val labelLayerId = "label-layer"
private val markerImageId = "my-marker-image"
private val nodePositions = GeoJsonSource(nodeSourceId)
private val nodeLayer = SymbolLayer(nodeLayerId, nodeSourceId).withProperties(
iconImage(markerImageId),
iconAnchor(Property.ICON_ANCHOR_BOTTOM),
iconAllowOverlap(true)
)
private val labelLayer = SymbolLayer(labelLayerId, nodeSourceId).withProperties(
textField(Expression.get("name")),
textSize(12f),
textColor(Color.RED),
textVariableAnchor(arrayOf(TEXT_ANCHOR_TOP)),
textJustify(TEXT_JUSTIFY_AUTO),
textAllowOverlap(true)
)
private fun nodesWithPosition() = NodeDB.nodes.values.filter { it.validPosition != null }
/**
* Using the latest nodedb, generate geojson features
*/
private fun getCurrentNodes(): FeatureCollection {
// Find all nodes with valid locations
val locations = nodesWithPosition().map { node ->
val p = node.position!!
debug("Showing on map: $node")
val f = Feature.fromGeometry(
Point.fromLngLat(
p.longitude,
p.latitude
)
)
node.user?.let {
f.addStringProperty("name", it.longName)
}
f
}
return FeatureCollection.fromFeatures(locations)
}
private fun zoomToNodes(map: MapboxMap) {
val nodes = nodesWithPosition()
if (nodes.isNotEmpty()) {
val update = if (nodes.size >= 2) {
// Multiple nodes, make them all fit on the map view
val bounds = LatLngBounds.Builder()
// Add all positions
bounds.includes(nodes.map { it.position!! }
.map { LatLng(it.latitude, it.longitude) })
CameraUpdateFactory.newLatLngBounds(bounds.build(), 150)
} else {
// Only one node, just zoom in on it
val it = nodes[0].position!!
val cameraPos = CameraPosition.Builder().target(
LatLng(it.latitude, it.longitude)
).zoom(9.0).build()
CameraUpdateFactory.newCameraPosition(cameraPos)
}
map.animateCamera(update, 1000)
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
@ -44,48 +119,9 @@ class MapFragment : ScreenFragment("Map"), Logging {
mapView.getMapAsync { map ->
// Find all nodes with valid locations
val nodesWithPosition = NodeDB.nodes.values.filter { it.validPosition != null }
val locations = nodesWithPosition.map { node ->
val p = node.position!!
debug("Showing on map: $node")
val f = Feature.fromGeometry(
Point.fromLngLat(
p.longitude,
p.latitude
)
)
node.user?.let {
f.addStringProperty("name", it.longName)
}
f
}
val nodeSourceId = "node-positions"
val nodeLayerId = "node-layer"
val labelLayerId = "label-layer"
val markerImageId = "my-marker-image"
val nodePositions =
GeoJsonSource(nodeSourceId, FeatureCollection.fromFeatures(locations))
// val markerIcon = BitmapFactory.decodeResource(context.resources, R.drawable.ic_twotone_person_pin_24)
val markerIcon = activity!!.getDrawable(R.drawable.ic_twotone_person_pin_24)!!
val nodeLayer = SymbolLayer(nodeLayerId, nodeSourceId).withProperties(
iconImage(markerImageId),
iconAnchor(Property.ICON_ANCHOR_BOTTOM),
iconAllowOverlap(true)
)
val labelLayer = SymbolLayer(labelLayerId, nodeSourceId).withProperties(
textField(Expression.get("name")),
textSize(12f),
textColor(Color.RED),
textVariableAnchor(arrayOf(TEXT_ANCHOR_TOP)),
textJustify(TEXT_JUSTIFY_AUTO),
textAllowOverlap(true)
)
map.setStyle(Style.OUTDOORS) { style ->
style.addSource(nodePositions)
style.addImage(markerImageId, markerIcon)
@ -95,28 +131,6 @@ class MapFragment : ScreenFragment("Map"), Logging {
//map.uiSettings.isScrollGesturesEnabled = true
//map.uiSettings.isZoomGesturesEnabled = true
if (nodesWithPosition.isNotEmpty()) {
val update = if (nodesWithPosition.size >= 2) {
// Multiple nodes, make them all fit on the map view
val bounds = LatLngBounds.Builder()
// Add all positions
bounds.includes(nodesWithPosition.map { it.position!! }
.map { LatLng(it.latitude, it.longitude) })
CameraUpdateFactory.newLatLngBounds(bounds.build(), 150)
} else {
// Only one node, just zoom in on it
val it = nodesWithPosition[0].position!!
val cameraPos = CameraPosition.Builder().target(
LatLng(it.latitude, it.longitude)
).zoom(9.0).build()
CameraUpdateFactory.newCameraPosition(cameraPos)
}
map.animateCamera(update, 1000)
}
}
}
@ -138,6 +152,11 @@ class MapFragment : ScreenFragment("Map"), Logging {
override fun onResume() {
super.onResume()
mapView.onResume()
mapView.getMapAsync { map ->
nodePositions.setGeoJson(getCurrentNodes()) // Update node positions
zoomToNodes(map)
}
}
override fun onDestroy() {