fix(ui): status bar layout and icons for Map, Dashboard, Manage
- Dashboard: apply background before statusBarsPadding so gradient extends under status bar - Map: add statusBarsPadding to layer selector so it no longer overlaps status bar - NavGraph: set white status bar icons (isAppearanceLightStatusBars=false) on main tab screens Made-with: Cursor
This commit is contained in:
@@ -7,27 +7,28 @@ import androidx.compose.foundation.layout.fillMaxSize
|
|||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.statusBarsPadding
|
||||||
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
import androidx.compose.foundation.verticalScroll
|
||||||
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.runtime.setValue
|
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Brush
|
import androidx.compose.ui.graphics.Brush
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
import org.db3.airmq.R
|
import org.db3.airmq.R
|
||||||
import org.db3.airmq.features.common.MockScreenScaffold
|
|
||||||
import org.db3.airmq.features.common.metric.MetricGaugeRow
|
|
||||||
import org.db3.airmq.features.common.metric.SensorType
|
|
||||||
import org.db3.airmq.features.common.ScreenAction
|
|
||||||
import org.db3.airmq.features.common.chart.AirMQChart
|
import org.db3.airmq.features.common.chart.AirMQChart
|
||||||
import org.db3.airmq.features.common.chart.ChartConfig
|
import org.db3.airmq.features.common.metric.MetricGaugePager
|
||||||
import org.db3.airmq.features.common.chart.ChartDataset
|
import org.db3.airmq.features.common.metric.SensorType
|
||||||
import org.db3.airmq.features.common.chart.generateSineWaveData
|
import org.db3.airmq.ui.theme.AirMQTheme
|
||||||
import org.db3.airmq.ui.theme.ChartBackground
|
|
||||||
import org.db3.airmq.ui.theme.ChartFill
|
|
||||||
import org.db3.airmq.ui.theme.LegacyNavGradientEnd
|
import org.db3.airmq.ui.theme.LegacyNavGradientEnd
|
||||||
import org.db3.airmq.ui.theme.LegacyNavGradientStart
|
import org.db3.airmq.ui.theme.LegacyNavGradientStart
|
||||||
|
|
||||||
@@ -38,13 +39,26 @@ fun DashboardScreen(
|
|||||||
onOpenCity: () -> Unit,
|
onOpenCity: () -> Unit,
|
||||||
onOpenDevice: () -> Unit,
|
onOpenDevice: () -> Unit,
|
||||||
onOpenNews: () -> Unit,
|
onOpenNews: () -> Unit,
|
||||||
onOpenWidgetConstructor: () -> Unit
|
onOpenWidgetConstructor: () -> Unit,
|
||||||
|
viewModel: DashboardViewModel = hiltViewModel()
|
||||||
|
) {
|
||||||
|
val state by viewModel.uiState.collectAsState()
|
||||||
|
DashboardContent(
|
||||||
|
state = state,
|
||||||
|
onEvent = viewModel::onEvent
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
internal fun DashboardContent(
|
||||||
|
state: DashboardScreenContract.State,
|
||||||
|
onEvent: (DashboardScreenContract.Event) -> Unit
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.verticalScroll(rememberScrollState())
|
||||||
) {
|
) {
|
||||||
MockScreenScaffold(
|
|
||||||
title = stringResource(id = R.string.title_dashboard),
|
|
||||||
subtitle = stringResource(id = R.string.dashboard_subtitle),
|
|
||||||
content = {
|
|
||||||
var selectedSensor by remember { mutableStateOf<SensorType?>(SensorType.DUST) }
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
@@ -53,16 +67,16 @@ fun DashboardScreen(
|
|||||||
colors = listOf(LegacyNavGradientStart, LegacyNavGradientEnd)
|
colors = listOf(LegacyNavGradientStart, LegacyNavGradientEnd)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
.statusBarsPadding()
|
||||||
) {
|
) {
|
||||||
MetricGaugeRow(
|
CitySelector(city = state.city, modifier = Modifier.padding(top = 12.dp))
|
||||||
selectedSensor = selectedSensor,
|
MetricGaugePager(
|
||||||
values = mapOf(
|
selectedSensor = state.selectedSensor,
|
||||||
SensorType.DUST to 6f,
|
values = state.gaugeValues,
|
||||||
SensorType.RADIOACTIVITY to 0f,
|
currentPage = state.currentPage,
|
||||||
SensorType.TEMPERATURE to 3f
|
onGaugeSelected = { onEvent(DashboardScreenContract.Event.GaugeSelected(it)) },
|
||||||
),
|
onPageChanged = { onEvent(DashboardScreenContract.Event.PageChanged(it)) },
|
||||||
onGaugeSelected = { selectedSensor = it },
|
modifier = Modifier.fillMaxWidth()
|
||||||
modifier = Modifier.padding(vertical = 8.dp)
|
|
||||||
)
|
)
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@@ -70,25 +84,60 @@ fun DashboardScreen(
|
|||||||
.height(144.dp)
|
.height(144.dp)
|
||||||
) {
|
) {
|
||||||
AirMQChart(
|
AirMQChart(
|
||||||
data = ChartDataset.Single(generateSineWaveData()),
|
data = state.chartData,
|
||||||
config = ChartConfig(
|
config = state.chartConfig.copy(
|
||||||
lineColor = Color.White,
|
|
||||||
fillColor = ChartFill,
|
|
||||||
backgroundColor = ChartBackground,
|
|
||||||
labelColor = Color.White,
|
|
||||||
leftTimeLabel = stringResource(R.string.text_yesterday),
|
leftTimeLabel = stringResource(R.string.text_yesterday),
|
||||||
rightTimeLabel = stringResource(R.string.text_now),
|
rightTimeLabel = stringResource(R.string.text_now)
|
||||||
unit = "°C"
|
|
||||||
),
|
),
|
||||||
sensorType = "sensor_temperature",
|
sensorType = state.selectedSensor.legacyKey,
|
||||||
modifier = Modifier.fillMaxSize()
|
modifier = Modifier.fillMaxSize()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
actions = listOf(
|
}
|
||||||
ScreenAction(stringResource(id = R.string.dashboard_open_news), onOpenNews),
|
|
||||||
ScreenAction(stringResource(id = R.string.manage_open_widget_constructor), onOpenWidgetConstructor)
|
@Composable
|
||||||
)
|
private fun CitySelector(
|
||||||
|
city: String,
|
||||||
|
modifier: Modifier = Modifier
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
modifier = modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(44.dp),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = city,
|
||||||
|
color = Color.White,
|
||||||
|
fontSize = 22.sp,
|
||||||
|
fontWeight = FontWeight.Medium
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview(showBackground = true, name = "Dashboard – dust selected")
|
||||||
|
@Composable
|
||||||
|
private fun PreviewDashboardDust() {
|
||||||
|
AirMQTheme {
|
||||||
|
DashboardContent(
|
||||||
|
state = DashboardScreenContract.previewState(selectedSensor = SensorType.DUST),
|
||||||
|
onEvent = {}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview(showBackground = true, name = "Dashboard – page 2 humidity")
|
||||||
|
@Composable
|
||||||
|
private fun PreviewDashboardPage2() {
|
||||||
|
AirMQTheme {
|
||||||
|
DashboardContent(
|
||||||
|
state = DashboardScreenContract.previewState(
|
||||||
|
selectedSensor = SensorType.HUMIDITY,
|
||||||
|
currentPage = 1
|
||||||
|
),
|
||||||
|
onEvent = {}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import androidx.compose.foundation.background
|
|||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.statusBarsPadding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.DisposableEffect
|
import androidx.compose.runtime.DisposableEffect
|
||||||
@@ -116,6 +117,7 @@ private fun MapScreenContent(
|
|||||||
},
|
},
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.align(Alignment.TopEnd)
|
.align(Alignment.TopEnd)
|
||||||
|
.statusBarsPadding()
|
||||||
.padding(top = 20.dp, end = 16.dp)
|
.padding(top = 20.dp, end = 16.dp)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
package org.db3.airmq.features.navigation
|
package org.db3.airmq.features.navigation
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.WindowInsets
|
import androidx.compose.foundation.layout.WindowInsets
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.SideEffect
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.material3.NavigationBar
|
import androidx.compose.material3.NavigationBar
|
||||||
import androidx.compose.material3.NavigationBarItem
|
import androidx.compose.material3.NavigationBarItem
|
||||||
@@ -13,6 +15,7 @@ import androidx.compose.material3.NavigationBarItemDefaults
|
|||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.platform.LocalView
|
||||||
import androidx.compose.ui.graphics.Brush
|
import androidx.compose.ui.graphics.Brush
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
@@ -25,6 +28,7 @@ import androidx.navigation.compose.composable
|
|||||||
import androidx.navigation.compose.currentBackStackEntryAsState
|
import androidx.navigation.compose.currentBackStackEntryAsState
|
||||||
import androidx.navigation.compose.rememberNavController
|
import androidx.navigation.compose.rememberNavController
|
||||||
import androidx.navigation.navArgument
|
import androidx.navigation.navArgument
|
||||||
|
import androidx.core.view.WindowCompat
|
||||||
import org.db3.airmq.R
|
import org.db3.airmq.R
|
||||||
import org.db3.airmq.features.city.CityScreen
|
import org.db3.airmq.features.city.CityScreen
|
||||||
import org.db3.airmq.features.constructor.ChartConstructorScreen
|
import org.db3.airmq.features.constructor.ChartConstructorScreen
|
||||||
@@ -64,6 +68,12 @@ fun AirMQNavGraph(modifier: Modifier = Modifier) {
|
|||||||
val currentRoute = navBackStackEntry?.destination?.route
|
val currentRoute = navBackStackEntry?.destination?.route
|
||||||
val showBottomBar = currentRoute in tabRoutes
|
val showBottomBar = currentRoute in tabRoutes
|
||||||
|
|
||||||
|
val view = LocalView.current
|
||||||
|
SideEffect {
|
||||||
|
val window = (view.context as? Activity)?.window ?: return@SideEffect
|
||||||
|
WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = !showBottomBar
|
||||||
|
}
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
contentWindowInsets = WindowInsets(0, 0, 0, 0),
|
contentWindowInsets = WindowInsets(0, 0, 0, 0),
|
||||||
|
|||||||
Reference in New Issue
Block a user