symbole angepasst

unused fun gelöscht
This commit is contained in:
2026-02-14 10:54:36 +01:00
parent 48802606e8
commit a2866cc268
12 changed files with 97 additions and 119 deletions

View File

@@ -26,7 +26,7 @@ class MainActivity : ComponentActivity() {
setContent {
SnapAndSolveTheme {
MainScreen(application=application)
MainScreen(application=application, context=this)
}
}
}

View File

@@ -2,6 +2,7 @@ import DamageFilterDialog
import DamageListDialog
import MapViewModel
import android.app.Application
import android.content.Context
import androidx.compose.foundation.layout.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
@@ -37,12 +38,12 @@ import kotlinx.coroutines.launch
@Composable
fun MainScreen(modifier: Modifier = Modifier, application: Application) {
fun MainScreen(modifier: Modifier = Modifier, application: Application, context: Context) {
var showReport by rememberSaveable { mutableStateOf(false) }
var sliderOpen by rememberSaveable { mutableStateOf(false) }
var showSettings by rememberSaveable { mutableStateOf(false) }
val mapViewModel = remember { MapViewModel(application) }
val mapViewModel = remember { MapViewModel(application, context) }
val albumViewModel = remember { AlbumViewModel(Dispatchers.Default) }
fun openReport() {
@@ -196,19 +197,16 @@ fun ContentScreen(
style = MaterialTheme.typography.titleMedium,
modifier = Modifier.padding(bottom = 12.dp)
)
SliderMenuItem(
text = "Einstellungen",
icon = Icons.Default.Settings,
onClick = onOpenSettings
)
SliderMenuItem(
text = "Schäden filtern",
icon = Icons.Default.FilterAlt,
onClick = { showFilterDialog = true }
)
SliderMenuItem(
text = "Schadensliste",
icon = Icons.Default.FormatListNumbered,
@@ -233,24 +231,3 @@ fun AppTopBar(
)
)
}
/*
suspend fun loadFirstAttachmentBitmap(
feature: ArcGISFeature
): ImageBitmap? {
// Feature muss geladen sein
feature.load().getOrThrow()
// Attachments abrufen
val attachments = feature.fetchAttachments().getOrThrow()
val first = attachments.firstOrNull() ?: return null
// Attachment-Daten laden
val data = first.fetchData().getOrThrow()
val bitmap = BitmapFactory.decodeByteArray(data, 0, data.size)
return bitmap.asImageBitmap()
}
*/

View File

@@ -1,4 +1,5 @@
import android.app.Application
import android.content.Context
import android.graphics.Bitmap
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
@@ -35,7 +36,7 @@ import java.io.ByteArrayOutputStream
class MapViewModel(application: Application) : AndroidViewModel(application) {
class MapViewModel(application: Application, context: Context) : AndroidViewModel(application) {
companion object {
// Zentrale Definition der Schadenstypen
@@ -99,7 +100,7 @@ class MapViewModel(application: Application) : AndroidViewModel(application) {
println("DEBUG: Fehler beim Laden der Tabelle: ${it.message}")
}
featureLayer = FeatureLayer.createWithFeatureTable(serviceFeatureTable)
featureLayer.renderer = createTypStatusRenderer()
featureLayer.renderer = createTypStatusRenderer(context)
map.operationalLayers.add(featureLayer)
// ===== DEBUG: Felder nach dem Hinzufügen zur Map =====
@@ -219,27 +220,9 @@ class MapViewModel(application: Application) : AndroidViewModel(application) {
when (selectedOperation) {
FeatureOperationType.DEFAULT -> selectFeatureAt(singleTapConfirmedEvent.screenCoordinate)
FeatureOperationType.DELETE -> deleteFeatureAt(singleTapConfirmedEvent.screenCoordinate)
FeatureOperationType.UPDATE_ATTRIBUTE -> selectFeatureForAttributeEditAt(singleTapConfirmedEvent.screenCoordinate)
FeatureOperationType.UPDATE_GEOMETRY -> updateFeatureGeometryAt(singleTapConfirmedEvent.screenCoordinate)
FeatureOperationType.PICK_REPORT_LOCATION -> pickReportLocation(singleTapConfirmedEvent.screenCoordinate)
// RATE_FEATURE wird nicht mehr gebraucht - wird im DEFAULT mit behandelt!
}
}
private fun deleteFeatureAt(screenCoordinate: ScreenCoordinate) {
featureLayer?.let { featureLayer ->
// Clear any existing selection.
featureLayer.clearSelection()
selectedFeature = null
viewModelScope.launch {
// Determine if a user tapped on a feature.
mapViewProxy.identify(featureLayer, screenCoordinate, 10.dp).onSuccess { identifyResult ->
selectedFeature = (identifyResult.geoElements.firstOrNull() as? ArcGISFeature)?.also {
featureLayer.selectFeature(it)
}
}
}
}
}
@@ -431,7 +414,6 @@ class MapViewModel(application: Application) : AndroidViewModel(application) {
enum class FeatureOperationType(val operationName: String, val instruction: String) {
DEFAULT("Default", ""),
DELETE("Delete feature", "Select an existing feature to delete it."),
UPDATE_ATTRIBUTE("Update attribute", "Select an existing feature to edit its attribute."),
UPDATE_GEOMETRY("Update geometry", "Select an existing feature and tap the map to move it to a new position."),
PICK_REPORT_LOCATION("Pick report location", "Tippe auf die Karte, um die Position zu setzen."),

View File

@@ -1,4 +1,3 @@
import MapViewModel
import MapViewModel.Companion.DAMAGE_TYPES
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
@@ -148,14 +147,7 @@ fun DamageFilterDialog(
selectedFilters - type
}
},
emoji = when (type) {
"Straße" -> "🛣️"
"Gehweg" -> "🚶"
"Fahrradweg" -> "🚴"
"Beleuchtung" -> "💡"
"Sonstiges" -> "📍"
else -> ""
}
emoji = getEmojiForType(type)
)
}

View File

@@ -645,11 +645,11 @@ fun formatDistance(meters: Double?): String {
fun getEmojiForType(typ: String): String {
return when (typ) {
"Straße" -> "🛣️"
"Gehweg" -> "🚶"
"Fahrradweg" -> "🚴"
"Beleuchtung" -> "💡"
"Sonstiges" -> "📍"
"Straße" -> String(Character.toChars(0x1F6E3))
"Gehweg" -> String(Character.toChars(0x1F6B5))
"Fahrradweg" -> String(Character.toChars(0x1F6B2))
"Beleuchtung" -> String(Character.toChars(0x1F4A1))
"Sonstiges" -> String(Character.toChars(0x1F4CC))
else -> ""
}
}
}

View File

@@ -1,45 +1,108 @@
package com.example.snapandsolve.view
import android.content.Context
import com.arcgismaps.Color
import com.arcgismaps.mapping.symbology.*
import kotlin.collections.iterator
import com.example.snapandsolve.R
fun createTypStatusRenderer(): UniqueValueRenderer {
// Status -> Hintergrundfarbe
val statusColor = mapOf(
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.Drawable
import androidx.core.content.ContextCompat
fun makeStatusTypeSymbol(
context: Context,
foregroundDrawableRes: Int,
statusColor: Color
): Symbol {
val white = Color.fromRgba(255, 255, 255, 255)
// Hintergrund: weißer Kreis + Outline in Statusfarbe
val background = SimpleMarkerSymbol(
style = SimpleMarkerSymbolStyle.Circle,
color = white,
size = 20f
).apply {
outline = SimpleLineSymbol(
style = SimpleLineSymbolStyle.Solid,
color = statusColor,
width = 2.5f
)
}
// Drawable aus Ressourcen laden
val drawable = ContextCompat.getDrawable(context, foregroundDrawableRes)
?: throw IllegalArgumentException("Drawable resource not found: $foregroundDrawableRes")
// Drawable zu Bitmap konvertieren
val bitmap = drawableToBitmap(drawable)
// Bitmap zu BitmapDrawable konvertieren
val bitmapDrawable = BitmapDrawable(context.resources, bitmap)
// Vordergrund: BitmapDrawable als PictureMarkerSymbol
val foreground = PictureMarkerSymbol.createWithImage(bitmapDrawable).apply {
width = 16f
height = 16f
}
return CompositeSymbol(listOf(background, foreground))
}
// Hilfsfunktion: Drawable zu Bitmap konvertieren
private fun drawableToBitmap(drawable: Drawable): Bitmap {
if (drawable is BitmapDrawable) {
return drawable.bitmap
}
// Für VectorDrawables und andere Drawable-Typen
val bitmap = Bitmap.createBitmap(
drawable.intrinsicWidth.takeIf { it > 0 } ?: 1,
drawable.intrinsicHeight.takeIf { it > 0 } ?: 1,
Bitmap.Config.ARGB_8888
)
val canvas = Canvas(bitmap)
drawable.setBounds(0, 0, canvas.width, canvas.height)
drawable.draw(canvas)
return bitmap
}
fun createTypStatusRenderer(context: Context): UniqueValueRenderer {
val statusColorByName = mapOf(
"neu" to Color.fromRgba(220, 50, 50, 255),
"in Bearbeitung" to Color.fromRgba(255, 180, 0, 255),
"Schaden behoben" to Color.fromRgba(60, 180, 75, 255)
)
// Typ -> Icon-Style (aus Standardbibliothek)
val typeIcon = mapOf(
"Straße" to SimpleMarkerSymbolStyle.Square,
"Gehweg" to SimpleMarkerSymbolStyle.Triangle,
"Fahrradweg" to SimpleMarkerSymbolStyle.Diamond,
"Beleuchtung" to SimpleMarkerSymbolStyle.X,
"Sonstiges" to SimpleMarkerSymbolStyle.Cross
val typeIconRes = mapOf(
"Straße" to R.drawable.motorway,
"Gehweg" to R.drawable.pedestrian,
"Fahrradweg" to R.drawable.bike,
"Beleuchtung" to R.drawable.lightbulb,
"Sonstiges" to R.drawable.pin
)
val renderer = UniqueValueRenderer().apply {
fieldNames.addAll(listOf("typ", "status"))
defaultLabel = "Sonstige"
defaultSymbol = makeStatusTypeSymbol(
iconStyle = SimpleMarkerSymbolStyle.Circle,
backgroundFill = Color.fromRgba(180, 180, 180, 255)
)
}
for ((typ, iconStyle) in typeIcon) {
for ((status, bgColor) in statusColor) {
for ((typ, iconRes) in typeIconRes) {
for ((status, outlineColor) in statusColorByName) {
val label = "$typ$status"
renderer.uniqueValues.add(
UniqueValue(
label = label,
description = label,
symbol = makeStatusTypeSymbol(iconStyle, bgColor),
symbol = makeStatusTypeSymbol(
context = context,
foregroundDrawableRes = iconRes,
statusColor = outlineColor
),
values = listOf(typ, status)
)
)
@@ -49,38 +112,3 @@ fun createTypStatusRenderer(): UniqueValueRenderer {
return renderer
}
fun makeStatusTypeSymbol(
iconStyle: SimpleMarkerSymbolStyle,
backgroundFill: Color
): Symbol {
val white = Color.fromRgba(255, 255, 255, 255)
// Hintergrund: Kreis in Statusfarbe
val background = SimpleMarkerSymbol(
style = SimpleMarkerSymbolStyle.Circle,
color = backgroundFill,
size = 18f
).apply {
outline = SimpleLineSymbol(
style = SimpleLineSymbolStyle.Solid,
color = white,
width = 1.5f
)
}
// Vordergrund: "Icon" als Outline (weiß), ohne Füllung
val foreground = SimpleMarkerSymbol(
style = iconStyle,
color = Color.fromRgba(0, 0, 0, 0), // transparent => nur Outline sichtbar
size = 10f
).apply {
outline = SimpleLineSymbol(
style = SimpleLineSymbolStyle.Solid,
color = white,
width = 2.0f
)
}
return CompositeSymbol(listOf(background, foreground))
}

View File

@@ -40,7 +40,6 @@ suspend fun findNearbyDamageOfSameType(
for (feature in result) {
val p = feature.geometry as? Point ?: continue
// ✅ Distanz korrekt
val dist = GeometryEngine.distanceOrNull(pointInLayerSR, p) ?: Double.POSITIVE_INFINITY
val typ = (feature.attributes["typ"] as? String).orEmpty()

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB