NavigationImage and padding

This commit is contained in:
Dimitris
2025-11-29 15:17:39 +01:00
parent 372cf504e2
commit c353a1d74e
11 changed files with 174 additions and 64 deletions

View File

@@ -20,12 +20,12 @@ android {
}
signingConfigs {
getByName("debug") {
keyAlias = "alias"
keyPassword = "alpha2000"
storeFile = file("/home/kouros/work/keystore/keystoreDebug")
storePassword = "alpha2000"
}
// getByName("debug") {
// keyAlias = "alias"
// keyPassword = "alpha2000"
// storeFile = file("/home/kouros/work/keystore/keystoreRelease")
// storePassword = "alpha2000"
// }
create("release") {
keyAlias = "release"
keyPassword = "zeta67#g"

View File

@@ -256,6 +256,7 @@ class MainActivity : ComponentActivity() {
fun Map() {
val step: StepData? by instruction.observeAsState()
Column {
//SimpleSearchBar()
if (step != null) {
NavigationInfo(step)
}

View File

@@ -0,0 +1,79 @@
package com.kouros.navigation
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.text.input.TextFieldState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ListItem
import androidx.compose.material3.SearchBar
import androidx.compose.material3.SearchBarDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.isTraversalGroup
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.traversalIndex
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SimpleSearchBar(
textFieldState: TextFieldState,
onSearch: (String) -> Unit,
searchResults: List<String>,
modifier: Modifier = Modifier
) {
// Controls expansion state of the search bar
var expanded by rememberSaveable { mutableStateOf(false) }
Box(
modifier
.fillMaxSize()
.semantics { isTraversalGroup = true }
) {
SearchBar(
modifier = Modifier
.align(Alignment.TopCenter)
.semantics { traversalIndex = 0f },
inputField = {
SearchBarDefaults.InputField(
query = textFieldState.text.toString(),
onQueryChange = { textFieldState.edit { replace(0, length, it) } },
onSearch = {
onSearch(textFieldState.text.toString())
expanded = false
},
expanded = expanded,
onExpandedChange = { expanded = it },
placeholder = { Text("Search") }
)
},
expanded = expanded,
onExpandedChange = { expanded = it },
) {
// Display search results in a scrollable column
Column(Modifier.verticalScroll(rememberScrollState())) {
searchResults.forEach { result ->
ListItem(
headlineContent = { Text(result) },
modifier = Modifier
.clickable {
textFieldState.edit { replace(0, length, result) }
expanded = false
}
.fillMaxWidth()
)
}
}
}
}
}

View File

@@ -3,22 +3,18 @@ package com.kouros.navigation.car
import android.location.Location
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material3.Badge
import androidx.compose.material3.BadgedBox
import androidx.compose.material3.Icon
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.draw.drawWithCache
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.graphics.Path
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.graphics.vector.rememberVectorPainter
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.TextStyle
@@ -54,7 +50,7 @@ fun cameraState(
tilt: Double,
preview: Boolean
): CameraState {
val padding = getPaddingValues(width, height, preview)
val padding = getPaddingValues(height, preview)
return rememberCameraState(
firstPosition =
CameraPosition(
@@ -118,29 +114,46 @@ fun BuildingLayer(tiles: Source) {
}
@Composable
fun DrawImage(location: Location) {
val textMeasurer = rememberTextMeasurer()
val vector = ImageVector.vectorResource(id = R.drawable.assistant_navigation_48px)
val painter = rememberVectorPainter(image = vector)
val tint = remember { ColorFilter.tint(NavigationColor) }
fun DrawImage(width: Int, height: Int, location: Location) {
NavigationImage(height)
Speed(width, height, location)
}
Box(
@Composable
fun NavigationImage(height: Int) {
val vector = ImageVector.vectorResource(id = R.drawable.assistant_navigation_48px)
val color = remember { NavigationColor }
BadgedBox(
modifier = Modifier
.size(48.dp, 48.dp)
.padding(start = 450.dp - 30.dp, top = 350.dp - 30.dp)
.drawBehind {
with(painter) {
draw(
size = Size(60F, 60F),
colorFilter = tint,
.padding(
start = 0.dp, top = distanceFromTop(height).dp
),
badge = {
Badge()
}
) {
Icon(
imageVector = vector,
contentDescription = "Navigation",
tint = color
)
}
})
}
@Composable
private fun Speed(
width: Int,
height: Int,
location: Location
) {
val textMeasurer = rememberTextMeasurer()
Box(
modifier = Modifier
.size(30.dp, 30.dp)
.padding(start = 650.dp, top = 350.dp)
.padding(
start = width.dp - percent(width, 20).dp,
top = height.dp - 60.dp
)
.drawWithCache {
val measuredText =
textMeasurer.measure(
@@ -157,6 +170,24 @@ fun DrawImage(location: Location) {
)
}
fun getPaddingValues(height: Int, preView: Boolean): PaddingValues {
val padding = PaddingValues(start = 0.dp, top = distanceFromTop(height).dp)
val prePadding = PaddingValues(start = 150.dp, bottom = 0.dp)
return if (preView) {
prePadding
} else {
padding
}
}
fun distanceFromTop(height: Int): Int {
return height - percent(height, 20)
}
fun percent(maxValue: Int, value: Int): Int {
return value * maxValue / 100
}
@Composable
fun Puck(cameraState: CameraState, location: Location) {
LocationPuck(
@@ -189,12 +220,3 @@ fun PuckState(cameraState: CameraState, userLocationState: UserLocationState) {
)
}
fun getPaddingValues(width: Int, height: Int, preView: Boolean): PaddingValues {
val padding = PaddingValues(start = 100.dp, top = 300.dp)
val prePadding = PaddingValues(start = 150.dp, bottom = 0.dp)
return if (preView) {
prePadding
} else {
padding
}
}

View File

@@ -206,7 +206,6 @@ class NavigationSession : Session(), NavigationScreen.Listener {
if (routeModel.isNavigating()) {
val snapedLocation = snapLocation(location, routeModel.route.maneuverLocations())
val distance = location.distanceTo(snapedLocation)
println(distance)
if (distance > MAXIMAL_ROUTE_DEVIATION) {
// navigationScreen.calculateNewRoute()
//return

View File

@@ -6,7 +6,9 @@ import android.hardware.display.DisplayManager
import android.hardware.display.VirtualDisplay
import android.location.Location
import android.location.LocationManager
import android.os.Build
import android.util.Log
import androidx.annotation.RequiresApi
import androidx.car.app.AppManager
import androidx.car.app.CarContext
import androidx.car.app.SurfaceCallback
@@ -25,14 +27,10 @@ import androidx.lifecycle.setViewTreeLifecycleOwner
import androidx.savedstate.setViewTreeSavedStateRegistryOwner
import com.kouros.navigation.car.navigation.RouteCarModel
import com.kouros.navigation.data.Constants
import com.kouros.navigation.data.Constants.MAXIMAL_ROUTE_DEVIATION
import com.kouros.navigation.data.Constants.NEXT_STEP_THRESHOLD
import com.kouros.navigation.data.Constants.SHOW_THREED_BUILDING
import com.kouros.navigation.model.RouteModel
import com.kouros.navigation.utils.NavigationUtils.getBooleanKeyValue
import com.kouros.navigation.utils.NavigationUtils.snapLocation
import com.kouros.navigation.utils.calculateZoom
import com.kouros.navigation.utils.location
import org.maplibre.compose.camera.CameraPosition
import org.maplibre.compose.camera.CameraState
import org.maplibre.compose.map.MaplibreMap
@@ -87,6 +85,7 @@ class SurfaceRenderer(
lateinit var presentation: Presentation
@RequiresApi(Build.VERSION_CODES.M)
override fun onSurfaceAvailable(surfaceContainer: SurfaceContainer) {
synchronized(this@SurfaceRenderer) {
Log.i(TAG, "Surface available $surfaceContainer")
@@ -136,6 +135,7 @@ class SurfaceRenderer(
}
}
@RequiresApi(Build.VERSION_CODES.KITKAT)
override fun onSurfaceDestroyed(surfaceContainer: SurfaceContainer) {
synchronized(this@SurfaceRenderer) {
Log.i(TAG, "SurfaceRenderer destroyed")
@@ -168,10 +168,11 @@ class SurfaceRenderer(
val route: String? by routeData.observeAsState()
val previewRoute: String? by previewRouteData.observeAsState()
val cameraState = cameraState(width, height, position, tilt, preview)
val baseStyle =
if (isSystemInDarkTheme()) BaseStyle.Uri(Constants.STYLE_DARK) else BaseStyle.Uri(
Constants.STYLE
)
val baseStyle =BaseStyle.Uri(Constants.STYLE)
// if (isSystemInDarkTheme()) BaseStyle.Uri(Constants.STYLE_DARK) else BaseStyle.Uri(
// Constants.STYLE
// )
MaplibreMap(
cameraState = cameraState,
@@ -196,7 +197,7 @@ class SurfaceRenderer(
var target = position.target
var localTilt = tilt
if (!preview) {
DrawImage(lastLocation)
DrawImage(width, height,lastLocation)
} else {
bearing = 0.0
zoom = previewZoom()
@@ -210,7 +211,7 @@ class SurfaceRenderer(
zoom = zoom,
target = target,
tilt = localTilt,
padding = getPaddingValues(width, height, preview)
padding = getPaddingValues(height, preview)
),
duration = cameraDuration
)
@@ -230,7 +231,7 @@ class SurfaceRenderer(
val cameraDuration = if ((lastBearing - position!!.bearing).absoluteValue > 20.0) {
2.seconds
} else {
2.seconds
1.seconds
}
return cameraDuration
}
@@ -286,7 +287,7 @@ class SurfaceRenderer(
bearing = bearing,
zoom = zoom,
tilt = 0.0,
padding = getPaddingValues(width, height, preview),
padding = getPaddingValues(height, preview),
target = target
)
)

View File

@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="48dp"
android:height="48dp"
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M190,840L160,810L480,80L800,810L770,840L480,708L190,840ZM258,742L480,644L702,742L480,228L258,742ZM480,644L480,644L480,644L480,644Z"/>
</vector>

View File

@@ -17,8 +17,6 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="back_caps_action_title" msgid="6392829425035919422">"ZURÜCK"</string>
<string name="home_caps_action_title" msgid="4853167242566949502">"STARTSEITE"</string>
<string name="exit_action_title" msgid="9086586388884500731">"Beenden"</string>
<string name="refresh_action_title" msgid="3674260822403151377">"Aktualisieren"</string>
<string name="close_action_title" msgid="2661907510124308560">"Schließen"</string>
@@ -28,7 +26,6 @@
<string name="stop_action_title" msgid="1187619482795416314">"Stopp"</string>
<string name="more_action_title" msgid="1039516575011403837">"Mehr"</string>
<string name="call_action_title" msgid="6218977436905001611">"Anrufen"</string>
<string name="primary_action_title" msgid="7042003552215710683">"Primär"</string>
<string name="options_action_title" msgid="1168121856107932984">"Optionen"</string>
<string name="search_action_title" msgid="3483459674263446335">"Suchen"</string>
<string name="checked_action_title" msgid="906023941445896399">"Aktiviert"</string>
@@ -42,7 +39,6 @@
<string name="throw_action_title" msgid="7163710562670220163">"Auslösen"</string>
<string name="commute_action_title" msgid="2585755255290185096">"Arbeitsweg"</string>
<string name="sign_out_action_title" msgid="1653943000866713010">"Abmelden"</string>
<string name="try_anyway_action_title" msgid="7384500054249311718">"Trotzdem versuchen"</string>
<string name="yes_action_title" msgid="5507096013762092189">"Ja"</string>
<string name="no_action_title" msgid="1452124604210014010">"Nein"</string>
<string name="disable_all_rows" msgid="3003225080532928046">"Alle Zeilen deaktivieren"</string>
@@ -77,7 +73,6 @@
<string name="car_hardware_demo_title" msgid="3679106197233262689">"Demo der Auto-Hardware"</string>
<string name="car_hardware_info" msgid="1244783247616395012">"Informationen zur Auto-Hardware"</string>
<string name="model_info" msgid="494224423025683030">"Modellinformationen"</string>
<string name="no_model_permission" msgid="5333629877014978947">"Keine Berechtigung für Modell"</string>
<string name="manufacturer_unavailable" msgid="4978995415869838056">"Hersteller nicht verfügbar"</string>
<string name="model_unavailable" msgid="4075463010215406573">"Modell nicht verfügbar"</string>
<string name="year_unavailable" msgid="994338773299644607">"Jahr nicht verfügbar"</string>

View File

@@ -17,8 +17,6 @@
<string name="app_name" translatable="false">Navigation</string>
<!-- Action Titles -->
<string name="back_caps_action_title">BACK</string>
<string name="home_caps_action_title">HOME</string>
<string name="exit_action_title">Exit</string>
<string name="refresh_action_title">Refresh</string>
<string name="close_action_title">Close</string>
@@ -28,7 +26,6 @@
<string name="stop_action_title">Stop</string>
<string name="more_action_title">More</string>
<string name="call_action_title">Call</string>
<string name="primary_action_title">Primary</string>
<string name="options_action_title">Options</string>
<string name="search_action_title">Search</string>
<string name="checked_action_title">Checked</string>
@@ -42,7 +39,6 @@
<string name="throw_action_title">Throw</string>
<string name="commute_action_title">Commute</string>
<string name="sign_out_action_title">Sign out</string>
<string name="try_anyway_action_title">Try Anyway</string>
<string name="yes_action_title">Yes</string>
<string name="no_action_title">No</string>
<string name="disable_all_rows">Disable All Rows</string>
@@ -87,7 +83,6 @@
<!-- CarHardwareInfoScreen -->
<string name="car_hardware_info">Car Hardware Information</string>
<string name="model_info">Model Information</string>
<string name="no_model_permission">No Model Permission</string>
<string name="manufacturer_unavailable">Manufacturer unavailable</string>
<string name="model_unavailable">Model unavailable</string>
<string name="year_unavailable">Year unavailable</string>

View File

@@ -2,6 +2,6 @@ package com.kouros.navigation.data
import androidx.compose.ui.graphics.Color
val NavigationColor = Color(0xFF094DB6)
val NavigationColor = Color(0xFF052086)
val RouteColor = Color(0xFF5582D0)

View File

@@ -3,6 +3,8 @@ package com.kouros.navigation.utils
import android.content.Context
import android.location.Location
import android.location.LocationManager
import android.os.Build
import androidx.annotation.RequiresApi
import androidx.core.content.edit
import com.kouros.navigation.data.Constants.MAXIMAL_ROUTE_DEVIATION
import com.kouros.navigation.data.Constants.SHARED_PREF_KEY
@@ -43,6 +45,7 @@ object NavigationUtils {
.getBoolean(key, false)
}
@RequiresApi(Build.VERSION_CODES.GINGERBREAD)
fun setBooleanKeyValue(context: Context, `val`: Boolean, key: String) {
context
.getSharedPreferences(
@@ -64,6 +67,11 @@ object NavigationUtils {
val point = pointFeature.geometry() as Point
newLocation.latitude = point.latitude()
newLocation.longitude = point.longitude()
newLocation.speed = location.speed
newLocation.bearing = location.bearing
newLocation.time = location.time
newLocation.accuracy = location.accuracy
newLocation.altitude = location.altitude
}
return newLocation
}