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)
|
androidTestImplementation(libs.androidx.compose.ui.test.junit4)
|
||||||
debugImplementation(libs.androidx.compose.ui.tooling)
|
debugImplementation(libs.androidx.compose.ui.tooling)
|
||||||
debugImplementation(libs.androidx.compose.ui.test.manifest)
|
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
|
// ArcGIS Maps for Kotlin - SDK dependency
|
||||||
implementation(libs.arcgis.maps.kotlin)
|
implementation(libs.arcgis.maps.kotlin)
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import com.arcgismaps.data.ArcGISFeature
|
|||||||
import com.arcgismaps.data.CodedValueDomain
|
import com.arcgismaps.data.CodedValueDomain
|
||||||
import com.arcgismaps.data.ServiceFeatureTable
|
import com.arcgismaps.data.ServiceFeatureTable
|
||||||
import com.arcgismaps.geometry.GeometryEngine
|
import com.arcgismaps.geometry.GeometryEngine
|
||||||
|
import com.arcgismaps.geometry.Point
|
||||||
import com.arcgismaps.mapping.ArcGISMap
|
import com.arcgismaps.mapping.ArcGISMap
|
||||||
import com.arcgismaps.mapping.BasemapStyle
|
import com.arcgismaps.mapping.BasemapStyle
|
||||||
import com.arcgismaps.mapping.Viewpoint
|
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.
|
* 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.platform.LocalContext
|
||||||
import androidx.compose.ui.text.input.TextFieldValue
|
import androidx.compose.ui.text.input.TextFieldValue
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import com.arcgismaps.geometry.Point
|
||||||
|
import com.arcgismaps.geometry.SpatialReference
|
||||||
import com.arcgismaps.location.LocationDisplayAutoPanMode
|
import com.arcgismaps.location.LocationDisplayAutoPanMode
|
||||||
import com.arcgismaps.toolkit.geoviewcompose.MapView
|
import com.arcgismaps.toolkit.geoviewcompose.MapView
|
||||||
import com.arcgismaps.toolkit.geoviewcompose.rememberLocationDisplay
|
import com.arcgismaps.toolkit.geoviewcompose.rememberLocationDisplay
|
||||||
|
import com.google.android.gms.location.LocationServices
|
||||||
import de.jadehs.strassenschadenpro2.MapViewModel
|
import de.jadehs.strassenschadenpro2.MapViewModel
|
||||||
import de.jadehs.strassenschadenpro2.components.DropDownMenuBox
|
import de.jadehs.strassenschadenpro2.components.DropDownMenuBox
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@@ -38,6 +41,8 @@ fun CreatePage(modifier: Modifier = Modifier, mapViewModel: MapViewModel) {
|
|||||||
|
|
||||||
var showModalBottomSheet = remember { mutableStateOf(false) }
|
var showModalBottomSheet = remember { mutableStateOf(false) }
|
||||||
|
|
||||||
|
var enableSaveButton = remember { mutableStateOf(false) }
|
||||||
|
|
||||||
val locationDisplay = rememberLocationDisplay().apply {
|
val locationDisplay = rememberLocationDisplay().apply {
|
||||||
setAutoPanMode(LocationDisplayAutoPanMode.Off)
|
setAutoPanMode(LocationDisplayAutoPanMode.Off)
|
||||||
}
|
}
|
||||||
@@ -60,6 +65,8 @@ fun CreatePage(modifier: Modifier = Modifier, mapViewModel: MapViewModel) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val fuesedLocationClient = remember { LocationServices.getFusedLocationProviderClient(context) }
|
||||||
|
|
||||||
Column(modifier = modifier.fillMaxSize()
|
Column(modifier = modifier.fillMaxSize()
|
||||||
.padding(top = 16.dp, start = 16.dp, end = 16.dp, bottom = 16.dp),
|
.padding(top = 16.dp, start = 16.dp, end = 16.dp, bottom = 16.dp),
|
||||||
verticalArrangement = Arrangement.Top,
|
verticalArrangement = Arrangement.Top,
|
||||||
@@ -69,6 +76,7 @@ fun CreatePage(modifier: Modifier = Modifier, mapViewModel: MapViewModel) {
|
|||||||
value = beschreibungTextFieldValue.value,
|
value = beschreibungTextFieldValue.value,
|
||||||
onValueChange = {
|
onValueChange = {
|
||||||
beschreibungTextFieldValue.value = it
|
beschreibungTextFieldValue.value = it
|
||||||
|
enableSaveButton.value = beschreibungTextFieldValue.value.text.isNotEmpty() && currentDamageType.value.isNotEmpty()
|
||||||
},
|
},
|
||||||
minLines = 5,
|
minLines = 5,
|
||||||
label = { Text("Beschreibung")}
|
label = { Text("Beschreibung")}
|
||||||
@@ -81,15 +89,28 @@ fun CreatePage(modifier: Modifier = Modifier, mapViewModel: MapViewModel) {
|
|||||||
dropDownItemList = mapViewModel.damageTypeList,
|
dropDownItemList = mapViewModel.damageTypeList,
|
||||||
onIndexSelected = { index ->
|
onIndexSelected = { index ->
|
||||||
currentDamageType.value = mapViewModel.damageTypeList[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(),
|
Row(modifier = Modifier.fillMaxWidth(),
|
||||||
horizontalArrangement = Arrangement.SpaceEvenly){
|
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")
|
Text("GPS")
|
||||||
}
|
}
|
||||||
Button(onClick = {
|
Button(enabled = enableSaveButton.value,
|
||||||
|
onClick = {
|
||||||
showModalBottomSheet.value = !showModalBottomSheet.value
|
showModalBottomSheet.value = !showModalBottomSheet.value
|
||||||
}){
|
}){
|
||||||
Text("Karte")
|
Text("Karte")
|
||||||
@@ -98,6 +119,7 @@ fun CreatePage(modifier: Modifier = Modifier, mapViewModel: MapViewModel) {
|
|||||||
}
|
}
|
||||||
if(showModalBottomSheet.value) {
|
if(showModalBottomSheet.value) {
|
||||||
ModalBottomSheet(
|
ModalBottomSheet(
|
||||||
|
sheetGesturesEnabled = false,
|
||||||
onDismissRequest = {
|
onDismissRequest = {
|
||||||
showModalBottomSheet.value = false
|
showModalBottomSheet.value = false
|
||||||
}
|
}
|
||||||
@@ -107,7 +129,12 @@ fun CreatePage(modifier: Modifier = Modifier, mapViewModel: MapViewModel) {
|
|||||||
arcGISMap = mapViewModel.map,
|
arcGISMap = mapViewModel.map,
|
||||||
locationDisplay = locationDisplay,
|
locationDisplay = locationDisplay,
|
||||||
mapViewProxy = mapViewModel.mapViewProxy,
|
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"
|
espressoCore = "3.7.0"
|
||||||
lifecycleRuntimeKtx = "2.9.4"
|
lifecycleRuntimeKtx = "2.9.4"
|
||||||
activityCompose = "1.11.0"
|
activityCompose = "1.11.0"
|
||||||
composeBom = "2024.09.00"
|
composeBom = "2025.12.00"
|
||||||
arcgisMapsKotlin = "200.8.0"
|
arcgisMapsKotlin = "200.8.0"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
|
|||||||
Reference in New Issue
Block a user