- Code bereinigt

- MapView in MapSegment ausgelagert
This commit is contained in:
2026-01-13 16:23:04 +01:00
parent f5ac96807c
commit 97d86523ab
3 changed files with 161 additions and 41 deletions

View File

@@ -20,14 +20,6 @@ class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewModel = AlbumViewModel(coroutineContext = Dispatchers.Default)
/*
Wird gebraucht um die Karte in ArcGIS anzuzeigen. Die Prüfung ob man Zugang hat oder nicht
wurde gelöscht.
*/
ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.ARCGIS_TOKEN)
enableEdgeToEdge()
setContent {

View File

@@ -18,6 +18,7 @@ import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.FilterAlt
import androidx.compose.material.icons.filled.FormatListNumbered
import androidx.compose.material.icons.filled.Menu
import androidx.compose.material3.*
import androidx.compose.runtime.*
@@ -44,9 +45,8 @@ import kotlinx.coroutines.Dispatchers
fun MainScreen(modifier: Modifier = Modifier, application: Application) {
var showReport by rememberSaveable { mutableStateOf(false) }
var sliderOpen by remember { mutableStateOf(false) }
// ViewModel Initialisierung
val mapViewModel = remember { MapViewModel(application) }
val albumViewModel = remember { AlbumViewModel(Dispatchers.Default) }
Scaffold(
modifier = Modifier.fillMaxSize(),
@@ -63,19 +63,26 @@ fun MainScreen(modifier: Modifier = Modifier, application: Application) {
},
floatingActionButton = {
LargeFloatingActionButton(
onClick = { showReport = true; sliderOpen = false },
onClick = {
showReport = true
sliderOpen = false
},
modifier = Modifier.offset(y = 64.dp),
containerColor = ButtonColor
) { Icon(Icons.Default.Add, contentDescription = "Add") }
) {
Icon(Icons.Default.Add, contentDescription = "Add")
}
},
floatingActionButtonPosition = FabPosition.Center,
) { innerPadding ->
ContentScreen(
modifier = Modifier.padding(innerPadding),
mapViewModel = mapViewModel,
mapViewModel,
albumViewModel,
showReport = showReport,
sliderOpen = sliderOpen,
onDismissReport = { showReport = false })
onDismissReport = { showReport = false }
)
}
}
@@ -83,26 +90,20 @@ fun MainScreen(modifier: Modifier = Modifier, application: Application) {
fun ContentScreen(
modifier: Modifier = Modifier,
mapViewModel: MapViewModel,
albumViewModel: AlbumViewModel,
showReport: Boolean,
sliderOpen: Boolean,
onDismissReport: () -> Unit
) {
val albumViewModel = remember { AlbumViewModel(Dispatchers.Default) }
val locationDisplay = setupLocationDisplay()
// VERBINDUNG ZUM VIEWMODEL (Hier wird das GPS-Werkzeug übergeben)
LaunchedEffect(locationDisplay) {
mapViewModel.locationDisplay = locationDisplay
}
Box(modifier = modifier.fillMaxSize()) {
MapView(
// HINTERGRUND: Die Map
MapSegment(
modifier = Modifier.fillMaxSize(),
arcGISMap = mapViewModel.map,
mapViewProxy = mapViewModel.mapViewProxy,
locationDisplay = locationDisplay
mapViewModel = mapViewModel,
)
// VORDERGRUND: Das Overlay (wenn showReport = true)
if (showReport) {
ReportOverlay(
onCancel = onDismissReport,
@@ -118,18 +119,29 @@ fun ContentScreen(
)
}
// Slider von Links
SideSlider(visible = sliderOpen) {
SliderMenuItem(text = "Schäden filtern", icon = Icons.Default.FilterAlt, onClick = {})
}
Text(
"Menü",
style = MaterialTheme.typography.titleMedium,
modifier = Modifier.padding(bottom = 12.dp)
)
if (mapViewModel.snackBarMessage.isNotEmpty()) {
Snackbar(modifier = Modifier.align(Alignment.BottomCenter).padding(bottom = 80.dp)) {
Text(mapViewModel.snackBarMessage)
SliderMenuItem(
text = "Schäden filtern",
icon = Icons.Default.FilterAlt,
onClick = {
/* TODO */
}
LaunchedEffect(mapViewModel.snackBarMessage) {
kotlinx.coroutines.delay(4000)
mapViewModel.snackBarMessage = ""
)
SliderMenuItem(
text = "Schadensliste",
icon = Icons.Default.FormatListNumbered,
onClick = {
/* TODO */
}
)
}
}
}
@@ -350,9 +362,3 @@ fun ReportOverlay(
}
}
}
fun createMap(): ArcGISMap {
return ArcGISMap(BasemapStyle.ArcGISTopographic).apply {
initialViewpoint = Viewpoint(53.14, 8.20, 20000.0)
}
}

View File

@@ -0,0 +1,122 @@
package com.example.snapandsolve
import MapViewModel
import android.Manifest
import android.content.Context
import android.content.pm.PackageManager
import android.widget.Toast
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.SnackbarHostState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.core.content.ContextCompat
import com.arcgismaps.ApiKey
import com.arcgismaps.ArcGISEnvironment
import com.arcgismaps.location.LocationDisplayAutoPanMode
import com.arcgismaps.toolkit.geoviewcompose.MapView
import com.arcgismaps.toolkit.geoviewcompose.rememberLocationDisplay
import kotlinx.coroutines.launch
@Composable
fun MapSegment(
modifier: Modifier = Modifier,
mapViewModel: MapViewModel
) {
val context = LocalContext.current
val coroutineScope = rememberCoroutineScope()
ArcGISEnvironment.applicationContext = context.applicationContext
ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.ARCGIS_TOKEN)
// val snackbarHostState = remember { SnackbarHostState() }
val locationDisplay = rememberLocationDisplay().apply {
setAutoPanMode(LocationDisplayAutoPanMode.Off)
}
if (checkPermissions(context)) {
// Permissions are already granted.
LaunchedEffect(Unit) {
locationDisplay.dataSource.start()
}
} else {
RequestPermissions(
context = context,
onPermissionsGranted = {
coroutineScope.launch {
locationDisplay.dataSource.start()
}
}
)
}
Column(
modifier = modifier
.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
) {
MapView(
modifier = Modifier.weight(90f),
arcGISMap = mapViewModel.map,
locationDisplay = locationDisplay,
mapViewProxy = mapViewModel.mapViewProxy,
onSingleTapConfirmed = {}//mapViewModel::onTap,
) {
/* TODO */
}
}
}
fun checkPermissions(context: Context): Boolean {
// Check permissions to see if both permissions are granted.
// Coarse location permission.
val permissionCheckCoarseLocation = ContextCompat.checkSelfPermission(
context,
Manifest.permission.ACCESS_COARSE_LOCATION
) == PackageManager.PERMISSION_GRANTED
// Fine location permission.
val permissionCheckFineLocation = ContextCompat.checkSelfPermission(
context,
Manifest.permission.ACCESS_FINE_LOCATION
) == PackageManager.PERMISSION_GRANTED
return permissionCheckCoarseLocation && permissionCheckFineLocation
}
fun showError(context: Context, message: String) {
Toast.makeText(context, message, Toast.LENGTH_LONG).show()
}
@Composable
fun RequestPermissions(context: Context, onPermissionsGranted: () -> Unit) {
// Create an activity result launcher using permissions contract and handle the result.
val activityResultLauncher = rememberLauncherForActivityResult(
ActivityResultContracts.RequestMultiplePermissions()
) { permissions ->
// Check if both fine & coarse location permissions are true.
if (permissions.all { it.value }) {
onPermissionsGranted()
} else {
showError(context, "Location permissions were denied")
}
}
LaunchedEffect(Unit) {
activityResultLauncher.launch(
// Request both fine and coarse location permissions.
arrayOf(
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION
)
)
}
}