Add GPS and map-based feature creation to CreatePage with attribute validation, MapViewModel enhancements for feature handling, and dependency updates.
This commit is contained in:
@@ -66,6 +66,8 @@ dependencies {
|
||||
androidTestImplementation(libs.androidx.compose.ui.test.junit4)
|
||||
debugImplementation(libs.androidx.compose.ui.tooling)
|
||||
debugImplementation(libs.androidx.compose.ui.test.manifest)
|
||||
implementation("androidx.compose.material:material-icons-extended:1.7.8")
|
||||
implementation("com.google.android.gms:play-services-location:21.3.0")
|
||||
|
||||
// ArcGIS Maps for Kotlin - SDK dependency
|
||||
implementation(libs.arcgis.maps.kotlin)
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.arcgismaps.data.ArcGISFeature
|
||||
import com.arcgismaps.data.CodedValueDomain
|
||||
import com.arcgismaps.data.ServiceFeatureTable
|
||||
import com.arcgismaps.geometry.GeometryEngine
|
||||
import com.arcgismaps.geometry.Point
|
||||
import com.arcgismaps.mapping.ArcGISMap
|
||||
import com.arcgismaps.mapping.BasemapStyle
|
||||
import com.arcgismaps.mapping.Viewpoint
|
||||
@@ -118,6 +119,56 @@ class MapViewModel(application: Application): AndroidViewModel(application) {
|
||||
}
|
||||
}
|
||||
|
||||
fun createFeatureWithAttributesAt(screenCoordinate: ScreenCoordinate, beschreibung: String, typ: String) {
|
||||
// Create the feature.
|
||||
val feature = serviceFeatureTable?.createFeature()?.apply {
|
||||
// Get the normalized geometry for the tapped location and use it as the feature's geometry.
|
||||
mapViewProxy.screenToLocationOrNull(screenCoordinate)?.let { mapPoint ->
|
||||
geometry = GeometryEngine.normalizeCentralMeridian(mapPoint)
|
||||
// Set feature attributes.
|
||||
attributes["Typ"] = typ
|
||||
attributes["Beschreibung"] = beschreibung
|
||||
}
|
||||
}
|
||||
feature?.let {
|
||||
viewModelScope.launch {
|
||||
// Add the feature to the table.
|
||||
serviceFeatureTable?.addFeature(it)
|
||||
// Apply the edits to the service on the service geodatabase.
|
||||
serviceFeatureTable?.applyEdits()
|
||||
// Update the feature to get the updated objectid - a temporary ID is used before the feature is added.
|
||||
it.refresh()
|
||||
// Confirm feature addition.
|
||||
snackBarMessage = "Created feature ${it.attributes["objectid"]}"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun createFeatureWithAttributesAtPoint(point: Point, beschreibung: String, typ: String) {
|
||||
// Create the feature.
|
||||
val feature = serviceFeatureTable?.createFeature()?.apply {
|
||||
// Get the normalized geometry for the tapped location and use it as the feature's geometry.
|
||||
|
||||
geometry = GeometryEngine.normalizeCentralMeridian(point)
|
||||
// Set feature attributes.
|
||||
attributes["Typ"] = typ
|
||||
attributes["Beschreibung"] = beschreibung
|
||||
|
||||
}
|
||||
feature?.let {
|
||||
viewModelScope.launch {
|
||||
// Add the feature to the table.
|
||||
serviceFeatureTable?.addFeature(it)
|
||||
// Apply the edits to the service on the service geodatabase.
|
||||
serviceFeatureTable?.applyEdits()
|
||||
// Update the feature to get the updated objectid - a temporary ID is used before the feature is added.
|
||||
it.refresh()
|
||||
// Confirm feature addition.
|
||||
snackBarMessage = "Created feature ${it.attributes["objectid"]}"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects a feature at the tapped location in preparation for deletion.
|
||||
*/
|
||||
|
||||
@@ -22,9 +22,12 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.text.input.TextFieldValue
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.arcgismaps.geometry.Point
|
||||
import com.arcgismaps.geometry.SpatialReference
|
||||
import com.arcgismaps.location.LocationDisplayAutoPanMode
|
||||
import com.arcgismaps.toolkit.geoviewcompose.MapView
|
||||
import com.arcgismaps.toolkit.geoviewcompose.rememberLocationDisplay
|
||||
import com.google.android.gms.location.LocationServices
|
||||
import de.jadehs.strassenschadenpro2.MapViewModel
|
||||
import de.jadehs.strassenschadenpro2.components.DropDownMenuBox
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -38,6 +41,8 @@ fun CreatePage(modifier: Modifier = Modifier, mapViewModel: MapViewModel) {
|
||||
|
||||
var showModalBottomSheet = remember { mutableStateOf(false) }
|
||||
|
||||
var enableSaveButton = remember { mutableStateOf(false) }
|
||||
|
||||
val locationDisplay = rememberLocationDisplay().apply {
|
||||
setAutoPanMode(LocationDisplayAutoPanMode.Off)
|
||||
}
|
||||
@@ -60,6 +65,8 @@ fun CreatePage(modifier: Modifier = Modifier, mapViewModel: MapViewModel) {
|
||||
)
|
||||
}
|
||||
|
||||
val fuesedLocationClient = remember { LocationServices.getFusedLocationProviderClient(context) }
|
||||
|
||||
Column(modifier = modifier.fillMaxSize()
|
||||
.padding(top = 16.dp, start = 16.dp, end = 16.dp, bottom = 16.dp),
|
||||
verticalArrangement = Arrangement.Top,
|
||||
@@ -69,6 +76,7 @@ fun CreatePage(modifier: Modifier = Modifier, mapViewModel: MapViewModel) {
|
||||
value = beschreibungTextFieldValue.value,
|
||||
onValueChange = {
|
||||
beschreibungTextFieldValue.value = it
|
||||
enableSaveButton.value = beschreibungTextFieldValue.value.text.isNotEmpty() && currentDamageType.value.isNotEmpty()
|
||||
},
|
||||
minLines = 5,
|
||||
label = { Text("Beschreibung")}
|
||||
@@ -81,15 +89,28 @@ fun CreatePage(modifier: Modifier = Modifier, mapViewModel: MapViewModel) {
|
||||
dropDownItemList = mapViewModel.damageTypeList,
|
||||
onIndexSelected = { index ->
|
||||
currentDamageType.value = mapViewModel.damageTypeList[index]
|
||||
Log.d("CreatePage", "Selected index: $index")
|
||||
enableSaveButton.value = beschreibungTextFieldValue.value.text.isNotEmpty() && currentDamageType.value.isNotEmpty()
|
||||
}
|
||||
)
|
||||
Row(modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.SpaceEvenly){
|
||||
Button(onClick = {}){
|
||||
Button(enabled = enableSaveButton.value,
|
||||
onClick = {
|
||||
fuesedLocationClient.lastLocation.addOnSuccessListener { location ->
|
||||
location?.let { location->
|
||||
val beschreibung = beschreibungTextFieldValue.value.text
|
||||
val typ = currentDamageType.value
|
||||
var point = Point(location.longitude,
|
||||
location.latitude,
|
||||
SpatialReference.wgs84())
|
||||
mapViewModel.createFeatureWithAttributesAtPoint(point,beschreibung,typ)
|
||||
}
|
||||
}
|
||||
}){
|
||||
Text("GPS")
|
||||
}
|
||||
Button(onClick = {
|
||||
Button(enabled = enableSaveButton.value,
|
||||
onClick = {
|
||||
showModalBottomSheet.value = !showModalBottomSheet.value
|
||||
}){
|
||||
Text("Karte")
|
||||
@@ -98,6 +119,7 @@ fun CreatePage(modifier: Modifier = Modifier, mapViewModel: MapViewModel) {
|
||||
}
|
||||
if(showModalBottomSheet.value) {
|
||||
ModalBottomSheet(
|
||||
sheetGesturesEnabled = false,
|
||||
onDismissRequest = {
|
||||
showModalBottomSheet.value = false
|
||||
}
|
||||
@@ -107,7 +129,12 @@ fun CreatePage(modifier: Modifier = Modifier, mapViewModel: MapViewModel) {
|
||||
arcGISMap = mapViewModel.map,
|
||||
locationDisplay = locationDisplay,
|
||||
mapViewProxy = mapViewModel.mapViewProxy,
|
||||
onSingleTapConfirmed = mapViewModel::onTap,
|
||||
onSingleTapConfirmed = { singleTapConfirmedEvent ->
|
||||
val screenCoordinate = singleTapConfirmedEvent.screenCoordinate
|
||||
val beschreibung = beschreibungTextFieldValue.value.text
|
||||
val typ = currentDamageType.value
|
||||
mapViewModel.createFeatureWithAttributesAt(screenCoordinate,beschreibung,typ)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ junitVersion = "1.3.0"
|
||||
espressoCore = "3.7.0"
|
||||
lifecycleRuntimeKtx = "2.9.4"
|
||||
activityCompose = "1.11.0"
|
||||
composeBom = "2024.09.00"
|
||||
composeBom = "2025.12.00"
|
||||
arcgisMapsKotlin = "200.8.0"
|
||||
|
||||
[libraries]
|
||||
|
||||
Reference in New Issue
Block a user