- Code bereinigt
- MapView in MapSegment ausgelagert
This commit is contained in:
@@ -20,14 +20,6 @@ class MainActivity : ComponentActivity() {
|
|||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
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()
|
enableEdgeToEdge()
|
||||||
|
|
||||||
setContent {
|
setContent {
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import androidx.compose.foundation.verticalScroll
|
|||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.Add
|
import androidx.compose.material.icons.filled.Add
|
||||||
import androidx.compose.material.icons.filled.FilterAlt
|
import androidx.compose.material.icons.filled.FilterAlt
|
||||||
|
import androidx.compose.material.icons.filled.FormatListNumbered
|
||||||
import androidx.compose.material.icons.filled.Menu
|
import androidx.compose.material.icons.filled.Menu
|
||||||
import androidx.compose.material3.*
|
import androidx.compose.material3.*
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
@@ -44,9 +45,8 @@ import kotlinx.coroutines.Dispatchers
|
|||||||
fun MainScreen(modifier: Modifier = Modifier, application: Application) {
|
fun MainScreen(modifier: Modifier = Modifier, application: Application) {
|
||||||
var showReport by rememberSaveable { mutableStateOf(false) }
|
var showReport by rememberSaveable { mutableStateOf(false) }
|
||||||
var sliderOpen by remember { mutableStateOf(false) }
|
var sliderOpen by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
// ViewModel Initialisierung
|
|
||||||
val mapViewModel = remember { MapViewModel(application) }
|
val mapViewModel = remember { MapViewModel(application) }
|
||||||
|
val albumViewModel = remember { AlbumViewModel(Dispatchers.Default) }
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
@@ -63,19 +63,26 @@ fun MainScreen(modifier: Modifier = Modifier, application: Application) {
|
|||||||
},
|
},
|
||||||
floatingActionButton = {
|
floatingActionButton = {
|
||||||
LargeFloatingActionButton(
|
LargeFloatingActionButton(
|
||||||
onClick = { showReport = true; sliderOpen = false },
|
onClick = {
|
||||||
|
showReport = true
|
||||||
|
sliderOpen = false
|
||||||
|
},
|
||||||
modifier = Modifier.offset(y = 64.dp),
|
modifier = Modifier.offset(y = 64.dp),
|
||||||
containerColor = ButtonColor
|
containerColor = ButtonColor
|
||||||
) { Icon(Icons.Default.Add, contentDescription = "Add") }
|
) {
|
||||||
|
Icon(Icons.Default.Add, contentDescription = "Add")
|
||||||
|
}
|
||||||
},
|
},
|
||||||
floatingActionButtonPosition = FabPosition.Center,
|
floatingActionButtonPosition = FabPosition.Center,
|
||||||
) { innerPadding ->
|
) { innerPadding ->
|
||||||
ContentScreen(
|
ContentScreen(
|
||||||
modifier = Modifier.padding(innerPadding),
|
modifier = Modifier.padding(innerPadding),
|
||||||
mapViewModel = mapViewModel,
|
mapViewModel,
|
||||||
|
albumViewModel,
|
||||||
showReport = showReport,
|
showReport = showReport,
|
||||||
sliderOpen = sliderOpen,
|
sliderOpen = sliderOpen,
|
||||||
onDismissReport = { showReport = false })
|
onDismissReport = { showReport = false }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,26 +90,20 @@ fun MainScreen(modifier: Modifier = Modifier, application: Application) {
|
|||||||
fun ContentScreen(
|
fun ContentScreen(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
mapViewModel: MapViewModel,
|
mapViewModel: MapViewModel,
|
||||||
|
albumViewModel: AlbumViewModel,
|
||||||
showReport: Boolean,
|
showReport: Boolean,
|
||||||
sliderOpen: Boolean,
|
sliderOpen: Boolean,
|
||||||
onDismissReport: () -> Unit
|
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()) {
|
Box(modifier = modifier.fillMaxSize()) {
|
||||||
MapView(
|
// HINTERGRUND: Die Map
|
||||||
|
MapSegment(
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
arcGISMap = mapViewModel.map,
|
mapViewModel = mapViewModel,
|
||||||
mapViewProxy = mapViewModel.mapViewProxy,
|
|
||||||
locationDisplay = locationDisplay
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// VORDERGRUND: Das Overlay (wenn showReport = true)
|
||||||
if (showReport) {
|
if (showReport) {
|
||||||
ReportOverlay(
|
ReportOverlay(
|
||||||
onCancel = onDismissReport,
|
onCancel = onDismissReport,
|
||||||
@@ -118,18 +119,29 @@ fun ContentScreen(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Slider von Links
|
||||||
SideSlider(visible = sliderOpen) {
|
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()) {
|
SliderMenuItem(
|
||||||
Snackbar(modifier = Modifier.align(Alignment.BottomCenter).padding(bottom = 80.dp)) {
|
text = "Schäden filtern",
|
||||||
Text(mapViewModel.snackBarMessage)
|
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
122
app/src/main/java/com/example/snapandsolve/MapSegment.kt
Normal file
122
app/src/main/java/com/example/snapandsolve/MapSegment.kt
Normal 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
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user